diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 000000000..5b85299a6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,41 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + + + +## Summary + +One paragraph explanation of the feature. + +## Motivation + +Why are we doing this? What use cases does it support? What is the expected outcome? + +## Describe alternatives you've considered + +A clear and concise description of the alternative solutions you've considered. Be sure to explain why Atom's existing customizability isn't suitable for this feature. + +## Additional context + +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..293c66c18 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,46 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + + + +### Prerequisites + +* [ ] Put an X between the brackets on this line if you have done all of the following: + * Reproduced the problem in Safe Mode: https://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode + * Followed all applicable steps in the debugging guide: https://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 + +[Description of the issue] + +### Steps to Reproduce + +1. [First Step] +2. [Second Step] +3. [and so on...] + +**Expected behavior:** [What you expect to happen] + +**Actual behavior:** [What actually happens] + +**Reproduces how often:** [What percentage of the time does it reproduce?] + +### Versions + +You can get this information from copy and pasting the output of `atom --version` and `apm --version` from the command line. Also, please include the OS and what version of the OS you're running. + +### Additional Information + +Any additional information, configuration or data that might be necessary to reproduce the issue. diff --git a/.github/lock.yml b/.github/lock.yml new file mode 100644 index 000000000..39319ee90 --- /dev/null +++ b/.github/lock.yml @@ -0,0 +1,17 @@ +# Configuration for lock-threads - https://github.com/dessant/lock-threads + +# Number of days of inactivity before a closed issue or pull request is locked +daysUntilLock: 180 +# Comment to post before locking. Set to `false` to disable +lockComment: > + This issue has been automatically locked since there has not been + any recent activity after it was closed. If you can still reproduce this issue in + [Safe Mode](https://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode) + then please open a new issue and fill out + [the entire issue template](https://github.com/atom/atom/blob/master/ISSUE_TEMPLATE.md) + to ensure that we have enough information to address your issue. Thanks! +# Issues or pull requests with these labels will not be locked +exemptLabels: + - help-wanted +# Limit to only `issues` or `pulls` +only: issues diff --git a/.github/move.yml b/.github/move.yml new file mode 100644 index 000000000..e69de29bb diff --git a/.travis.yml b/.travis.yml index e127aa499..f5a6ae3a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ matrix: include: - os: linux dist: trusty - env: NODE_VERSION=6.9.4 DISPLAY=:99.0 CC=clang CXX=clang++ npm_config_clang=1 + env: NODE_VERSION=8.9.3 DISPLAY=:99.0 CC=clang CXX=clang++ npm_config_clang=1 sudo: required @@ -27,7 +27,7 @@ install: - source /tmp/.nvm/nvm.sh - nvm install $NODE_VERSION - nvm use --delete-prefix $NODE_VERSION - - npm install -g npm@5.3.0 + - npm install --global npm@6.2.0 - script/build --create-debian-package --create-rpm-package --compress-artifacts script: diff --git a/README.md b/README.md index b0d8a6504..ee936527d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png) -[![macOS Build Status](https://circleci.com/gh/atom/atom/tree/master.svg?style=shield)](https://circleci.com/gh/atom/atom) [![Linux Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) +[![Build status](https://github.visualstudio.com/Atom/_apis/build/status/Atom%20Production%20Branches?branch=master)](https://github.visualstudio.com/Atom/_build/latest?definitionId=32&branch=master) [![Linux Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) [![Join the Atom Community on Slack](https://atom-slack.herokuapp.com/badge.svg)](https://atom-slack.herokuapp.com) @@ -65,7 +65,6 @@ repeat these steps to upgrade to future releases. ## Building -* [FreeBSD](./docs/build-instructions/freebsd.md) * [Linux](https://flight-manual.atom.io/hacking-atom/sections/hacking-on-atom-core/#platform-linux) * [macOS](https://flight-manual.atom.io/hacking-atom/sections/hacking-on-atom-core/#platform-mac) * [Windows](https://flight-manual.atom.io/hacking-atom/sections/hacking-on-atom-core/#platform-windows) diff --git a/apm/package-lock.json b/apm/package-lock.json new file mode 100644 index 000000000..eb521d46d --- /dev/null +++ b/apm/package-lock.json @@ -0,0 +1,4522 @@ +{ + "name": "atom-bundled-apm", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "atom-package-manager": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atom-package-manager/-/atom-package-manager-2.1.1.tgz", + "integrity": "sha512-pHRL1p1XQVNY/qpKgnlG0+nYfU9rAr2GC1BWg1M/s0cuN1IVvF5+vbyXY2Us/hdgJV9cwfWJLvHbB0ogzhmEHA==", + "requires": { + "asar-require": "0.3.0", + "async": "~0.2.8", + "colors": "~0.6.1", + "first-mate": "6.2.0", + "fs-plus": "2.x", + "git-utils": "^4.0", + "hosted-git-info": "^2.1.4", + "keytar": "^4.0", + "mv": "2.0.0", + "ncp": "~0.5.1", + "node-gyp": "3.4.0", + "npm": "6.2.0", + "open": "0.0.5", + "plist": "git+https://github.com/nathansobo/node-plist.git#bd3a93387f1d4b2cff819b200870d35465796e77", + "q": "~0.9.7", + "read": "~1.0.5", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "season": "^6.0.2", + "semver": "^5.1.0", + "tar": "^2.2.1", + "temp": "^0.8.3", + "underscore-plus": "1.x", + "wordwrap": "0.0.2", + "wrench": "~1.5.1", + "yargs": "^3.23.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "array-index": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz", + "integrity": "sha1-7FanSe4QPk4Ix5C5w1PfFgVbl/k=", + "requires": { + "debug": "^2.2.0", + "es6-symbol": "^3.0.2" + }, + "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-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "asar": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/asar/-/asar-0.12.1.tgz", + "integrity": "sha1-35Q+jrXNdPvKBmPi10uPK3J7UI8=", + "requires": { + "chromium-pickle-js": "^0.1.0", + "commander": "^2.9.0", + "cuint": "^0.2.1", + "glob": "^6.0.4", + "minimatch": "^3.0.0", + "mkdirp": "^0.5.0", + "mksnapshot": "^0.3.0", + "tmp": "0.0.28" + } + }, + "asar-require": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/asar-require/-/asar-require-0.3.0.tgz", + "integrity": "sha1-R+TLRBSJSthplTbNDFjAySFRtFs=", + "requires": { + "asar": "0.12.1" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "~2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "chromium-pickle-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.1.0.tgz", + "integrity": "sha1-HUixB9ghJqLz4hHC6iX4A7pVGyE=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "coffee-script": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.9.0.tgz", + "integrity": "sha1-dJLLvD8DYcxdiGWv9yN1Uv8z4fc=" + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cson-parser": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-1.0.9.tgz", + "integrity": "sha1-t5/BuCp3V0NoDw7/uL+tMRNNrHQ=", + "requires": { + "coffee-script": "1.9.0" + } + }, + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=" + }, + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "requires": { + "es5-ext": "~0.10.2" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "decompress-zip": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.0.tgz", + "integrity": "sha1-rjvLfjTGWHmt/nfhnDD4ZgK0vbA=", + "requires": { + "binary": "^0.3.0", + "graceful-fs": "^4.1.3", + "mkpath": "^0.1.0", + "nopt": "^3.0.1", + "q": "^1.1.2", + "readable-stream": "^1.1.8", + "touch": "0.0.3" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + } + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "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" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "es5-ext": { + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "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": { + "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.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=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-iterator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "integrity": "sha1-1vWLjE/EE8JJtLqhl2j45NfIlE4=", + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.5", + "es6-symbol": "~2.0.1" + } + }, + "es6-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "integrity": "sha1-dhtcZ8/U8dGK+yNPaR1nhoLLO/M=", + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.5" + } + }, + "es6-weak-map": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", + "integrity": "sha1-cGzvnpmqI2undmwjnIueKG6n0ig=", + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.6", + "es6-iterator": "~0.1.3", + "es6-symbol": "~2.0.1" + } + }, + "event-kit": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/event-kit/-/event-kit-1.5.0.tgz", + "integrity": "sha1-Ek72qtgyjcsmtxxHWQtbjmPrxIc=", + "requires": { + "grim": "^1.2.1" + } + }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "first-mate": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/first-mate/-/first-mate-6.2.0.tgz", + "integrity": "sha1-lSnK5evqVkC03DxD7ViMWzUoVa8=", + "requires": { + "emissary": "^1", + "event-kit": "^1.0.0", + "fs-plus": "^2", + "grim": "^1.2.1", + "oniguruma": "^6.1.0", + "season": "^5.0.2", + "underscore-plus": "^1" + }, + "dependencies": { + "season": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/season/-/season-5.4.1.tgz", + "integrity": "sha1-S9baYVKn8tbwixQzzi2SBmmFPQ0=", + "requires": { + "cson-parser": "1.0.9", + "fs-plus": "2.x", + "optimist": "~0.4.0" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "fs-plus": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-2.10.1.tgz", + "integrity": "sha1-MgR4HXhAYR5jZOe2+wWMljJ8WqU=", + "requires": { + "async": "^1.5.2", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.2", + "underscore-plus": "1.x" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "git-utils": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/git-utils/-/git-utils-4.1.4.tgz", + "integrity": "sha1-uS0x9h/LTHNvSngxTeNuQbn8fWg=", + "requires": { + "fs-plus": "^2.1.0", + "nan": "^2.0.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "grim": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/grim/-/grim-1.5.0.tgz", + "integrity": "sha1-sysI71Z88YUvgXWe2caLDXE5ajI=", + "requires": { + "emissary": "^1.2.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "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-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keytar": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-4.2.1.tgz", + "integrity": "sha1-igamV3/fY3PgqmsRInfmPex3/RI=", + "requires": { + "nan": "2.8.0", + "prebuild-install": "^2.4.1" + }, + "dependencies": { + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=" + } + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "requires": { + "mime-db": "~1.36.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "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": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mkpath": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz", + "integrity": "sha1-dVSm+Nhxg0zJe1RisSLEwSTW3pE=" + }, + "mksnapshot": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/mksnapshot/-/mksnapshot-0.3.1.tgz", + "integrity": "sha1-JQHAVldDbXQs6Vik/5LHfkDdN+Y=", + "requires": { + "decompress-zip": "0.3.0", + "fs-extra": "0.26.7", + "request": "^2.79.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "mv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.0.0.tgz", + "integrity": "sha1-jn7CtRh8hHFNd8jpg7HtKdejOhs=", + "requires": { + "mkdirp": "~0.3.5", + "ncp": "~0.4.2", + "rimraf": "~2.2.6" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" + }, + "ncp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=" + }, + "rimraf": { + "version": "2.2.8", + "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "nan": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz", + "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==" + }, + "ncp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz", + "integrity": "sha1-dDmFMW49tFkoG1hxaehFc1oFQ58=" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "node-abi": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz", + "integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==", + "requires": { + "semver": "^5.4.1" + } + }, + "node-gyp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.4.0.tgz", + "integrity": "sha1-3aVYOTs+y74kyea4cDxxGUxj+jY=", + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3", + "osenv": "0", + "path-array": "^1.0.0", + "request": "2", + "rimraf": "2", + "semver": "2.x || 3.x || 4 || 5", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "gauge": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.6.0.tgz", + "integrity": "sha1-01MBrRjpaQK0dR3LvkD0IYuUKkY=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-color": "^0.1.7", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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" + } + }, + "npmlog": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-3.1.2.tgz", + "integrity": "sha1-LUb6h0M3r5SYovErtD2NC+SjaHM=", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.6.0", + "set-blocking": "~2.0.0" + } + } + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "npm": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.2.0.tgz", + "integrity": "sha512-GnlNsOnxwVJX4WSfyQY0gY3LnUX2cc46XU0eu1g+WSuZgDRUGmw8tuptitJu6byp0RWGT8ZEAKajblwdhQHN8A==", + "requires": { + "JSONStream": "^1.3.3", + "abbrev": "~1.1.1", + "ansicolors": "~0.3.2", + "ansistyles": "~0.1.3", + "aproba": "~1.2.0", + "archy": "~1.0.0", + "bin-links": "^1.1.2", + "bluebird": "~3.5.1", + "byte-size": "^4.0.3", + "cacache": "^11.0.2", + "call-limit": "~1.1.0", + "chownr": "~1.0.1", + "cli-columns": "^3.1.2", + "cli-table3": "^0.5.0", + "cmd-shim": "~2.0.2", + "columnify": "~1.5.4", + "config-chain": "~1.1.11", + "debuglog": "*", + "detect-indent": "~5.0.0", + "detect-newline": "^2.1.0", + "dezalgo": "~1.0.3", + "editor": "~1.0.0", + "figgy-pudding": "^3.1.0", + "find-npm-prefix": "^1.0.2", + "fs-vacuum": "~1.2.10", + "fs-write-stream-atomic": "~1.0.10", + "gentle-fs": "^2.0.1", + "glob": "~7.1.2", + "graceful-fs": "~4.1.11", + "has-unicode": "~2.0.1", + "hosted-git-info": "^2.6.0", + "iferr": "^1.0.0", + "imurmurhash": "*", + "inflight": "~1.0.6", + "inherits": "~2.0.3", + "ini": "^1.3.5", + "init-package-json": "^1.10.3", + "is-cidr": "^2.0.6", + "json-parse-better-errors": "^1.0.2", + "lazy-property": "~1.0.0", + "libcipm": "^2.0.0", + "libnpmhook": "^4.0.1", + "libnpx": "^10.2.0", + "lock-verify": "^2.0.2", + "lockfile": "^1.0.4", + "lodash._baseindexof": "*", + "lodash._baseuniq": "~4.6.0", + "lodash._bindcallback": "*", + "lodash._cacheindexof": "*", + "lodash._createcache": "*", + "lodash._getnative": "*", + "lodash.clonedeep": "~4.5.0", + "lodash.restparam": "*", + "lodash.union": "~4.6.0", + "lodash.uniq": "~4.5.0", + "lodash.without": "~4.4.0", + "lru-cache": "^4.1.3", + "meant": "~1.0.1", + "mississippi": "^3.0.0", + "mkdirp": "~0.5.1", + "move-concurrently": "^1.0.1", + "node-gyp": "^3.7.0", + "nopt": "~4.0.1", + "normalize-package-data": "~2.4.0", + "npm-audit-report": "^1.3.1", + "npm-cache-filename": "~1.0.2", + "npm-install-checks": "~3.0.0", + "npm-lifecycle": "^2.0.3", + "npm-package-arg": "^6.1.0", + "npm-packlist": "~1.1.10", + "npm-pick-manifest": "^2.1.0", + "npm-profile": "^3.0.2", + "npm-registry-client": "^8.5.1", + "npm-registry-fetch": "^1.1.0", + "npm-user-validate": "~1.0.0", + "npmlog": "~4.1.2", + "once": "~1.4.0", + "opener": "~1.4.3", + "osenv": "^0.1.5", + "pacote": "^8.1.6", + "path-is-inside": "~1.0.2", + "promise-inflight": "~1.0.1", + "qrcode-terminal": "^0.12.0", + "query-string": "^6.1.0", + "qw": "~1.0.1", + "read": "~1.0.7", + "read-cmd-shim": "~1.0.1", + "read-installed": "~4.0.3", + "read-package-json": "^2.0.13", + "read-package-tree": "^5.2.1", + "readable-stream": "^2.3.6", + "readdir-scoped-modules": "*", + "request": "^2.81.0", + "retry": "^0.12.0", + "rimraf": "~2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.5.0", + "sha": "~2.0.1", + "slide": "~1.1.6", + "sorted-object": "~2.0.1", + "sorted-union-stream": "~2.1.3", + "ssri": "^6.0.0", + "tar": "^4.4.4", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "uid-number": "0.0.6", + "umask": "~1.1.0", + "unique-filename": "~1.1.0", + "unpipe": "~1.0.0", + "update-notifier": "^2.5.0", + "uuid": "^3.3.2", + "validate-npm-package-license": "^3.0.3", + "validate-npm-package-name": "~3.0.0", + "which": "^1.3.1", + "worker-farm": "^1.6.0", + "wrappy": "~1.0.2", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "JSONStream": { + "version": "1.3.3", + "bundled": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.4.1", + "bundled": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "ansi-align": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.0.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansicolors": { + "version": "0.3.2", + "bundled": true + }, + "ansistyles": { + "version": "0.1.3", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "asap": { + "version": "2.0.6", + "bundled": true + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.7.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bin-links": { + "version": "1.1.2", + "bundled": true, + "requires": { + "bluebird": "^3.5.0", + "cmd-shim": "^2.0.2", + "gentle-fs": "^2.0.0", + "graceful-fs": "^4.1.11", + "write-file-atomic": "^2.3.0" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.5.1", + "bundled": true + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.x.x" + } + }, + "boxen": { + "version": "1.3.0", + "bundled": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.0.0", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "builtins": { + "version": "1.0.3", + "bundled": true + }, + "byline": { + "version": "5.0.0", + "bundled": true + }, + "byte-size": { + "version": "4.0.3", + "bundled": true + }, + "cacache": { + "version": "11.0.2", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "figgy-pudding": "^3.1.0", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.0", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "call-limit": { + "version": "1.1.0", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.1", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true + }, + "ci-info": { + "version": "1.1.3", + "bundled": true + }, + "cidr-regex": { + "version": "2.0.9", + "bundled": true, + "requires": { + "ip-regex": "^2.1.0" + } + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, + "cli-columns": { + "version": "3.1.2", + "bundled": true, + "requires": { + "string-width": "^2.0.0", + "strip-ansi": "^3.0.1" + } + }, + "cli-table3": { + "version": "0.5.0", + "bundled": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "bundled": true + }, + "cmd-shim": { + "version": "2.0.2", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "mkdirp": "~0.5.0" + } + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "^1.1.1" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.0", + "bundled": true, + "optional": true + }, + "columnify": { + "version": "1.5.4", + "bundled": true, + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + } + }, + "combined-stream": { + "version": "1.0.6", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "concat-stream": { + "version": "1.6.2", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "bundled": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "configstore": { + "version": "3.1.2", + "bundled": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "copy-concurrently": { + "version": "1.0.5", + "bundled": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.x.x" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + }, + "cyclist": { + "version": "0.2.2", + "bundled": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "bundled": true + } + } + }, + "debuglog": { + "version": "1.0.1", + "bundled": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "requires": { + "clone": "^1.0.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "dezalgo": { + "version": "1.0.3", + "bundled": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "bundled": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "dotenv": { + "version": "5.0.1", + "bundled": true + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "duplexify": { + "version": "3.6.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } + }, + "editor": { + "version": "1.0.0", + "bundled": true + }, + "encoding": { + "version": "0.1.12", + "bundled": true, + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "err-code": { + "version": "1.1.2", + "bundled": true + }, + "errno": { + "version": "0.1.7", + "bundled": true, + "requires": { + "prr": "~1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "bundled": true + }, + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "figgy-pudding": { + "version": "3.1.0", + "bundled": true + }, + "find-npm-prefix": { + "version": "1.0.2", + "bundled": true + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "from2": { + "version": "2.3.0", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs-vacuum": { + "version": "1.2.10", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "path-is-inside": "^1.0.1", + "rimraf": "^2.5.2" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "genfun": { + "version": "4.0.1", + "bundled": true + }, + "gentle-fs": { + "version": "2.0.1", + "bundled": true, + "requires": { + "aproba": "^1.1.2", + "fs-vacuum": "^1.2.10", + "graceful-fs": "^4.1.11", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "path-is-inside": "^1.0.2", + "read-cmd-shim": "^1.0.1", + "slide": "^1.1.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": 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" + } + }, + "global-dirs": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ini": "^1.3.4" + } + }, + "got": { + "version": "6.7.1", + "bundled": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "hosted-git-info": { + "version": "2.6.0", + "bundled": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "bundled": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "bundled": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "bundled": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "iferr": { + "version": "1.0.0", + "bundled": true + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", + "bundled": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "init-package-json": { + "version": "1.10.3", + "bundled": true, + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "ip": { + "version": "1.1.5", + "bundled": true + }, + "ip-regex": { + "version": "2.1.0", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-ci": { + "version": "1.1.0", + "bundled": true, + "requires": { + "ci-info": "^1.0.0" + } + }, + "is-cidr": { + "version": "2.0.6", + "bundled": true, + "requires": { + "cidr-regex": "^2.0.8" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "bundled": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "is-obj": { + "version": "1.0.1", + "bundled": true + }, + "is-path-inside": { + "version": "1.0.1", + "bundled": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "bundled": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "latest-version": { + "version": "3.1.0", + "bundled": true, + "requires": { + "package-json": "^4.0.0" + } + }, + "lazy-property": { + "version": "1.0.0", + "bundled": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "libcipm": { + "version": "2.0.0", + "bundled": true, + "requires": { + "bin-links": "^1.1.2", + "bluebird": "^3.5.1", + "find-npm-prefix": "^1.0.2", + "graceful-fs": "^4.1.11", + "lock-verify": "^2.0.2", + "npm-lifecycle": "^2.0.3", + "npm-logical-tree": "^1.2.1", + "npm-package-arg": "^6.1.0", + "pacote": "^8.1.6", + "protoduck": "^5.0.0", + "read-package-json": "^2.0.13", + "rimraf": "^2.6.2", + "worker-farm": "^1.6.0" + } + }, + "libnpmhook": { + "version": "4.0.1", + "bundled": true, + "requires": { + "figgy-pudding": "^3.1.0", + "npm-registry-fetch": "^3.0.0" + }, + "dependencies": { + "npm-registry-fetch": { + "version": "3.1.1", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^3.1.0", + "lru-cache": "^4.1.2", + "make-fetch-happen": "^4.0.0", + "npm-package-arg": "^6.0.0" + } + } + } + }, + "libnpx": { + "version": "10.2.0", + "bundled": true, + "requires": { + "dotenv": "^5.0.1", + "npm-package-arg": "^6.0.0", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.0", + "update-notifier": "^2.3.0", + "which": "^1.3.0", + "y18n": "^4.0.0", + "yargs": "^11.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lock-verify": { + "version": "2.0.2", + "bundled": true, + "requires": { + "npm-package-arg": "^5.1.2 || 6", + "semver": "^5.4.1" + } + }, + "lockfile": { + "version": "1.0.4", + "bundled": true, + "requires": { + "signal-exit": "^3.0.2" + } + }, + "lodash._baseindexof": { + "version": "3.1.0", + "bundled": true + }, + "lodash._baseuniq": { + "version": "4.6.0", + "bundled": true, + "requires": { + "lodash._createset": "~4.0.0", + "lodash._root": "~3.0.0" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "bundled": true + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "bundled": true + }, + "lodash._createcache": { + "version": "3.1.2", + "bundled": true, + "requires": { + "lodash._getnative": "^3.0.0" + } + }, + "lodash._createset": { + "version": "4.0.3", + "bundled": true + }, + "lodash._getnative": { + "version": "3.9.1", + "bundled": true + }, + "lodash._root": { + "version": "3.0.1", + "bundled": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "bundled": true + }, + "lodash.restparam": { + "version": "3.6.1", + "bundled": true + }, + "lodash.union": { + "version": "4.6.0", + "bundled": true + }, + "lodash.uniq": { + "version": "4.5.0", + "bundled": true + }, + "lodash.without": { + "version": "4.4.0", + "bundled": true + }, + "lowercase-keys": { + "version": "1.0.1", + "bundled": true + }, + "lru-cache": { + "version": "4.1.3", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "bundled": true, + "requires": { + "pify": "^3.0.0" + } + }, + "make-fetch-happen": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^11.0.1", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + } + }, + "meant": { + "version": "1.0.1", + "bundled": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mime-db": { + "version": "1.33.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.18", + "bundled": true, + "requires": { + "mime-db": "~1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.3", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mississippi": { + "version": "3.0.0", + "bundled": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "bundled": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "mute-stream": { + "version": "0.0.7", + "bundled": true + }, + "node-fetch-npm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-gyp": { + "version": "3.7.0", + "bundled": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": ">=2.9.0 <2.82.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + } + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-audit-report": { + "version": "1.3.1", + "bundled": true, + "requires": { + "cli-table3": "^0.5.0", + "console-control-strings": "^1.1.0" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true + }, + "npm-cache-filename": { + "version": "1.0.2", + "bundled": true + }, + "npm-install-checks": { + "version": "3.0.0", + "bundled": true, + "requires": { + "semver": "^2.3.0 || 3.x || 4 || 5" + } + }, + "npm-lifecycle": { + "version": "2.0.3", + "bundled": true, + "requires": { + "byline": "^5.0.0", + "graceful-fs": "^4.1.11", + "node-gyp": "^3.6.2", + "resolve-from": "^4.0.0", + "slide": "^1.1.6", + "uid-number": "0.0.6", + "umask": "^1.1.0", + "which": "^1.3.0" + } + }, + "npm-logical-tree": { + "version": "1.2.1", + "bundled": true + }, + "npm-package-arg": { + "version": "6.1.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.6.0", + "osenv": "^0.1.5", + "semver": "^5.5.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "2.1.0", + "bundled": true, + "requires": { + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, + "npm-profile": { + "version": "3.0.2", + "bundled": true, + "requires": { + "aproba": "^1.1.2 || 2", + "make-fetch-happen": "^2.5.0 || 3 || 4" + } + }, + "npm-registry-client": { + "version": "8.5.1", + "bundled": true, + "requires": { + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", + "npmlog": "2 || ^3.1.0 || ^4.0.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "safe-buffer": "^5.1.1", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3", + "ssri": "^5.2.4" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.1" + } + } + } + }, + "npm-registry-fetch": { + "version": "1.1.0", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^2.0.1", + "lru-cache": "^4.1.2", + "make-fetch-happen": "^3.0.0", + "npm-package-arg": "^6.0.0", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "cacache": { + "version": "10.0.4", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + }, + "dependencies": { + "mississippi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + } + } + }, + "figgy-pudding": { + "version": "2.0.1", + "bundled": true + }, + "make-fetch-happen": { + "version": "3.0.0", + "bundled": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^10.0.4", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.0", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^3.0.1", + "ssri": "^5.2.4" + } + }, + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "smart-buffer": { + "version": "1.1.15", + "bundled": true + }, + "socks": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ip": "^1.1.4", + "smart-buffer": "^1.0.13" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "bundled": true, + "requires": { + "agent-base": "^4.1.0", + "socks": "^1.1.10" + } + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.1" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-user-validate": { + "version": "1.0.0", + "bundled": true + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.4.3", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "package-json": { + "version": "4.0.1", + "bundled": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "pacote": { + "version": "8.1.6", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "cacache": "^11.0.2", + "get-stream": "^3.0.0", + "glob": "^7.1.2", + "lru-cache": "^4.1.3", + "make-fetch-happen": "^4.0.1", + "minimatch": "^3.0.4", + "minipass": "^2.3.3", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.10", + "npm-pick-manifest": "^2.1.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.0", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.5.0", + "ssri": "^6.0.0", + "tar": "^4.4.3", + "unique-filename": "^1.1.0", + "which": "^1.3.0" + } + }, + "parallel-transform": { + "version": "1.1.0", + "bundled": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-is-inside": { + "version": "1.0.2", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "pify": { + "version": "3.0.0", + "bundled": true + }, + "prepend-http": { + "version": "1.0.4", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true + }, + "promise-retry": { + "version": "1.1.1", + "bundled": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + } + } + }, + "promzard": { + "version": "0.3.0", + "bundled": true, + "requires": { + "read": "1" + } + }, + "proto-list": { + "version": "1.2.4", + "bundled": true + }, + "protoduck": { + "version": "5.0.0", + "bundled": true, + "requires": { + "genfun": "^4.0.1" + } + }, + "prr": { + "version": "1.0.1", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "bundled": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "query-string": { + "version": "6.1.0", + "bundled": true, + "requires": { + "decode-uri-component": "^0.2.0", + "strict-uri-encode": "^2.0.0" + } + }, + "qw": { + "version": "1.0.1", + "bundled": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "read": { + "version": "1.0.7", + "bundled": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-installed": { + "version": "4.0.3", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "^4.1.2", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + } + }, + "read-package-json": { + "version": "2.0.13", + "bundled": true, + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "slash": "^1.0.0" + } + }, + "read-package-tree": { + "version": "5.2.1", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "once": "^1.3.0", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "bundled": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "requires": { + "rc": "^1.0.1" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve-from": { + "version": "4.0.0", + "bundled": true + }, + "retry": { + "version": "0.12.0", + "bundled": true + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + }, + "run-queue": { + "version": "1.0.3", + "bundled": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "semver-diff": { + "version": "2.1.0", + "bundled": true, + "requires": { + "semver": "^5.0.3" + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "sha": { + "version": "2.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "readable-stream": "^2.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "slash": { + "version": "1.0.0", + "bundled": true + }, + "slide": { + "version": "1.1.6", + "bundled": true + }, + "smart-buffer": { + "version": "4.0.1", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.x.x" + } + }, + "socks": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + } + }, + "sorted-object": { + "version": "2.0.1", + "bundled": true + }, + "sorted-union-stream": { + "version": "2.1.3", + "bundled": true, + "requires": { + "from2": "^1.3.0", + "stream-iterate": "^1.1.0" + }, + "dependencies": { + "from2": { + "version": "1.3.0", + "bundled": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~1.1.10" + } + }, + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.1.14", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + }, + "sshpk": { + "version": "1.14.2", + "bundled": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "ssri": { + "version": "6.0.0", + "bundled": true + }, + "stream-each": { + "version": "1.2.2", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-iterate": { + "version": "1.2.0", + "bundled": true, + "requires": { + "readable-stream": "^2.1.5", + "stream-shift": "^1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "bundled": true + }, + "strict-uri-encode": { + "version": "2.0.0", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringstream": { + "version": "0.0.6", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "supports-color": { + "version": "5.4.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tar": { + "version": "4.4.4", + "bundled": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.3", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "term-size": { + "version": "1.2.0", + "bundled": true, + "requires": { + "execa": "^0.7.0" + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true + }, + "through": { + "version": "2.3.8", + "bundled": true + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.3.4", + "bundled": true, + "requires": { + "punycode": "^1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "bundled": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "umask": { + "version": "1.1.0", + "bundled": true + }, + "unique-filename": { + "version": "1.1.0", + "bundled": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "bundled": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "bundled": true + }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, + "update-notifier": { + "version": "2.5.0", + "bundled": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "util-extend": { + "version": "1.0.3", + "bundled": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "bundled": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "^1.0.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1" + } + }, + "worker-farm": { + "version": "1.6.0", + "bundled": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.3.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "11.0.0", + "bundled": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + }, + "dependencies": { + "y18n": { + "version": "3.2.1", + "bundled": true + } + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.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=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "oniguruma": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/oniguruma/-/oniguruma-6.2.1.tgz", + "integrity": "sha1-pQ7mlkKEStHSUmhaqxhxcbBuzgQ=", + "requires": { + "nan": "^2.0.9" + } + }, + "open": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=" + }, + "optimist": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.4.0.tgz", + "integrity": "sha1-y47Dfy/jqphky2eidSUOfhliCiU=", + "requires": { + "wordwrap": "~0.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://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=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-array": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-array/-/path-array-1.0.1.tgz", + "integrity": "sha1-fi8PNfB6IBUSK4aLfqwOssT+wnE=", + "requires": { + "array-index": "^1.0.0" + } + }, + "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=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "plist": { + "version": "git+https://github.com/nathansobo/node-plist.git#bd3a93387f1d4b2cff819b200870d35465796e77", + "from": "git+https://github.com/nathansobo/node-plist.git", + "requires": { + "xmlbuilder": "0.4.x", + "xmldom": "0.1.x" + } + }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^1.0.2", + "github-from-package": "0.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "node-abi": "^2.2.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "os-homedir": "^1.0.1", + "pump": "^2.0.1", + "rc": "^1.1.6", + "simple-get": "^2.7.0", + "tar-fs": "^1.13.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "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" + } + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "season": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/season/-/season-6.0.2.tgz", + "integrity": "sha1-naWPsd3SSCTXYhstxjpxI7UCF7Y=", + "requires": { + "cson-parser": "^1.3.0", + "fs-plus": "^3.0.0", + "yargs": "^3.23.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==" + }, + "cson-parser": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-1.3.5.tgz", + "integrity": "sha1-fsZ14DkUVTO/KmqFYHPxWZ2cLSQ=", + "requires": { + "coffee-script": "^1.10.0" + } + }, + "fs-plus": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.0.2.tgz", + "integrity": "sha1-a19Sp3EolMTd6f2PgfqMYN8EHz0=", + "requires": { + "async": "^1.5.2", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.2", + "underscore-plus": "1.x" + } + } + } + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.1.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "^1.0.0", + "rimraf": "~2.2.6" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "tmp": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz", + "integrity": "sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA=", + "requires": { + "os-tmpdir": "~1.0.1" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "touch": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", + "integrity": "sha1-Ua7z1ElXHU8oel2Hyci0kYGg2x0=", + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1" + } + } + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "underscore-plus": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.6.8.tgz", + "integrity": "sha512-88PrCeMKeAAC1L4xjSiiZ3Fg6kZOYrLpLGVPPeqKq/662DfQe/KTSKdSR/Q/tucKNnfW2MNAUGSCkDf8HmXC5Q==", + "requires": { + "underscore": "~1.8.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "wrench": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/wrench/-/wrench-1.5.9.tgz", + "integrity": "sha1-QRaRxjqbJTGxcAJnJ5veyiOyFCo=" + }, + "xmlbuilder": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-0.4.3.tgz", + "integrity": "sha1-xGFLp04K0ZbmCcknLNnh3bKKilg=" + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + } + } + } + } +} diff --git a/apm/package.json b/apm/package.json index 90093b3d4..a6a2fd19d 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.19.0" + "atom-package-manager": "2.1.1" } } diff --git a/appveyor.yml b/appveyor.yml index c7f2d3f9e..7e5c07b10 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,6 +10,7 @@ branches: only: - master - /^[0-9.]+-releases$/ + - /^electron-[0-9.]+$/ platform: - x64 @@ -19,7 +20,7 @@ environment: global: ATOM_DEV_RESOURCE_PATH: c:\projects\atom TEST_JUNIT_XML_ROOT: c:\projects\junit-test-results - NODE_VERSION: 6.9.4 + NODE_VERSION: 8.9.3 matrix: - TASK: test @@ -35,19 +36,22 @@ install: - IF NOT EXIST %TEST_JUNIT_XML_ROOT% MKDIR %TEST_JUNIT_XML_ROOT% - SET PATH=C:\Program Files\Atom\resources\cli;%PATH% - ps: Install-Product node $env:NODE_VERSION $env:PLATFORM - - npm install -g npm@5.3.0 + - npm install --global npm@6.2.0 build_script: - CD %APPVEYOR_BUILD_FOLDER% - IF NOT EXIST C:\tmp MKDIR C:\tmp - SET SQUIRREL_TEMP=C:\tmp + - IF [%APPVEYOR_REPO_BRANCH:~-9%]==[-releases] SET IS_RELEASE_BRANCH=true + - IF [%APPVEYOR_REPO_BRANCH%]==[master] IF NOT DEFINED APPVEYOR_PULL_REQUEST_NUMBER SET IS_SIGNED_ZIP_BRANCH=true + - IF [%APPVEYOR_REPO_BRANCH:~0,9%]==[electron-] SET IS_SIGNED_ZIP_BRANCH=true - IF [%TASK%]==[installer] ( - IF [%APPVEYOR_REPO_BRANCH:~-9%]==[-releases] ( + IF [%IS_RELEASE_BRANCH%]==[true] ( ECHO Building on release branch - Creating production artifacts && script\build.cmd --code-sign --compress-artifacts --create-windows-installer ) ELSE ( - IF [%APPVEYOR_REPO_BRANCH%]==[master] IF NOT DEFINED APPVEYOR_PULL_REQUEST_NUMBER ( - ECHO Building on master branch - Creating signed zips && + IF [%IS_SIGNED_ZIP_BRANCH%]==[true] ( + ECHO Building on %APPVEYOR_REPO_BRANCH% branch - Creating signed zips && script\build.cmd --code-sign --compress-artifacts ) ELSE ( ECHO Skipping installer build for non-release/non-master branch @@ -74,6 +78,12 @@ artifacts: name: atom-windows.zip - path: out\RELEASES name: RELEASES + - path: out\AtomSetup-x64.exe + name: AtomSetup-x64.exe + - path: out\atom-x64-windows.zip + name: atom-x64-windows.zip + - path: out\RELEASES-x64 + name: RELEASES-x64 - path: out\atom-*-delta.nupkg name: atom-delta.nupkg - path: out\atom-*-full.nupkg diff --git a/atom.sh b/atom.sh index cd28dd334..935204bfc 100755 --- a/atom.sh +++ b/atom.sh @@ -13,6 +13,9 @@ case $(basename $0) in atom-beta) CHANNEL=beta ;; + atom-nightly) + CHANNEL=nightly + ;; atom-dev) CHANNEL=dev ;; @@ -59,6 +62,9 @@ if [ $REDIRECT_STDERR ]; then exec 2> /dev/null fi +ATOM_HOME="${ATOM_HOME:-$HOME/.atom}" +mkdir -p "$ATOM_HOME" + if [ $OS == 'Mac' ]; then if [ -L "$0" ]; then SCRIPT="$(readlink "$0")" @@ -73,10 +79,20 @@ if [ $OS == 'Mac' ]; then ATOM_APP_NAME="$(basename "$ATOM_APP")" fi - if [ "$CHANNEL" == 'beta' ]; then - ATOM_EXECUTABLE_NAME="Atom Beta" + if [ ! -z "${ATOM_APP_NAME}" ]; then + # If ATOM_APP_NAME is known, use it as the executable name + ATOM_EXECUTABLE_NAME="${ATOM_APP_NAME%.*}" else - ATOM_EXECUTABLE_NAME="Atom" + # Else choose it from the inferred channel name + if [ "$CHANNEL" == 'beta' ]; then + ATOM_EXECUTABLE_NAME="Atom Beta" + elif [ "$CHANNEL" == 'nightly' ]; then + ATOM_EXECUTABLE_NAME="Atom Nightly" + elif [ "$CHANNEL" == 'dev' ]; then + ATOM_EXECUTABLE_NAME="Atom Dev" + else + ATOM_EXECUTABLE_NAME="Atom" + fi fi if [ -z "${ATOM_PATH}" ]; then @@ -111,6 +127,9 @@ elif [ $OS == 'Linux' ]; then beta) ATOM_PATH="$USR_DIRECTORY/share/atom-beta/atom" ;; + nightly) + ATOM_PATH="$USR_DIRECTORY/share/atom-nightly/atom" + ;; dev) ATOM_PATH="$USR_DIRECTORY/share/atom-dev/atom" ;; @@ -119,9 +138,6 @@ elif [ $OS == 'Linux' ]; then ;; esac - ATOM_HOME="${ATOM_HOME:-$HOME/.atom}" - mkdir -p "$ATOM_HOME" - : ${TMPDIR:=/tmp} [ -x "$ATOM_PATH" ] || ATOM_PATH="$TMPDIR/atom-build/Atom/atom" @@ -146,8 +162,20 @@ on_die() { } trap 'on_die' SIGQUIT SIGTERM -# If the wait flag is set, don't exit this process until Atom tells it to. +# If the wait flag is set, don't exit this process until Atom kills it. if [ $WAIT ]; then + WAIT_FIFO="$ATOM_HOME/.wait_fifo" + + if [ ! -p "$WAIT_FIFO" ]; then + rm -f "$WAIT_FIFO" + mkfifo "$WAIT_FIFO" + fi + + # Block endlessly by reading from a named pipe. + exec 2>/dev/null + read < "$WAIT_FIFO" + + # If the read completes for some reason, fall back to sleeping in a loop. while true; do sleep 1 done diff --git a/circle.yml b/circle.yml deleted file mode 100644 index b5791e7ad..000000000 --- a/circle.yml +++ /dev/null @@ -1,45 +0,0 @@ -machine: - environment: - XCODE_SCHEME: test - XCODE_WORKSPACE: test - XCODE_PROJECT: test - TEST_JUNIT_XML_ROOT: ${CIRCLE_TEST_REPORTS} - - xcode: - version: 7.3 - -general: - artifacts: - - out/atom-mac.zip - - out/atom-mac-symbols.zip - - docs/output/atom-api.json - -dependencies: - pre: - - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash - - nvm install 6.9.4 - - nvm use 6.9.4 - - npm install -g npm@5.3.0 - - override: - - script/build --code-sign --compress-artifacts - - cache_directories: - - electron - - apm/node_modules - - script/node_modules - - node_modules - - ~/.atom/compile-cache - - ~/.atom/snapshot-cache - -test: - override: - - script/lint - - osascript -e 'tell application "System Events" to keystroke "x"' # clear screen saver - - caffeinate -s script/test # Run with caffeinate to prevent screen saver - -experimental: - notify: - branches: - only: - - master diff --git a/docs/README.md b/docs/README.md index c45e117e4..094bc6e5b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,7 +8,6 @@ Most of the Atom user and developer documentation is contained in the [Atom Flig Instructions for building Atom on various platforms from source. -* [FreeBSD](./build-instructions/freebsd.md) * Moved to [the Flight Manual](https://flight-manual.atom.io/hacking-atom/sections/hacking-on-atom-core/) * Linux * macOS diff --git a/docs/build-instructions/build-status.md b/docs/build-instructions/build-status.md index 9bc806e88..a6f7fdfd6 100644 --- a/docs/build-instructions/build-status.md +++ b/docs/build-instructions/build-status.md @@ -1,8 +1,8 @@ # Atom build status -| System | Travis | AppVeyor/Win | Circle/Mac | Dependencies | +| System | Travis | AppVeyor/Win | VSTS | Dependencies | |--------|--------|--------------|------------|--------------| -| [Atom](https://github.com/atom/atom) | [![Travis Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) | [![AppVeyor/Wi Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) | [![Circle/Mac Build Status](https://circleci.com/gh/atom/atom.svg?style=shield)](https://circleci.com/gh/atom/atom) | [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) | +| [Atom](https://github.com/atom/atom) | [![Travis Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) | [![AppVeyor/Wi Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) | [![Build status](https://github.visualstudio.com/Atom/_apis/build/status/Atom%20Production%20Branches?branch=master)](https://github.visualstudio.com/Atom/_build/latest?definitionId=32&branch=master) | [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) | | [APM](https://github.com/atom/apm) | [![Travis Build Status](https://travis-ci.org/atom/apm.svg?branch=master)](https://travis-ci.org/atom/apm) | [![AppVeyor/Wi Build Status](https://ci.appveyor.com/api/projects/status/j6ixw374a397ugkb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/apm/branch/master) | | [![Dependency Status](https://david-dm.org/atom/apm.svg)](https://david-dm.org/atom/apm) | | [Electron](https://github.com/electron/electron) | [![Travis Build Status](https://travis-ci.org/electron/electron.svg?branch=master)](https://travis-ci.org/electron/electron) | [![AppVeyor/Wi Build Status](https://ci.appveyor.com/api/projects/status/kvxe4byi7jcxbe26/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/electron) | | [![Dependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron) diff --git a/docs/build-instructions/freebsd.md b/docs/build-instructions/freebsd.md deleted file mode 100644 index ab07ff529..000000000 --- a/docs/build-instructions/freebsd.md +++ /dev/null @@ -1,19 +0,0 @@ -# FreeBSD - -FreeBSD -RELEASE 64-bit is the recommended platform. - -## Requirements - -* FreeBSD -* `pkg install node` -* `pkg install npm` -* `pkg install libgnome-keyring` -* `npm config set python /usr/local/bin/python2 -g` to ensure that gyp uses Python 2 - -## Instructions - -```sh -git clone https://github.com/atom/atom -cd atom -script/build -``` diff --git a/docs/focus/2018-02-12.md b/docs/focus/2018-02-12.md deleted file mode 100644 index 345543a9b..000000000 --- a/docs/focus/2018-02-12.md +++ /dev/null @@ -1,55 +0,0 @@ -## Highlights from the past week - -- Atom IDE - - Started conversion of atom-languageclient to TypeScript [atom/atom-languageclient#175](https://github.com/atom/atom-languageclient/pull/175) -- @atom/watcher - - Report events related to [symlinks](https://github.com/atom/watcher/pull/111) and [test for symlink-related edge cases.](https://github.com/atom/watcher/pull/114) - - Produce filesystem events with a [consistent parent path](https://github.com/atom/watcher/pull/113) to the one used to create a watcher, even if the watcher was created with a a path containing symlinks. - - Verified correct behavior with regard to [filesystem case sensitivity.](https://github.com/atom/watcher/pull/116) - - Corrected buggy [utf8 to utf16 conversion](https://github.com/atom/watcher/pull/115) on Windows. - - Ran through the MacOS cases in the [testing matrix.](https://github.com/atom/atom/pull/16124) - - Set up a Samba share on @ungb's testing server to exercise Samba network drives. - - Published version 1.0.0 on [npm.](https://www.npmjs.com/package/@atom/watcher) -- GitHub Package - - Introduce a package configuration option to [disable the in-editor merge conflict resolution.](https://github.com/atom/github/pull/1305) - - Published a new release v0.10.0 - - Investigated and spiked on a fix for amending bug in single-commit repos, which was surfaced by failing cache invalidation tests that were blocking release - - Deferred fixing underlying bug - [atom/github#1303](https://github.com/atom/github/issues/1303) - - Fixed failing tests - [atom/github#1302](https://github.com/atom/github/pull/1302) -- Teletype - - Released [Teletype 0.7.0](https://github.com/atom/teletype/releases/tag/v0.7.0) with improved diagnostics for errors that occur during package initialization ([atom/teletype#266](https://github.com/atom/teletype/issues/266), [atom/teletype#297](https://github.com/atom/teletype/issues/297)) - - Opened [atom/teletype#323](https://github.com/atom/teletype/pull/323), [atom/teletype-client#52](https://github.com/atom/teletype-client/pull/52), and [atom/fuzzy-finder#335](https://github.com/atom/fuzzy-finder/pull/335) to pave the way for guests to use the fuzzy-finder to open any remote editor shared by the host ([atom/teletype#268](https://github.com/atom/teletype/issues/268)) - -## Focus for week ahead - -- Atom IDE - - Finish conversion of atom-languageclient to TypeScript [atom/atom-languageclient#175](https://github.com/atom/atom-languageclient/pull/175) - - Contribute TypeScript type definitions for Atom IDE to [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) - - Contribute missing TypeScript type defintions for Atom to [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/atom) -- @atom/watcher - - Complete [the testing matrix](https://github.com/atom/atom/pull/16124) on Linux and Windows. - - :shipit: Merge [@atom/watcher support]((https://github.com/atom/atom/pull/16124)) into Atom _(as a non-default `PathWatcher` backend)_. :shipit: -- GitHub Package - - Quarterly planning. Which might change all of these :wink: - - Finish tracking down our [freezing CI builds.](https://github.com/atom/github/pull/1289) - - Resurrect the [gargantuan credential helper and GPG pinentry refactoring PR](https://github.com/atom/github/pull/846) and see how much work is needed to get it over the finish line. - - Fix issue with diff view popping up unexpectedly - [atom/github#1287](https://github.com/atom/github/issues/1287) -- Teletype - - Complete initial implementation and merge pull requests ([atom/teletype#323](https://github.com/atom/teletype/pull/323), [atom/teletype-client#52](https://github.com/atom/teletype-client/pull/52), and [atom/fuzzy-finder#335](https://github.com/atom/fuzzy-finder/pull/335)) allowing guests to use the fuzzy-finder to open any remote editor shared by the host ([atom/teletype#268](https://github.com/atom/teletype/issues/268)) - - Use fuzzy-finder support internally in our day-to-day workflows to assess usability -- Tree-sitter - - Finish and merge [tree-sitter/tree-sitter#128](https://github.com/tree-sitter/tree-sitter/pull/128), which fixes a fundamental performance problem when editing large files. - - Fix syntax highlighting bugs [#16643](https://github.com/atom/atom/issues/16643) and [#16642](https://github.com/atom/atom/issues/16642). - - Fix [#16621](https://github.com/atom/atom/issues/16621) - snippets not working when using Tree-sitter. -- Xray - * @nathansobo (and @as-cii part time) will be focusing the next 12 weeks on a prototype for [a new Electron-based text editor](https://github.com/atom/xray). The goal is to explore the viability of radical performance improvements that could be possible if we make breaking changes to Atom's APIs. At the end of the 12 weeks, we will reassess our plans based on what we have managed to learn and accomplish. - * Week 1 of 12 - * Clarify and document goals for the next 12 weeks. - * Ensure that the guide matches our current plans. - * Refine WebGL based text rendering. - * Make sure ASCII text renders correctly without being clipped - * Render text correctly on high DPI displays - * Use correct API for texture atlas updates - * Add mouse-wheel scrolling support - * Non-ASCII rendering, using the HarfBuzz text shaping library to detect combining characters - * Stretch goal: Switch document encoding to UTF-8 for memory compactness and support multi-byte-aware character indexing. diff --git a/docs/focus/2018-02-19.md b/docs/focus/2018-02-19.md deleted file mode 100644 index 9bc89628a..000000000 --- a/docs/focus/2018-02-19.md +++ /dev/null @@ -1,51 +0,0 @@ -## Highlights from the past week - -- Atom IDE - - Converted atom-languageclient to TypeScript - - ide-typescript updated to use TypeScript 2.7.2 - - Published updates to ide-typescript, ide-json, and ide-csharp to improve language server stability -- @atom/watcher - - Gracefully handle the situation where a network share with a watch root is disconnected ([#119](https://github.com/atom/watcher/pull/119)) - - Merged into Atom master behind a feature flag ([#16124](https://github.com/atom/atom/pull/16124)) just after the 1.24.0 / 1.25.0-beta0 release - - Fixed a crash when messages are sent to the worker thread before it's properly initialized ([atom/watcher#121](https://github.com/atom/watcher/pull/121)) -- GitHub Package - - Investigate intermittently freezing tests on Travis in [atom/github#1289](https://github.com/atom/github/pull/1289). Not much luck so far - - Fixed issue with diff views popping up unexpectedly [atom/github#1311](https://github.com/atom/github/pull/1311). Just waiting on review -- Teletype - - Fixed an unanticipated bug that would cause non-existent selections to appear in the editor of other participants ([atom/teletype#326](https://github.com/atom/teletype/pull/326)). - - Published [version 0.8.0](https://github.com/atom/teletype/releases/tag/v0.8.0). - - Refactored teletype-client and simplified how added/removed editors are broadcasted to participants ([atom/teletype-client#52](https://github.com/atom/teletype-client/pull/52)). - - Polished the design of fuzzy-finder ([atom/fuzzy-finder#335](https://github.com/atom/fuzzy-finder/pull/335)) - - Pushed [atom/teletype#323](https://github.com/atom/teletype/pull/323) over the finish line. -- Xray - - We made a slight change of plans and decided to spend more time clarifying the overall vision for the project. - - We have a [branch](https://github.com/atom/xray/tree/roadmap) with a new README that matches our current thinking, but the Q1 roadmap is still in progress. - - We did manage to get text rendering with retina displays and non-clipped characters, but there's still work to do. We are also experimenting populating our glyph atlas with up to 4 variants of each glyph at different subpixel positions to more closely match text rendered purely on the CPU. -- Tree-sitter - - Took some time to fix unrelated regressions from the bug-bash month - - Fixed a bug where atom --wait did not work correctly on Windows (#16740) - - Fixed a bug that prevented Atom from reusing an existing window when the same path was opened twice (#16764) - - Fixed regressions in the behavior of the atom.textEditors.getGrammarOverride and atom.grammars.loadGrammar methods (#16733, #16747) - - Fixed several syntax highlighting bugs (#16642, #16643) -## Focus for week ahead - -- Atom IDE - - Investigate new Atom IDE UI features for rename operations and workspace symbol search - - Publish TypeScript definitions for atom-ide/atom-languageclient to DefinitelyTyped - - Wire up atom-ide-ui console to LSP server logging -- @atom/watcher - - Diagnose and correct crashes and lock-ups as people report them -- GitHub Package - - Establish high-level goals and scope bounds for the GitHub side of the integration - - Document a protocol for the evolution of major features: ensure they contribute to a cohesive experience with the rest of the package, make sure that @simurai is looped in to the conversation, make sure the community has visibility to our goals - - Show recent commits in Git panel -- Teletype - - Merge and use [atom/fuzzy-finder#335](https://github.com/atom/fuzzy-finder/pull/335), [atom/teletype-client#52](https://github.com/atom/teletype-client/pull/52) and [atom/teletype#323](https://github.com/atom/teletype/pull/323). - - Publish Teletype v0.9.0 containing the new fuzzy-finder support. -- Tree-sitter - - Fix an issue where snippets are not available when using tree-sitter (#16621) - - Start work on optimizing editing in the presence of large parse errors (#16590) - - Start work on allowing parsing to take place on a background thread -- Xray - - We will continue clarifying the overall vision with a focus on real time collaboration. This may extend beyond the scope of Xray, but is important to get clarity on before comitting to a roadmap. - - We hope to iron out the remaining issues with subpixel-positioning of glyphs to more faithfully reproduce Chrome's behavior when rendering text via the normal DOM-based code path. diff --git a/docs/focus/2018-02-26.md b/docs/focus/2018-02-26.md deleted file mode 100644 index 4d1715442..000000000 --- a/docs/focus/2018-02-26.md +++ /dev/null @@ -1,43 +0,0 @@ -## Highlights from the past week - -- Atom IDE - - TypeScript conversion fully cleaned up, types ready for definitely typed - - Started work on AutoComplete rewrites to address poor filtering and over-eager pop-up - - Review of code actions integration (currently on ide-java) -- @atom/watcher -- GitHub Package - - Loads of [planning and process](https://github.com/atom/github/blob/master/docs/how-we-work.md) - - Recent commit history [RFC](https://github.com/atom/github/pull/1318) and [implementation](https://github.com/atom/github/pull/1322) - - Port another few components from Etch to React in preparation for :point_up: - - Wrestle with a few [flaky](https://github.com/atom/github/pull/1289) [tests](https://github.com/atom/github/pull/1320) to get our [build](https://github.com/atom/github/pull/1317) under control. -- Teletype -- Tree-sitter - - Finally wrote some documentation about Tree-sitter and how to develop parsers, now that members of the Atom community are starting to contribute to parsers. -- Xray - - We finished off some up-front planning around Xray's support for real time collaboration. - - We're now comfortably scrolling a dev-build of React at 60 frames per second. Frames are rendered in about 1.2ms per frame on our hardware, and rendering is looking identical to Chrome's CPU backend for basic ASCII text, modulo ligatures and kerning. We still have a lot of features to add, but we don't any of them will dramatically impact frame computation time. -- Reactor Duty - - Discovered root cause of Windows test failures in [atom/tree-view#1203](https://github.com/atom/tree-view/issues/1203), discussed in-progress fix with @50wliu - -## Focus for week ahead - -- Atom IDE - - Complete work on AutoComplete improvements - - Stop cancellations for autocomplete and outline throwing errors in the logs - - Investigate workspace symbol user interface -- @atom/watcher - - Diagnose crashes and lockups on Atom launch -- GitHub Package - - Recent commit implementation: land a [read-only view of the most recent commits](https://github.com/atom/github/pull/1322). - - Port [CommitViewController and CommitView to React](https://github.com/atom/github/pull/1325). - - Write up `docs/vision` from meeting notes. - - Begin on ["remember me"](https://github.com/atom/github/issues/861) for the git credential helper. -- Teletype -- Tree-sitter - - Optimizing syntax tree updates in the presence of syntax errors. This will improve performance across the board but also make Tree-sitter usable in edge cases where the wrong language is being used to parse a document. -- Xray - - @as-cii will be focused on more sophisticated text-shaping to extend our support beyond basic ASCII. We're working on a [glyph-renderer](https://github.com/atom/xray/tree/glyph-renderer) module that handles text layout and glyph rasterization. To support a standalone web-based component, we're starting with a WebAssembly module based on HarfBuzz and FreeType, but we can always explore using platform-specific frameworks for the Electron use case. - - @nathansobo will be focused on implementing selections. We're introducing a new "anchor" abstraction that creates a stable reference to a buffer location, along with methods for converting anchors to offsets or points. Each editor will store selections as a sorted array of anchor ranges. To move a selection, we'll convert its anchors to concrete points, adjust their rows/columns, then convert the points back to anchors. We're curious how long it will take us to do this for thousands of selections. Hopefully it's fast. Then we'll focus on inserting text inside the selections. -- Reactor Duty - - Investigate dock pane dragging regression [atom/atom#16769](https://github.com/atom/atom/issues/16769) - - Merge PR [atom/node-keytar#67](https://github.com/atom/node-keytar/pull/67) diff --git a/docs/focus/2018-03-05.md b/docs/focus/2018-03-05.md deleted file mode 100644 index 597db55f1..000000000 --- a/docs/focus/2018-03-05.md +++ /dev/null @@ -1,55 +0,0 @@ -## Highlights from the past week - -- Atom IDE - - Console logging started - - IDE-Java/PHP/TypeScript updates and fixes -- GitHub Package - - Recent commits view, read-only mode :tm: (@kuychaco, @smashwilson, @simurai) [#1322](https://github.com/atom/github/pull/1322) - - Recent commits view: show co-authors (@kuychaco, @simurai) - - Commit interactions research spike: undo most recent, amend (@kuychaco) [#1328](https://github.com/atom/github/pull/1328) - - Port CommitView and CommitController to React. (@smashwilson) [#1325](https://github.com/atom/github/pull/1325) - - Begin "Remember me" within the credential dialog [#1327](https://github.com/atom/github/pull/1327) -- Tree-sitter - - Shifted focus to address some open-source contributions to parsers: - - Wrote documentation about how to create parsers: http://tree-sitter.github.io/tree-sitter - - Fixed issues with the Bash parser - - Fixed a bug found during constant fuzzing by the security team: https://github.com/tree-sitter/tree-sitter/issues/133 -- Xray - - Decided not to run all text through HarfBuzz for performance reasons, and came up with a plan for addressing mandatory text shaping issues in the future. - - Implemented anchors, selections, and basic selection movement. - - Partially implemented selection rendering. - - For more details, see the [detailed update](https://github.com/atom/xray/blob/master/docs/updates/2018_03_05.md) in the Xray repository. -- Engineering Improvements - - Automated Linux package repository publishing as part of Atom release process -- Reactor Duty - - Shipped node-keytar update, primary feature being prebuilt node modules ([atom/node-keytar#67](https://github.com/atom/node-keytar/pull/67)) - - Merged community pull requests to atom/atom-select-list, atom/command-palette, and atom/tree-view - -## Focus for week ahead - -- Atom IDE - - Console logging completion - - Investigate language server process hanging on deactivation in ide-typescript - - Investigate using the new native LSP support in omnisharp-roslyn in ide-csharp -- @atom/watcher - - Diagnose crashes and lockups on Atom launch (@smashwilson) -- GitHub Package - - Finish "Remember me" within the credential dialog (@smashwilson) [#1327](https://github.com/atom/github/pull/1327) - - Write up `docs/vision` from meeting notes (@smashwilson) - - Kick-start our GPG pinentry handling (@smashwilson) [#846](https://github.com/atom/github/pull/846) - - Build UI for adding co-authors, much like Desktop's UI/UX - desktop.github.com/features/co-authors/ -- Teletype - - Open pull request for the avatar UX enhancements described in ([atom/teletype#268](https://github.com/atom/teletype/issues/268)) -- Tree-sitter - - Carrying over goals from previous weeks: - - Optimize syntax tree updates in the presence of syntax errors. This will improve performance across the board but also make Tree-sitter usable in edge cases where the wrong language is being used to parse a document. - - Start work on allowing parsing to take place on a background thread -- Xray - - Finish selection rendering - - Wire up enough of the key bindings / commands system to move cursors/selections - - Start on editing - - For more details, see [the detailed update](https://github.com/atom/xray/blob/master/docs/updates/2018_03_05.md) -- Engineering Improvements - - Finish new Atom release publishing automation -- Reactor Duty - diff --git a/docs/focus/README.md b/docs/focus/README.md index d12495479..e5cc0f538 100644 --- a/docs/focus/README.md +++ b/docs/focus/README.md @@ -2,154 +2,27 @@ Want to know what the Atom team is working on and what has our focus over the next few months? You've come to the right place. 🎯 -In this directory, you'll find **weekly progress and planning updates** from the core Atom team at GitHub (e.g., [`2018-02-12.md`](2018-02-12.md)), and the sections below represent our **near-term roadmap**: -* [Atom IDE](#atom-ide) -* [GitHub package](#github-package) -* [Teletype](#teletype) -* [Tree-sitter](#tree-sitter) -* [Xray](#xray) +This roadmap is a [living document](https://en.wikipedia.org/wiki/Living_document): it represents our current plans, but we expect these plans to change from time to time. Follow [this link](https://github.com/atom/atom/blob/4fbad81a7cd2f2e3925d7e920086bc1ebf2fe210/docs/focus/README.md) to see the previous major version of this roadmap. -This roadmap is a [living document](https://en.wikipedia.org/wiki/Living_document): it represents our current plans, but we expect these plans to change from time to time. +You can find our bi-weekly iteration plans by searching for issues with the [`iteration-plan`](https://github.com/atom/atom/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aiteration-plan) label. --- -# Atom IDE +### Core package development is streamlined +Everything in Atom is a package. While this adds to its hackability, it is not always the best path forward. Consolidating packages as well as thinking about other ways to decrease friction for contributors will help pay down some of our tech debt in this area. More information regarding planning was provided in [this RFC](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate-core-packages.md) -## Roadmap +- [ ] Merge at least 22 packages in to atom/atom -TODO -## Looking farther ahead +### Improve Communication and Process -TODO +- [ ] Refine process for triaging issues and PRs across Atom org repositories +- [ ] Publish a document that outlines merge requirements for community PRs +- [ ] Reactive tickets are incorporated in to 80% of all sprints +- [ ] Automate some aspects of Atom issue and PR triage with Probot, especially around ensuring PRs follow our contribution guidelines ---- +### Establish and Measure -# GitHub package - -Main repository: [atom/github](http://github.com/atom/github) (Atom package) - -## Roadmap - -Watch our progress on the [short-term roadmap project](https://github.com/atom/github/projects/8). - -##### Recent commit history - -_Near-term goal:_ An informational view that displays the most recent 1-3 commits beneath the mini commit message editor. Design and discussion in: [#554](https://github.com/atom/github/issues/554), [#86](https://github.com/atom/github/issues/86). - -_Longer-term goals:_ Introduce interactivity to the commits shown in the recent history list. Right-click on the top click to amend it, or on prior commits to reset. Overhaul the "amend button" functionality and implementation. - -##### Commit co-authoring - -_Near-term goal:_ Allow users to specify co-authors when committing. Draw inspiration from [Desktop's implementation](https://github.com/desktop/desktop/pull/3879) for UI. Tracking issue: [#1309](https://github.com/atom/github/issues/1309). - -_Longer-term goals:_ Expose an API so that packages like teletype can add portal participants to commits automatically. Tangentially related to [#1089](https://github.com/atom/github/issues/1089). - -##### Pull request workflow - Create Pull Request - -_Near-term goal:_ Add buttons in the GitHub panel to allow users to push any unpushed changes and open new pull requests. The "Open new pull request" button will link to the github.com compare view in browser. Open pull request: [#1138](https://github.com/atom/github/pull/1138). - -_Longer-term goals:_ Offer a complete in-editor experience. Compose pull request titles and descriptions in the GitHub dock item. However, we wish to avoid needing replicating the full .com experience, so to specify labels, projects, or milestones, we will preserve the "navigate browser to compare view" functionality, and focus on text composition. - -This will require building out UI in the GitHub panel and adding GraphQL API support to create pull requests. - -UI/UX considerations include: - -* Offer a pop-out editor to craft PR descriptions in a full pane, similar to the commit editor pop out. -* Allow the user to specify the merge target. -* Show a preview of the list of commits that would be introduced by PR. - -##### Build stability - -_Near-term goal:_ Fix that damn Travis hang documented in [#1119](https://github.com/atom/github/issues/1119). Resume the diagnosis work in [#1289](https://github.com/atom/github/pull/1289) and find a way to bring our build success rate back under control. - -##### GPG and credential handler overhaul - -_Near-term goals:_ Passphrase prompting from git credential helpers and GPG has been a significant pain point since public release; unsurprisingly, because those are the areas where we need to leverage binaries and configuration from the users' system if present. - -* Implement a "remember me" checkbox backed by keytar. This is probably our top feature request. [#861](https://github.com/atom/github/issues/861) - -_Longer-term goals:_ Finish the credential handler refactor begun in [#846](https://github.com/atom/github/pull/846) to handle GPG 1.x through 2.3 and include diagnostic logging and testing. - -* Improve our handling of 2FA credentials. Ideally we could detect when a user has 2FA enabled and prompt for a one-time code. [#844](https://github.com/atom/github/issues/844) - -## Looking farther ahead - -In no particular order: - -- Git Virtual File System support. -- Improved branch management. [#556](https://github.com/atom/github/issues/556) -- Introduce an overview dock item that summarizes and navigates to other functionality. [#1018](https://github.com/atom/github/issues/1018) -- Code review. [#269](https://github.com/atom/github/issues/269), [#268](https://github.com/atom/github/issues/268) -- `git log` pane. -- Merge or close pull requests. -- Browse and check out pull requests. - ---- - -# Teletype - -Main repository: [atom/teletype](http://github.com/atom/teletype) (Atom package) - -## Roadmap - -##### 1. Deliver a multi-file collaboration experience that meets 80% of the needs with 20% of the effort - -- Ship RFC-001 (https://github.com/atom/teletype/issues/268) - -##### 2. Streamline collaboration set-up - -Near-term goal: Encourage more collaboration by reducing barriers to entry. - -Longer-term goal: Provide the world's fastest transition from "I want to collaborate" to "I am collaborating." 🚀 - -- Publish RFC (including a request for review from GitHub's Community and Safety team) -- Host can share a URL for the portal, and guests can follow the URL to instantly join the portal (https://github.com/atom/teletype/issues/109) -- Quickly collaborate with coworkers and friends (https://github.com/atom/teletype/issues/213, https://github.com/atom/teletype/issues/284) - - You can view a list of past collaborators (i.e., a ["buddy list"](https://github.com/atom/teletype/issues/22) of sorts). - - You can choose any online person in the buddy list and invite them to join your portal. They get a notification (or similar) informing them of the invitation, and they can choose to join the portal or not. - - To prevent abuse/harassment, each time you join a portal via a URL or portal ID, Teletype adds the collaborators to your buddy list. You can directly invite anyone in your buddy list to join your portal, and anyone in your buddy list can invite you to a portal. You can remove anyone from your buddy list, at which point they can no longer _directly_ invite you to a portal. - -##### 3. Nice bang-for-the-buck refinements - -- Add a colored border around avatars that matches the cursor when that participant's tether is not retracted (https://github.com/atom/teletype/issues/338) - -##### 4. Prioritized bugs - -- Uncaught TypeError: Cannot match against 'undefined' or 'null' (https://github.com/atom/teletype/issues/233) - -## Looking farther ahead - -In no particular order: - -- 🐛 Resolve or reduce impact of package initialization errors (https://github.com/atom/teletype/issues/266) -- 🐛 Surface uncaught errors in promises (https://github.com/atom/teletype/issues/298#issuecomment-355369327) -- ✨ Ensure remote buffers are updated when host renames files (https://github.com/atom/teletype/issues/147) -- 💖 In the buddy list, you can see which people are currently online (i.e., presence) -- 💖 Screen-sharing -- (We should prioritize screen-sharing above audio. We can keep using Slack/Skype/Zoom/Whatever for audio and use Atom for screen-sharing, whereas the opposite is not true; disabling audio on a Slack call would feel unintuitive.) -- 💖 Audio - ---- - -# Tree-sitter - -## Roadmap - -TODO - -## Looking farther ahead - -TODO - ---- - -# Xray - -## Roadmap - -TODO - -## Looking farther ahead - -TODO +- [ ] Implement Atom metrics dashboard that can be used to drive future decisions +- [ ] Determine what may be helpful to measure in the future building upon work [already in progress](http://blog.atom.io/2018/06/20/atom-metrics.html) diff --git a/docs/rfcs/000-template.md b/docs/rfcs/000-template.md new file mode 100644 index 000000000..52e852159 --- /dev/null +++ b/docs/rfcs/000-template.md @@ -0,0 +1,37 @@ +# Feature title + +## Status + +Proposed + +## Summary + +One paragraph explanation of the feature. + +## Motivation + +Why are we doing this? What use cases does it support? What is the expected outcome? + +## Explanation + +Explain the proposal as if it was already implemented and you were describing it to an Atom user. That generally means: + +- Introducing new named concepts. +- Explaining the feature largely in terms of examples. +- Explaining any changes to existing workflows. + +## Drawbacks + +Why should we *not* do this? + +## Rationale and alternatives + +- Why is this approach the best in the space of possible approaches? +- What other approaches have been considered and what is the rationale for not choosing them? +- What is the impact of not doing this? + +## Unresolved questions + +- What unresolved questions do you expect to resolve through the RFC process before this gets merged? +- What unresolved questions do you expect to resolve through the implementation of this feature before it is released in a new version of Atom? +- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? diff --git a/docs/rfcs/001-updatable-bundled-packages.md b/docs/rfcs/001-updatable-bundled-packages.md new file mode 100644 index 000000000..dbf23b678 --- /dev/null +++ b/docs/rfcs/001-updatable-bundled-packages.md @@ -0,0 +1,105 @@ +# Updatable Bundled Packages + +## Status + +Proposed + +## Summary + +This feature will enable an opt-in subset of bundled Atom packages to be updated with `apm` outside of the Atom release cycle. This will enable users to receive new functionality and bug fixes for some bundled packages as regularly as needed without waiting for them to be included in a new Atom release. This is especially important for packages like [GitHub](https://github.com/atom/github/) and [Teletype](https://github.com/atom/teletype/) which provide essential Atom functionality and could be improved independently of Atom. + +## Motivation + +Atom currently uses a monthly release cycle with staged Stable and Beta releases so that major issues get caught early in Beta before reaching the Stable release. Because Atom releases updates monthly, this means that a new feature merged into `master` right after a new Atom release could take one month to reach the next Beta and then another month to reach Stable. + +Since a large part of Atom's built-in functionality is provided by bundled packages, it makes sense to allow some of those packages to be updated independently of Atom's monthly release cycle so that users can receive new features and fixes whenever they become available. + +Bundled packages are treated differently than community packages that you can install using `apm`: + +- You are not prompted to update them when new versions are released on `apm` +- `apm` will warn you at the command line when you try to install or update a bundled package +- If a user intentionally installs a bundled package from `apm` the [dalek package](https://github.com/atom/dalek/) will show a warning in the "deprecations" view asking the user to remove the offending package + +Despite all this, if the user *does* manually install an update to a bundled package using `apm`, it will be loaded into the editor and updated dutifully as new releases occur. The only new functionality needed is to enable `apm` to check bundled packages for updates when those packages haven't yet been installed in the user's `~/.atom/packages` folder. + +The primary use case for this improvement is enabling the GitHub package to ship improvements more frequently than Atom's release cycle since many of its improvements can be done without changes to Atom itself. If this approach is proven to work well for the GitHub package, we might also consider using it to ship Teletype as a bundled Atom package. + +## Explanation + +Any bundled Atom package can opt in to new updates released via `apm` by adding `"coreUpdatable": true` to its `package.json` file. This causes `apm` to consider it as part of the list of packages it checks for updates. If a community (non-bundled) package sets this field to `true` or `false` it will be ignored as it's only relevant to bundled packages. + +Atom shows update notifications for Updatable bundled packages whenever they are available so long as those updates support the engine version of the current Atom build. Bundled package updates can also be found and installed in the Settings view's *Updates* tab. + +The `dalek` package is aware of the new "Updatable" metadata and excludes updated bundled packages from its deprecation warnings. + +### User Experience Examples + +1. The user downloads and installs Atom 1.28.0 which includes GitHub package version 0.15.0. Two weeks later, GitHub package 0.16.0 is released with a few new features. The user is prompted to update to the new version and gets the new features even though Atom 1.29.0 hasn't been released yet. + +2. The user downloads and installs Atom 1.28.0, including GitHub package 0.15.0, which was released two weeks prior. Since that release the GitHub package has been updated to version 0.15.1 on `apm`. When the user starts Atom for the first time they are prompted to update the GitHub package. + +3. In the future, a user has an old install of Atom 1.28.0 and waits a long time between installing Atom updates. The GitHub package releases version 0.25.0 but the user is not prompted to install it because the GitHub package has set `engines` in `package.json` to restrict to Atom 1.32.0 and above. + +### Rules for Updatable Bundled Packages + +Any package that opts into this behavior must adhere to these rules: + +1. **Each release must ensure that its `engines` field in `package.json` reflects the necessary Atom version for the Atom, Electron, and Node.js APIs used in the package**. This field defines the range of Atom versions in which the package is expected to work. The field should always be set to the lowest possible Atom version that the package supports. + +2. **Any new update to a bundled package *must* support current Stable *and* Beta releases**. This enables the user to upgrade the package and continue to use it in side-by-side Stable and Beta installs on their machine. If a package wants to use API features of a newer version of Atom while still supporting older Atom versions, it must do so in a way that is aware of the user's version and adjust itself accordingly. + +3. **Atom's `package.json` *must* stay up to date with the latest supported version of the package** in the `master` and Beta release branches. This ensures that the user always gets the latest version of the package in a new release and also benefits from its inclusion in Atom's snapshot. + +For rule #3, it will be important to have automation to ensure that current Beta release and `master` are kept up to date with the latest compatible version of any updatable bundled package as it will be difficult for maintainers to do that manually. This could be accomplished by a nightly CI run which is focused explicitly on bumping package dependencies in this manner. + +## Drawbacks + +### Possible API incompatibility + +The primary drawback of this approach is that Updatable bundled packages might exhibit problems on older Atom versions due to missing or changed APIs in Atom, Electron, or Node.js. The solution for these packages is to keep their `engines` field updated appropriately, but there's still a chance that some updates will slip through without the necessary engine version changes. If this does occur and users are affected by it, the solution is to publish a new update which rolls back the package to the functionality of its previous release and then publish another new update with the new functionality restored and the proper `engines` version in place. + +### Increased Atom startup time + +Another major drawback is that the snapshotted code for the bundled package will no longer be used since a newer version has been installed. This updated version of the package cannot be easily added back into Atom's snapshot so it could cause a noticable drag on Atom's startup time. Some quick measurements with Timecop show a 10x increase in GitHub package load time for bundled (snapshot) vs updated (non-snapshot) package code: + +| GitHub Package Code | Load Time | +|----------------------------------|-----------| +| **Bundled** | 52 ms | +| **Updated (first load)** | 5026 ms | +| **Updated (subsequent loads)** | 591 ms | + +There was no measurable effect on shell or window startup time, only package load time. It seems that the transpilation phase of the first load of the package incurs a 100x increase in load time. Pre-transpilation of the package code (either when shipped or when installed using `apm`) will be useful in mitigating this cost. Further investigation into snapshotting package code will be needed to understand if the load time increase can be mitigated. + +There is a possibility that the GitHub package could load parts of its codebase on demand to mitigate the increased startup time when not loaded as part of Atom's snapshot. This approach is discussed in more detail at [atom/github#1522](https://github.com/atom/github/issues/1522). + +### Incompatibility across Atom release channels + +One other possible drawback is that an updated version of a bundled package might not be compatible across two different Atom channels. For example, if the user installs a new update to a bundled package that only supports the current Atom Beta release or higher, the user will no longer have access to that package if they open Atom Stable. However, this drawback is no different than what the user would face today installing a community package under the same circumstances, so this could be considered a general problem in the Atom package ecosystem. + +Finally, one risk of this approach is that the Atom team forgets to update a bundled package to its latest appropriate version on `apm` just before a new release. If this happens, the user will install a new Atom update and then be prompted to update a package that should have been snapshotted and shipped in-box. To avoid this problem we could add some build automation that checks for the latest version of a bundled package to see if the current Atom build would be supported by it. + +## Rationale and alternatives + +This is the best approach for updating bundled packages because it allows those packages to take control of their own release cycle so long as they manage their Atom engine version correctly. It also does so in a way that allows us to decide which packages can be updated independently, reducing the likelihood of problems for users. + +The primary alternative to this approach is to speed up the Atom release cycle so that bundled Atom package updates will reach users more frequently. This approach will be investigated independently of this RFC as it may still be valuable even with Updatable bundled packages. + +## Unresolved questions + +> - What unresolved questions do you expect to resolve through the RFC process before this gets merged? + +Is it enough to just depend on the `engines` field of `package.json` to protect users from installing a package update that doesn't work with their version of Atom? + +> - What unresolved questions do you expect to resolve through the implementation of this feature before it is released in a new version of Atom? + +Is there any optimization we can use to reduce the performance hit of loading updated bundled packages? + +> - What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? + +One issue that's out of scope for this RFC is how we ship new features and fixes to the core components of Atom (not its bundled packages) more frequently. There are two options we can investigate to accomplish this: + +- **Ship Atom updates more frequently, possibly every two weeks** + +- **Introduce a channel for nightly builds which surface the latest changes every day** + +Both of these possibilities will be covered in future RFCs as they could be implemented independently of the feature described in this RFC. diff --git a/docs/rfcs/002-atom-nightly-releases.md b/docs/rfcs/002-atom-nightly-releases.md new file mode 100644 index 000000000..5bb72c8ff --- /dev/null +++ b/docs/rfcs/002-atom-nightly-releases.md @@ -0,0 +1,57 @@ +# Atom Nightly Releases + +## Status + +Implemented in PR [#17538](https://github.com/atom/atom/pull/17538) + +## Summary + +This RFC proposes that Atom add a third official release channel which delivers new builds of Atom nightly from the `master` branch. Nightly releases will allow new improvements to reach users long before a new Stable or Beta release is shipped. This effort will also give us the opportunity to experiment with new release automation strategies that could eventually be used to speed up the Stable and Beta release cadence. + +## Motivation + +Atom currently uses a monthly release cycle with staged Stable and Beta releases so that major issues get caught early in Beta before reaching the Stable release. Because Atom releases updates monthly, this means that a new feature merged into `master` right after a new Atom release could take one month to reach the next Beta and then another month to reach Stable. + +This release process works well for delivering stable improvements to users on a regular basis but it results in friction for users who want to try out the latest Atom improvements and provide feedback. If we deliver a nightly release channel, it will be possible to deliver new features and bug fixes on a regular basis and get valuable feedback to guide our work. + +Today, a bleeding-edge user must manually pull Atom's `master` branch and compile their own build. There is a source of `dev` builds from `master` across our CI services but those aren't made available to users as an official distribution. + +## Explanation + +A user who wants to use the latest improvements to Atom each day can go to atom.io, download the Atom Nightly release, and install it on their machine. This release can be installed alongside Atom Stable and Atom Beta. + +Each night when there are new commits to Atom's `master` branch, a scheduled CI build creates a new Atom Nightly release with packages for Windows, macOS, and Linux. These packages are automatically uploaded to a new GitHub release on the `atom/atom-nightly-releases` repository using a monotonically-increasing nightly version based off of the version in `master` (e.g. `v1.29.0-nightly1`). + +Every 4 hours, an Atom Nightly release installed on Windows or macOS checks for a new update by consulting Electron's [update.electronjs.org](update-electron) service. If a new update is available, it is downloaded in the background and the user is notified to restart Atom once it's complete. This update flow is the same as what users experience in Atom Stable or Beta releases but updates occur more frequently. + +Linux users must manually download nightly releases for now as there isn't an easy way to automatically install new updates across the various Linux distributions. We may consider providing updatable [AppImage](http://appimage.org/) packages in the future; this will be proposed in a separate RFC. + +## Drawbacks + +There isn't a major downside to this effort since it would run in parallel to the existing Atom release process without affecting it. + +## Rationale and alternatives + +This is a useful approach because it allows us to achieve a much more rapid feedback loop with highly engaged users to ensure that Atom is improving regularly. It's the best approach because it allows us to get rapid feedback without sacrificing the stability of the Stable and Beta releases. + +Another option is to speed up Atom's release cadence to ship Stable and Beta every two weeks (or more regularly). This approach could shorten our feedback loop but at the expense of greater instability since new improvements would not have as much time to be polished before release. + +The impact of not taking this approach is that we continue to have to wait 1-2 months to get feedback from users about new features or bugs in Stable and Beta releases. + +## Unresolved questions + +- **What should we call this release channel?** + + Some ideas: + + - Atom Nightly + - Atom Reactor + - Atom Dev - Currently the name of dev builds but it might make sense to leave that for "normal" builds from `master` + + According to a [Twitter poll](https://twitter.com/daviwil/status/1006545552987701248) with about 1,600 responses, 50% of the voters chose "Atom Nightly". The final name will be determined before launch. + +- **Will Electron's new autoUpdate service work for all Atom releases?** + + One outcome of this effort is to use the new [update.electronjs.org](update-electron) service for Atom's update checks so that we can deprecate on our own custom update service. Building the Nightly channel on this service will allow us to evaluate it to see if it meets the needs of the Stable and Beta channels. + +[update-electron]: https://github.com/electron/update.electronjs.org diff --git a/docs/rfcs/003-consolidate-core-packages.md b/docs/rfcs/003-consolidate-core-packages.md new file mode 100644 index 000000000..960ac95ce --- /dev/null +++ b/docs/rfcs/003-consolidate-core-packages.md @@ -0,0 +1,345 @@ +# Consolidate Core Atom Packages + +## Status + +Accepted + +## Summary + +Atom's official distribution is comprised of 92 core packages which provide its built-in functionality. These packages currently live in their own independent repositories in the Atom organization, all with their own separate issues, PRs, releases, and CI configurations. This RFC proposes that by consolidating most, if not all, of these core packages back into the `atom/atom` repo, we will see the following benefits: + +- Less confusion for new contributors +- Simpler core package contribution experience +- Greatly reduced burden for maintainers + +## Motivation + +Let's cover each of the bullet points mentioned above: + +### Less confusion for contributors + +Imagine that a new contributor wants to add a small new feature to the `tree-view` package. The first place they are likely to look is the `atom/atom` repository. Scanning through the folders will lead to a dead end as nothing that looks like `tree-view` code can be found. They might take one of the following steps next: + +- By reading README.md, maybe they will decide to click the link to the Atom Flight Manual and _maybe_ find the [Contributing to Official Atom Packages](https://flight-manual.atom.io/hacking-atom/sections/contributing-to-official-atom-packages/) page there +- They could read the CONTRIBUTING.md file which [has a section](https://github.com/atom/atom/blob/master/CONTRIBUTING.md#atom-and-packages) that explains where to find the repos for core packages and how to contribute, but we don't really have a clear pointer to that in our README.md +- If they don't happen to find that page, they might use Google to search for "atom tree view" and find the atom/tree-view repo and _maybe_ read the CONTRIBUTING.md file which sends them to Atom's overall contribution documentation +- They might go to the Atom Forum or Slack community to ask how to contribute to a particular part of Atom and *hopefully* get a helpful response that points them in the right direction + +Having all of the core Atom packages represented in a top-level `packages` folder, even if they all don't actually live in the repo, will go a long way to making the core package code more discoverable. + +### Simpler core package contribution experience + +Separating core Atom features out into individual repositories and delivering them to Atom builds via `apm` is a great idea in theory because it validates the Atom package ecosystem and gives developers many examples of how to develop an Atom package. It also gives Atom developers real-world experience working with Atom's APIs so that we ensure community package authors have the same hackability that Atom developers enjoy. + +On the other hand, having these packages live in separate repositories and released "independently" introduces a great deal of overhead when adding new features. Here is a comparison of the current package development workflow contrasted to what we could achieve with consolidated packages: + +#### Current Package Development Workflow + +For example, to add a single feature to the `tree-view` package, one must: + +1. Fork and clone the `tree-view` repository to their computer (making sure to pull the commit relevant to the version of Atom they are working with) +1. Run `apm install` and `apm link` inside of the repo folder +1. Make their desired changes to the code +1. Open a PR to the `tree-view` repo and wait for CI to pass and a maintainer to review it +1. Work with maintainers to get the PR approved and merged + +After this is finished, an Atom maintainer must take the following steps: + +1. Clone the `tree-view` repo +2. Run `apm publish` to publish a new release of the package +3. Edit `package.json` in the Atom repo to reflect the new version of `tree-view` +4. Commit and push the changes to the relevant branch where the change belongs (`master` or `1.nn-releases`) + +#### Simplified Package Development + +If we were to move `tree-view` (or any other core Atom package) back into `atom/atom`, the development workflow would look more like this: + +1. Fork and clone `atom/atom` and switch to a release branch if necessary +1. Build Atom and launch it in dev mode +1. Make desired changes to the code in `packages/tree-view` +1. Open a PR on `atom/atom` and wait for CI to pass and a maintainer to review it +1. Work with maintainers to get the PR approved and merged + +At this point, the change is merged into Atom and ready for inclusion in the next release. + +### Greatly reduced burden for maintainers + +Since packages all have their own repositories, this means that we have to watch 91 different repos for issues and pull requests. This also means that we have to redirect issues filed on `atom/atom` to the appropriate repository when a user doesn't know where it belongs. Even more importantly, there's not an easy way to prioritize and track issues across the Atom organization without using GitHub Projects. + +Also, as mentioned above, there's the added duty of doing the package "version dance" when we merge any new PRs to a package repository: publish the package update, update `package.json` in Atom. It's very easy to forget to do this and not have community contributions included in the next Atom release! + +The more core packages live in `atom/atom`, the less work Atom maintainers have to do overall. + +## Explanation + +Many of Atom's core packages now live in the core `atom/atom` repository. To the Atom user, this change will be imperceptible as these packages still show up in the list of Core Packages in the Settings View. Users can still optionally disable these packages. + +For maintainers and contributors, there will be less juggling of repositories and no more publishing of updates to these packages with `apm`: + +Contributors now clone and build `atom/atom` to work on improvements to core packages. They will no longer have to use `apm link` in dev mode to test changes they make to packages in the repo's `packages` folder. Core packages that aren't consolidated still have folders under `packages` with README.md files that point to the home repository for that package. + +When a contributor sends a PR to `atom/atom` that only affects files in a folder under `packages`, only the specs for the relevant package folders will be executed using Atom's CI scripts. This means that a full Atom build will not be required when no Atom Core code is changed in a PR. Package specs are also now run against all 3 OSes on Atom `master` and release builds. + +Atom maintainers no longer have to publish new versions to consolidated core packages and then edit `package.json` to bump the package version in a particular Atom release branch (Stable, Beta, or `master`). When a PR against a consolidated core package in `atom/atom` is merged, no version number change is required and the changes will immediately be a part of the next release from that branch. + +## Drawbacks + +One possible drawback of this approach is that there might be some initial confusion where core Atom packages live, especially if some are consolidated into `atom/atom` and others still live in their own repositories. We will manage this confusion by doing the following: + +- Include a `README.md` file in the `packages` folder which lists core packages that are not consolidated in the Atom repo. This will enable users to find the home repositories of those packages. + +- Archive the repositories for consolidated core packages, but only after migrating existing issues, merging or closing existing PRs, and updating the README.md to point to the new home of the package code. + +Also, contributors will now have to fork, clone, and build `atom/atom` to contribute to core packages where they would previously just need to clone the package repository. This might put added burden on them such as installing necessary build dependencies on their machine that they wouldn't otherwise need. It is very likely we could simplify this process for them, though. + +One final drawback is that it will now be harder to have single-package maintainers. We currently have 7 core packages where there is a maintainer who isn't a part of the core Atom maintainers team. These maintainers generally are able to merge community PRs and make commits to those packages with their own judgement. If we get rid of individual package repositories, do we now make those maintainers full Atom maintainers? + +## Rationale and alternatives + +The Motivation section explains most of the rationale, so this section will focus on the process of consolidating packages back into `atom/atom`. The set of packages we've chosen to consolidate were evaluated based on a few factors: + +- Number of open issues and PRs (exclude any with > 10 open PRs) +- Time since last update (longer duration since last update is prioritized) +- Number of package-only maintainers on the repo (exclude any with package maintainers for now) + +Using this criteria, all 91 packages have been evaluated and categorized to determine whether they are good candidates for consolidation: + +#### Initial Consolidation Candidates + +| Package | Open Issues | Open PRs | Outside Maintainers | Last Updated | +|---------|-------------|----------|---------------------| -------------| +| **[about]** | 2 | 0 | 0 | 7/11/18 | +| **[archive-view]** | 10 | 0 | 0 | 6/3/18 | +| **[atom-dark-syntax]** | 5 | 0 | 0 | 12/6/17 | +| **[atom-dark-ui]** | 1 | 2 | 0 | 2/13/18 | +| **[atom-light-syntax]** | 1 | 0 | 0 | 10/17/16 | +| **[atom-light-ui]** | 1 | 0 | 0 | 2/13/18 | +| **[autoflow]** | 17 | 4 | 0 | 4/17/18 | +| **[autosave]** | 13 | 0 | 0 | 9/16/17 | +| **[background-tips]** | 3 | 2 | 0 | 2/17/18 | +| **[base16-tomorrow-dark-theme]** | 5 | 0 | 0 | 1/10/17 | +| **[base16-tomorrow-light-theme]** | 1 | 0 | 0 | 1/10/17 | +| **[bookmarks]** | 19 | 4 | 0 | 12/10/17 | +| **[bracket-matcher]** | 74 | 8 | 0 | 3/20/18 | +| **[command-palette]** | 18 | 6 | 0 | 2/27/18 | +| **[dalek]** | 2 | 0 | 0 | 2/28/18 | +| **[deprecation-cop]** | 5 | 0 | 0 | 9/7/17 | +| **[dev-live-reload]** | 4 | 0 | 0 | 11/14/17 | +| **[encoding-selector]** | 11 | 2 | 0 | 4/19/18 | +| **[exception-reporting]** | 5 | 0 | 0 | 2/6/18 | +| **[git-diff]** | 38 | 1 | 0 | 1/18/18 | +| **[go-to-line]** | 5 | 2 | 0 | 1/25/18 | +| **[grammar-selector]** | 3 | 1 | 0 | 4/12/18 | +| **[image-view]** | 4 | 4 | 0 | 7/9/18 | +| **[incompatible-packages]** | 1 | 0 | 0 | 4/25/17 | +| **[keybinding-resolver]** | 11 | 3 | 0 | 7/6/18 | +| **[language-clojure]** | 13 | 3 | 0 | 1/26/18 | +| **[language-coffee-script]** | 9 | 2 | 0 | 11/1/17 | +| **[language-csharp]** | 1 | 1 | 0 | 4/27/18 | +| **[language-css]** | 6 | 7 | 0 | 6/11/18 | +| **[language-gfm]** | 52 | 9 | 0 | 6/15/18 | +| **[language-git]** | 4 | 2 | 0 | 4/18/17 | +| **[language-html]** | 11 | 4 | 0 | 7/5/18 | +| **[language-hyperlink]** | 2 | 3 | 0 | 10/25/17 | +| **[language-json]** | 1 | 0 | 0 | 5/11/18 | +| **[language-less]** | 5 | 1 | 0 | 6/11/18 | +| **[language-make]** | 7 | 3 | 0 | 11/26/16 | +| **[language-mustache]** | 0 | 0 | 0 | 2/5/18 | +| **[language-objective-c]** | 2 | 0 | 0 | 12/1/15 | +| **[language-php]** | 25 | 7 | 0 | 6/11/18 | +| **[language-property-list]** | 1 | 0 | 0 | 3/11/17 | +| **[language-python]** | 33 | 4 | 0 | 6/18/18 | +| **[language-ruby]** | 38 | 10 | 0 | 10/25/17 | +| **[language-ruby-on-rails]** | 9 | 6 | 0 | 12/7/17 | +| **[language-sass]** | 12 | 5 | 0 | 5/2/18 | +| **[language-shellscript]** | 12 | 3 | 0 | 6/18/18 | +| **[language-source]** | 0 | 0 | 0 | 1/6/15 | +| **[language-sql]** | 6 | 4 | 0 | 1/26/18 | +| **[language-text]** | 1 | 0 | 0 | 3/9/18 | +| **[language-todo]** | 10 | 6 | 0 | 1/26/18 | +| **[language-toml]** | 1 | 0 | 0 | 1/6/18 | +| **[language-typescript]** | 6 | 0 | 0 | 6/18/18 | +| **[language-xml]** | 2 | 1 | 0 | 6/12/17 | +| **[language-yaml]** | 8 | 2 | 0 | 3/9/18 | +| **[line-ending-selector]** | 10 | 0 | 0 | 5/18/18 | +| **[link]** | 0 | 1 | 0 | 11/14/17 | +| **[metrics]** | 1 | 2 | 0 | 7/5/18 | +| **[notifications]** | 29 | 8 | 0 | 3/22/18 | +| **[one-dark-syntax]** | 4 | 0 | 0 | 5/27/18 | +| **[one-dark-ui]** | 13 | 1 | 0 | 5/1/18 | +| **[one-light-syntax]** | 2 | 1 | 0 | 5/27/18 | +| **[one-light-ui]** | 2 | 0 | 0 | 5/1/18 | +| **[open-on-github]** | 8 | 3 | 0 | 11/21/17 | +| **[package-generator]** | 10 | 2 | 0 | 11/16/17 | +| **[status-bar]** | 25 | 3 | 0 | 11/6/17 | +| **[styleguide]** | 12 | 2 | 0 | 4/12/18 | +| **[tabs]** | 66 | 7 | 0 | 5/13/18 | +| **[timecop]** | 5 | 0 | 0 | 11/4/17 | +| **[update-package-dependencies]** | 0 | 0 | 0 | 12/10/17 | +| **[welcome]** | 0 | 0 | 0 | 11/21/17 | +| **[whitespace]** | 31 | 6 | 0 | 5/30/18 | +| **[wrap-guide]** | 3 | 4 | 0 | 11/27/17 | + +#### Packages to be Consolidated Later + +The following packages will not be consolidated until the stated reasons can be resolved or we decide on a consolidation strategy for them: + +| Package | Open Issues | Open PRs | Outside Maintainers | Last Updated | Reason | +|---------|-------------|----------|---------------------|--------------|-------| +| **[find-and-replace]** | 219 | 17 | 0 | 6/4/18 | Too many open PRs | +| **[fuzzy-finder]** | 89 | 22 | 0 | 5/17/18 | Too many open PRs | +| **[github]** | | | | | Independent project | +| **[language-c]** | 53 | 15 | 0 | 7/10/18 | Too many open PRs | +| **[language-go]** | 12 | 2 | **1** | 6/18/18 | Package maintainer, possibly inactive? | +| **[language-java]** | 8 | 2 | **1** | 6/11/18 | Package maintainer | +| **[language-javascript]** | 66 | 12 | 0 | 7/6/18 | Too many open PRs | +| **[language-perl]** | 17 | 1 | **1** | 10/30/17 | Package maintainer, possibly inactive? | +| **[markdown-preview]** | 139 | 12 | 0 | 1/8/18 | Too many open PRs | +| **[settings-view]** | 137 | 18 | 0 | 5/17/18 | Too many open PRs | +| **[snippets]** | 57 | 4 | **1** | 4/17/18 | Package maintainer | +| **[solarized-dark-syntax]** | 8 | 3 | **1** | 5/27/18 | Package maintainer | +| **[solarized-light-syntax]** | 2 | 3 | **1** | 5/27/18 | Package maintainer | +| **[spell-check]** | 68 | 14 | **1** | 5/25/18 | Too many open PRs, package maintainer | +| **[symbols-view]** | 86 | 13 | 0 | 12/10/17 | Too many open PRs | +| **[tree-view]** | 210 | 36 | 0 | 3/21/18 | Too many open PRs | + +#### Packages to Never Consolidate + +These packages will not be consolidated because they would inhibit contributions from our friends in the Nuclide team at Facebook: + +- **[autocomplete-atom-api]** +- **[autocomplete-css]** +- **[autocomplete-html]** +- **[autocomplete-plus]** +- **[autocomplete-snippets]** + +### Consolidation Process + +To consolidate a single core package repository back into `atom/atom`, the following steps will be taken: + +1. All open pull requests on the package's repository must either be closed or merged before consolidation can proceed +1. The package repository's code in `master` will be copied over to Atom's `packages` folder in a subfolder bearing that package's name. +1. Atom's `package.json` file will be updated to change the package's `packageDependencies` entry to reference its local path with the following syntax: `"tree-view": "file:./packages/tree-view"` +1. A test build will be created locally to manually verify that the package loads and works correctly at first glance +1. The package specs for the newly-consolidated package will be run against the local Atom build +1. A PR will be sent to `atom/atom` to verify that CI passes with the introduction of the consolidated package +1. Once CI is clean and the PR is approved, the PR will be merged +1. The package's original repository will have all of its existing issues moved over to `atom/atom` using a bulk issue mover tool, assigning a label to those issues relative to the package name, like `packages/tree-view` +1. The package's original repository will have its README.md updated to point contributors to the code's new home in `atom/atom` +1. The package's original repository will now be archived on GitHub + +### Alternative Approaches + +One alternative approach would be to break this core Atom functionality out of packages and put it directly in the Atom codebase without treating them as packages. This would simplify the development process even further but with the following drawbacks: + +- The Atom team would have less regular exposure to Atom package development +- Users would no longer be able to disable core packages to replace their behavior with other packages (different tree views, etc) + +## Unresolved questions + +- Is there a good reason to not move the `language-*` packages into `atom/atom`? + + One concern here is that there exist projects which depend directly on these repositories for the TextMate syntax grammars they contain. Moving the code into `atom/atom` would require that we notify the consumers of the grammars so that they can redirect their requests to the `atom/atom` repo. + +- Should we use `git subtree` to migrate the entire commit history of these packages over or just depend on the history from a package's original repository? + + For now, we won't use `git subtree` due to the possibility that bringing over thousands of commits could cause unknown problems in the Atom repo. We may try this for newly consolidated packages in the future if we decide that not having the package commit history is a sufficient impediment to problem investigations. + +- What are the criteria we might use to eventually decide to move larger packages like `tree-view`, `settings-view`, and `find-and-replace` back into `atom/atom`? + +- Will we be losing any useful data about these packages if we don't have standalone repositories anymore? + +- Should we use this as an opportunity to remove any unnecessary packages from the core Atom distribution? + +[about]: https://github.com/atom/about +[archive-view]: https://github.com/atom/archive-view +[atom-dark-syntax]: https://github.com/atom/atom-dark-syntax +[atom-dark-ui]: https://github.com/atom/atom-dark-ui +[atom-light-syntax]: https://github.com/atom/atom-light-syntax +[atom-light-ui]: https://github.com/atom/atom-light-ui +[autocomplete-atom-api]: https://github.com/atom/autocomplete-atom-api +[autocomplete-css]: https://github.com/atom/autocomplete-css +[autocomplete-html]: https://github.com/atom/autocomplete-html +[autocomplete-plus]: https://github.com/atom/autocomplete-plus +[autocomplete-snippets]: https://github.com/atom/autocomplete-snippets +[autoflow]: https://github.com/atom/autoflow +[autosave]: https://github.com/atom/autosave +[background-tips]: https://github.com/atom/background-tips +[base16-tomorrow-dark-theme]: https://github.com/atom/base16-tomorrow-dark-theme +[base16-tomorrow-light-theme]: https://github.com/atom/base16-tomorrow-light-theme +[bookmarks]: https://github.com/atom/bookmarks +[bracket-matcher]: https://github.com/atom/bracket-matcher +[command-palette]: https://github.com/atom/command-palette +[dalek]: https://github.com/atom/dalek +[deprecation-cop]: https://github.com/atom/deprecation-cop +[dev-live-reload]: https://github.com/atom/dev-live-reload +[encoding-selector]: https://github.com/atom/encoding-selector +[exception-reporting]: https://github.com/atom/exception-reporting +[find-and-replace]: https://github.com/atom/find-and-replace +[fuzzy-finder]: https://github.com/atom/fuzzy-finder +[git-diff]: https://github.com/atom/git-diff +[github]: https://github.com/atom/github +[go-to-line]: https://github.com/atom/go-to-line +[grammar-selector]: https://github.com/atom/grammar-selector +[image-view]: https://github.com/atom/image-view +[incompatible-packages]: https://github.com/atom/incompatible-packages +[keybinding-resolver]: https://github.com/atom/keybinding-resolver +[language-c]: https://github.com/atom/language-c +[language-clojure]: https://github.com/atom/language-clojure +[language-coffee-script]: https://github.com/atom/language-coffee-script +[language-csharp]: https://github.com/atom/language-csharp +[language-css]: https://github.com/atom/language-css +[language-gfm]: https://github.com/atom/language-gfm +[language-git]: https://github.com/atom/language-git +[language-go]: https://github.com/atom/language-go +[language-html]: https://github.com/atom/language-html +[language-hyperlink]: https://github.com/atom/language-hyperlink +[language-java]: https://github.com/atom/language-java +[language-javascript]: https://github.com/atom/language-javascript +[language-json]: https://github.com/atom/language-json +[language-less]: https://github.com/atom/language-less +[language-make]: https://github.com/atom/language-make +[language-mustache]: https://github.com/atom/language-mustache +[language-objective-c]: https://github.com/atom/language-objective-c +[language-perl]: https://github.com/atom/language-perl +[language-php]: https://github.com/atom/language-php +[language-property-list]: https://github.com/atom/language-property-list +[language-python]: https://github.com/atom/language-python +[language-ruby]: https://github.com/atom/language-ruby +[language-ruby-on-rails]: https://github.com/atom/language-ruby-on-rails +[language-sass]: https://github.com/atom/language-sass +[language-shellscript]: https://github.com/atom/language-shellscript +[language-source]: https://github.com/atom/language-source +[language-sql]: https://github.com/atom/language-sql +[language-text]: https://github.com/atom/language-text +[language-todo]: https://github.com/atom/language-todo +[language-toml]: https://github.com/atom/language-toml +[language-typescript]: https://github.com/atom/language-typescript +[language-xml]: https://github.com/atom/language-xml +[language-yaml]: https://github.com/atom/language-yaml +[line-ending-selector]: https://github.com/atom/line-ending-selector +[link]: https://github.com/atom/link +[markdown-preview]: https://github.com/atom/markdown-preview +[metrics]: https://github.com/atom/metrics +[notifications]: https://github.com/atom/notifications +[one-dark-syntax]: https://github.com/atom/one-dark-syntax +[one-dark-ui]: https://github.com/atom/one-dark-ui +[one-light-syntax]: https://github.com/atom/one-light-syntax +[one-light-ui]: https://github.com/atom/one-light-ui +[open-on-github]: https://github.com/atom/open-on-github +[package-generator]: https://github.com/atom/package-generator +[settings-view]: https://github.com/atom/settings-view +[snippets]: https://github.com/atom/snippets +[solarized-dark-syntax]: https://github.com/atom/solarized-dark-syntax +[solarized-light-syntax]: https://github.com/atom/solarized-light-syntax +[spell-check]: https://github.com/atom/spell-check +[status-bar]: https://github.com/atom/status-bar +[styleguide]: https://github.com/atom/styleguide +[symbols-view]: https://github.com/atom/symbols-view +[tabs]: https://github.com/atom/tabs +[timecop]: https://github.com/atom/timecop +[tree-view]: https://github.com/atom/tree-view +[update-package-dependencies]: https://github.com/atom/update-package-dependencies +[welcome]: https://github.com/atom/welcome +[whitespace]: https://github.com/atom/whitespace +[wrap-guide]: https://github.com/atom/wrap-guide diff --git a/keymaps/darwin.cson b/keymaps/darwin.cson index 6d576f102..ec73bc8c2 100644 --- a/keymaps/darwin.cson +++ b/keymaps/darwin.cson @@ -79,8 +79,8 @@ 'ctrl-shift-tab ^ctrl': 'pane:move-active-item-to-top-of-stack' 'cmd-=': 'window:increase-font-size' 'cmd-+': 'window:increase-font-size' - 'cmd--': 'window:decrease-font-size' 'cmd-_': 'window:decrease-font-size' + 'cmd--': 'window:decrease-font-size' 'cmd-0': 'window:reset-font-size' 'cmd-k up': 'pane:split-up-and-copy-active-item' # Atom Specific diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..74ab8c386 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5996 @@ +{ + "name": "atom", + "version": "1.32.0-dev", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@atom/nsfw": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/@atom/nsfw/-/nsfw-1.0.18.tgz", + "integrity": "sha512-YceKV9a3X62mh4Q78Nyi8aTRaoVGdpeJBHogL8gxU17iBhEpYvxGgMfTe02j1hH2taFT4barkZ5RdZkGKIsJ/w==", + "requires": { + "fs-extra": "0.26.7", + "lodash.isinteger": "4.0.4", + "lodash.isundefined": "3.0.1", + "nan": "2.10.0", + "promisify-node": "0.3.0" + } + }, + "@atom/source-map-support": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@atom/source-map-support/-/source-map-support-0.3.4.tgz", + "integrity": "sha1-Vcy+DmSyx0LFszPzV/mpMWEUXP0=", + "requires": { + "source-map": "0.1.32" + } + }, + "@atom/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/@atom/temp/-/temp-0.8.4.tgz", + "integrity": "sha1-RVFIywz2ygNI5xpc+ZiGq8rERek=", + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.6.2" + } + }, + "@atom/watcher": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@atom/watcher/-/watcher-1.0.8.tgz", + "integrity": "sha512-53un+vGSaY7Fsbvmg8gerYOA3ISipMWR3qiYR9hZWqSfvFsksXJfGrmFsfbBj3uqGRQ3gPTi6wpxcFSWjbWVFQ==", + "requires": { + "event-kit": "2.5.0", + "fs-extra": "6.0.1", + "nan": "2.10.0", + "node-pre-gyp": "0.10.0" + }, + "dependencies": { + "fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.2" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "4.1.11" + } + } + } + }, + "CSSselect": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/CSSselect/-/CSSselect-0.4.1.tgz", + "integrity": "sha1-+Kt+H4QYzmPNput713ioXX7EkrI=", + "requires": { + "CSSwhat": "0.4.7", + "domutils": "1.4.3" + } + }, + "CSSwhat": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/CSSwhat/-/CSSwhat-0.4.7.tgz", + "integrity": "sha1-hn2g/zn3eGEyQsRM/qg/CqTr35s=" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "about": { + "version": "file:packages/about", + "requires": { + "etch": "0.9.0", + "semver": "5.5.1" + }, + "dependencies": { + "etch": { + "version": "0.9.0", + "bundled": true + }, + "semver": { + "version": "5.5.1", + "bundled": true + } + } + }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "alter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz", + "integrity": "sha1-x1iICGF1cgNKrmJICvJrHU0cs80=", + "requires": { + "stable": "0.1.8" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "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": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "apparatus": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/apparatus/-/apparatus-0.0.10.tgz", + "integrity": "sha512-KLy/ugo33KZA7nugtQ7O0E1c8kQ52N3IvD/XgIh4w/Nr28ypfkwDfA67F1ev4N1m5D+BOk1+b2dEJDfpj/VvZg==", + "requires": { + "sylvester": "0.0.21" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archive-view": { + "version": "https://www.atom.io/api/packages/archive-view/versions/0.65.1/tarball", + "integrity": "sha512-/rTgY/88lVONL0JNwygl+42eCdK+h2xrGWTb2kNBk2gnL/OQZfOXKaxxgOv2Wde7Kz0gOiAyZKYwxv+PIUOoaA==", + "requires": { + "etch": "0.9.0", + "fs-plus": "3.0.2", + "humanize-plus": "1.8.2", + "ls-archive": "1.3.1", + "temp": "0.8.3" + }, + "dependencies": { + "etch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.0.tgz", + "integrity": "sha1-CSJpiPLO4GkL3yCMyyXkFNXfrV8=" + } + } + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, + "ast-traverse": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ast-traverse/-/ast-traverse-0.1.1.tgz", + "integrity": "sha1-ac8rg4bxnc2hux4F1o/jWdiJfeY=" + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=" + }, + "async": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.6.tgz", + "integrity": "sha1-rT83PZJJrjJIgVZVgryQ4VKrvWg=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atom-babel6-transpiler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/atom-babel6-transpiler/-/atom-babel6-transpiler-1.2.0.tgz", + "integrity": "sha512-lZucrjVyRtPAPPJxvICCEBsAC1qn48wUHaIlieriWCXTXLqtLC2PvkQU7vNvU2w1eZ7tw9m0lojZ8PbpVyWTvg==", + "requires": { + "babel-core": "6.26.3" + }, + "dependencies": { + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "atom-dark-syntax": { + "version": "https://www.atom.io/api/packages/atom-dark-syntax/versions/0.29.1/tarball", + "integrity": "sha512-b5rCHzPR64JCc5WrLFsz1UawYKUB5v6QswTe/MYHs7tkmJJNzaFbQi2JmbroK58b+3ccwbYrRH8DxWyzGRS2kg==" + }, + "atom-dark-ui": { + "version": "https://www.atom.io/api/packages/atom-dark-ui/versions/0.53.3/tarball", + "integrity": "sha512-iCCFdXWaAsNmNFEDdrO+onBMg5PKpVL8YDyjhHLPpCuIsm0jjpbg3qjrBCkhaDHJfiiNIrY2HhqhQKvYcFmYPA==" + }, + "atom-grammar-test": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/atom-grammar-test/-/atom-grammar-test-0.6.4.tgz", + "integrity": "sha1-2KU1A9H+k5mX9Ji3SirDEARKfU4=", + "requires": { + "chevrotain": "0.18.0", + "escape-string-regexp": "1.0.5" + } + }, + "atom-keymap": { + "version": "8.2.10", + "resolved": "https://registry.npmjs.org/atom-keymap/-/atom-keymap-8.2.10.tgz", + "integrity": "sha512-OGdBlLyxQxHNXD4/H0OyaN8/Sfq40MvXf9YcdzME/XycM8ZVCj3ZYEVN5OU1R9Kmz/vfBWjLM6E+/l2sYSWqhQ==", + "requires": { + "clear-cut": "2.0.2", + "emissary": "1.3.3", + "event-kit": "1.5.0", + "fs-plus": "3.0.2", + "grim": "1.5.0", + "keyboard-layout": "2.0.13", + "pathwatcher": "8.0.1", + "property-accessors": "1.1.3", + "season": "6.0.2" + }, + "dependencies": { + "event-kit": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/event-kit/-/event-kit-1.5.0.tgz", + "integrity": "sha1-Ek72qtgyjcsmtxxHWQtbjmPrxIc=", + "requires": { + "grim": "1.5.0" + } + } + } + }, + "atom-light-syntax": { + "version": "https://www.atom.io/api/packages/atom-light-syntax/versions/0.29.1/tarball", + "integrity": "sha512-sRUWw4iJi8zuw4EBtcE2kGeSzGquQP6ZQqC0k7+UlbHdoL0a/l9mlBftcow6VRCnLb/lPCkH3Aywmq3PbmFOHg==" + }, + "atom-light-ui": { + "version": "https://www.atom.io/api/packages/atom-light-ui/versions/0.46.3/tarball", + "integrity": "sha512-oCbvW6mQzxmUdqHuz5F6vHlQRGXJqeh432/i/uCQL0LOWTj8wIgel6aEVRgHVijsanQZr7PGlQWcK+BoVv3O/A==" + }, + "atom-pathspec": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/atom-pathspec/-/atom-pathspec-0.0.0.tgz", + "integrity": "sha512-7UMEHdTtBV5sJONT0uMeQ6M8JFdfMQy/14rxuP6OuoFfSiDjxyZHuorIbv8gqhRB3FQMMLPzqONoFJE2cpHiCg==" + }, + "atom-select-list": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/atom-select-list/-/atom-select-list-0.7.2.tgz", + "integrity": "sha512-a707OB1DhLGjzqtFrtMQKH7BBxFuCh8UBoUWxgFOrLrSwVh3g+/TlVPVDOz12+U0mDu3mIrnYLqQyhywQOTxhw==", + "requires": { + "etch": "0.12.8", + "fuzzaldrin": "2.1.0" + } + }, + "atom-slick": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/atom-slick/-/atom-slick-2.0.0.tgz", + "integrity": "sha1-/w2+Fb4sTtomi50w124lF+C308o=" + }, + "atom-ui": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/atom-ui/-/atom-ui-0.4.1.tgz", + "integrity": "sha1-cNl3ZsukcW15jpSWKq0HkghB6lw=" + }, + "autocomplete-atom-api": { + "version": "https://www.atom.io/api/packages/autocomplete-atom-api/versions/0.10.7/tarball", + "integrity": "sha512-027xza+IwcoAut6ryUQYJGXkIOJkFVAA2mRzmOX5DdADSrifXDn3BZtPjfRpMMvqstC8H+xuxNs0dOdUYhssqw==" + }, + "autocomplete-css": { + "version": "https://www.atom.io/api/packages/autocomplete-css/versions/0.17.5/tarball", + "integrity": "sha512-iFsTHwAzESHV3p9HD23WnlZA69G8f5x3rvY6BmorrOMqPodx/6xBK1cq81SDGtlHgJ9hmwpc1DAtinpFy3qEOQ==" + }, + "autocomplete-html": { + "version": "https://www.atom.io/api/packages/autocomplete-html/versions/0.8.5/tarball", + "integrity": "sha512-OpZM+I4ttUKpjb/1WoTbWBfEkedxPO8fTCUCckzYN/V/IQioWRqgozfOxaALTRqJE6Xh8Sm7g1jqo8Ikhqs7LA==" + }, + "autocomplete-plus": { + "version": "https://www.atom.io/api/packages/autocomplete-plus/versions/2.41.0/tarball", + "integrity": "sha512-9TKOCiqODN06LOsO2GlxzjaK5Y5o96emktpqtyfNl7Nj7BkuND/ZHPl7vDXQq/ZfAlq87j18RCSj79O3bYNivg==", + "requires": { + "atom-slick": "2.0.0", + "fuzzaldrin": "2.1.0", + "fuzzaldrin-plus": "0.6.0", + "grim": "2.0.2", + "marked": "0.3.19", + "minimatch": "3.0.4", + "selector-kit": "0.1.0", + "stable": "0.1.8", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "autocomplete-snippets": { + "version": "https://www.atom.io/api/packages/autocomplete-snippets/versions/1.12.0/tarball", + "integrity": "sha512-13AruoBEEXQu4J0a58Uz1bskgJuf1ZdYEFoEmUL6m/ojYThDYVwZnlYP0fMmwQNFp1kN3NIYloyhy8YBUfDgsQ==" + }, + "autoflow": { + "version": "https://www.atom.io/api/packages/autoflow/versions/0.29.4/tarball", + "integrity": "sha512-KG6nOam4TBOmpg3C5vid0WRVw/f+z+NIwKflFUgozCs67h7bkwm7JQ9FOfs0kRjcZ8atreJjw9zu67/cqlINVg==", + "requires": { + "underscore-plus": "1.6.8" + } + }, + "autosave": { + "version": "https://www.atom.io/api/packages/autosave/versions/0.24.6/tarball", + "integrity": "sha512-RsKEDXkjLTMXuTi5AN/Y78kMBJUypYZvLHtyc3G6pK1wTJY0hmOmndBWQK9gvP3sECL/KfutMOQtP1oibHKv6Q==", + "requires": { + "fs-plus": "3.0.2" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", + "optional": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + } + } + }, + "babel-core": { + "version": "5.8.38", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-5.8.38.tgz", + "integrity": "sha1-H8ruedfmG3ULALjlT238nQr4ZVg=", + "requires": { + "babel-plugin-constant-folding": "1.0.1", + "babel-plugin-dead-code-elimination": "1.0.2", + "babel-plugin-eval": "1.0.1", + "babel-plugin-inline-environment-variables": "1.0.1", + "babel-plugin-jscript": "1.0.4", + "babel-plugin-member-expression-literals": "1.0.1", + "babel-plugin-property-literals": "1.0.1", + "babel-plugin-proto-to-assign": "1.0.4", + "babel-plugin-react-constant-elements": "1.0.3", + "babel-plugin-react-display-name": "1.0.3", + "babel-plugin-remove-console": "1.0.1", + "babel-plugin-remove-debugger": "1.0.1", + "babel-plugin-runtime": "1.0.7", + "babel-plugin-undeclared-variables-check": "1.0.2", + "babel-plugin-undefined-to-void": "1.1.6", + "babylon": "5.8.38", + "bluebird": "2.11.0", + "chalk": "1.1.3", + "convert-source-map": "1.5.1", + "core-js": "1.2.7", + "debug": "2.6.9", + "detect-indent": "3.0.1", + "esutils": "2.0.2", + "fs-readdir-recursive": "0.1.2", + "globals": "6.4.1", + "home-or-tmp": "1.0.0", + "is-integer": "1.0.7", + "js-tokens": "1.0.1", + "json5": "0.4.0", + "lodash": "3.10.1", + "minimatch": "2.0.10", + "output-file-sync": "1.1.2", + "path-exists": "1.0.0", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "regenerator": "0.8.40", + "regexpu": "1.3.0", + "repeating": "1.1.3", + "resolve": "1.8.1", + "shebang-regex": "1.0.0", + "slash": "1.0.0", + "source-map": "0.5.7", + "source-map-support": "0.2.10", + "to-fast-properties": "1.0.3", + "trim-right": "1.0.1", + "try-resolve": "1.0.1" + }, + "dependencies": { + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.10", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "requires": { + "repeating": "2.0.1" + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "1.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "esutils": "2.0.2" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-chai-assert-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-chai-assert-async/-/babel-plugin-chai-assert-async-0.1.0.tgz", + "integrity": "sha512-7z/7GQpUtVRjSFnM6qQ46gJyuprYW5bQHW47Ofia9ge2w6LEYkjo2m80SpTQqMdWYxi/I/Q8gN6nXNR0k36C0w==" + }, + "babel-plugin-constant-folding": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-constant-folding/-/babel-plugin-constant-folding-1.0.1.tgz", + "integrity": "sha1-g2HTZMmORJw2kr26Ue/whEKQqo4=" + }, + "babel-plugin-dead-code-elimination": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-dead-code-elimination/-/babel-plugin-dead-code-elimination-1.0.2.tgz", + "integrity": "sha1-X3xFEnTc18zNv7s+C4XdKBIfD2U=" + }, + "babel-plugin-eval": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz", + "integrity": "sha1-ovrtJc5r5preS/7CY/cBaRlZUNo=" + }, + "babel-plugin-inline-environment-variables": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-inline-environment-variables/-/babel-plugin-inline-environment-variables-1.0.1.tgz", + "integrity": "sha1-H1jOkSB61qgmqL9kX6/mj/X+P/4=" + }, + "babel-plugin-jscript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/babel-plugin-jscript/-/babel-plugin-jscript-1.0.4.tgz", + "integrity": "sha1-jzQsOCduh6R9X6CovT1etsytj8w=" + }, + "babel-plugin-member-expression-literals": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-member-expression-literals/-/babel-plugin-member-expression-literals-1.0.1.tgz", + "integrity": "sha1-zF7bD6qNyScXDnTW0cAkQAIWJNM=" + }, + "babel-plugin-property-literals": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-property-literals/-/babel-plugin-property-literals-1.0.1.tgz", + "integrity": "sha1-AlIwGQAZKYCxwRjv6kjOk6q4MzY=" + }, + "babel-plugin-proto-to-assign": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/babel-plugin-proto-to-assign/-/babel-plugin-proto-to-assign-1.0.4.tgz", + "integrity": "sha1-xJ56/QL1d7xNoF6i3wAiUM980SM=", + "requires": { + "lodash": "3.10.1" + } + }, + "babel-plugin-react-constant-elements": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/babel-plugin-react-constant-elements/-/babel-plugin-react-constant-elements-1.0.3.tgz", + "integrity": "sha1-lGc26DeEKcvDSdz/YvUcFDs041o=" + }, + "babel-plugin-react-display-name": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/babel-plugin-react-display-name/-/babel-plugin-react-display-name-1.0.3.tgz", + "integrity": "sha1-dU/jiSboQkpOexWrbqYTne4FFPw=" + }, + "babel-plugin-relay": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-relay/-/babel-plugin-relay-1.6.0.tgz", + "integrity": "sha512-C7ylRxOCw04pXMxuGZ16mBBol36VQTMdbnWolB9YdQWIygf0nEQuNUS8OW/IQxTaHj7Q87uJ94POXCNFDnuT0w==", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-remove-console": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-remove-console/-/babel-plugin-remove-console-1.0.1.tgz", + "integrity": "sha1-2PJFVsOgUAXUKqqv0neH9T/wE6c=" + }, + "babel-plugin-remove-debugger": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-remove-debugger/-/babel-plugin-remove-debugger-1.0.1.tgz", + "integrity": "sha1-/S6jzWGkKK0fO5yJiC/0KT6MFMc=" + }, + "babel-plugin-runtime": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-runtime/-/babel-plugin-runtime-1.0.7.tgz", + "integrity": "sha1-v3x9lm3Vbs1cF/ocslPJrLflSq8=" + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "requires": { + "babel-helper-builder-react-jsx": "6.26.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-undeclared-variables-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-undeclared-variables-check/-/babel-plugin-undeclared-variables-check-1.0.2.tgz", + "integrity": "sha1-XPGqU52BP/ZOmWQSkK9iCWX2Xe4=", + "requires": { + "leven": "1.0.2" + } + }, + "babel-plugin-undefined-to-void": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/babel-plugin-undefined-to-void/-/babel-plugin-undefined-to-void-1.1.6.tgz", + "integrity": "sha1-f1eO+LeN+uYAM4XYQXph7aBuL4E=" + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0" + } + }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-self": "6.22.0", + "babel-plugin-transform-react-jsx-source": "6.22.0", + "babel-preset-flow": "6.23.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "requires": { + "babel-core": "6.26.3", + "babel-runtime": "6.26.0", + "core-js": "2.5.7", + "home-or-tmp": "2.0.0", + "lodash": "4.17.10", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.10", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "requires": { + "source-map": "0.5.7" + } + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.7", + "regenerator-runtime": "0.11.1" + }, + "dependencies": { + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + } + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.10" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + } + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.10" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.10", + "to-fast-properties": "1.0.3" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + } + } + }, + "babylon": { + "version": "5.8.38", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-5.8.38.tgz", + "integrity": "sha1-7JsSCxG/bM1Bc6GL8hfmC3mFn/0=" + }, + "background-tips": { + "version": "https://www.atom.io/api/packages/background-tips/versions/0.28.0/tarball", + "integrity": "sha512-mEEkeL6bY6ZSPl7WCHjhJ4KjVUU9UElHb4CB4MhnW4b4mRTHaWR7rnnCVq312wRZ9cwjdvd/5OTXXbD2AQyfYw==", + "requires": { + "underscore-plus": "1.6.8" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base16-tomorrow-dark-theme": { + "version": "https://www.atom.io/api/packages/base16-tomorrow-dark-theme/versions/1.6.0/tarball", + "integrity": "sha512-5h2CeNhHOEG8InVyah+PcANjVOgtWAbpsBHmLfYwhhTU+yKS3ZWbYvnZg6B9A8gDy9Jrmq2ZmnWL47qLDUaztg==" + }, + "base16-tomorrow-light-theme": { + "version": "https://www.atom.io/api/packages/base16-tomorrow-light-theme/versions/1.6.0/tarball", + "integrity": "sha512-pJ/hCD2Tn8kc/9WkFkQnqcow0VtfotrXGjZY+Bmdbzv2EdV5kT25c5UVfUYgfLsVrSs1peUWFmCtHT3RZwtHzA==" + }, + "batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "binary-search": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.4.tgz", + "integrity": "sha512-dPxU/vZLnH0tEVjVPgi015oSwqu6oLfCeHywuFRhBE0yM0mYocvleTl8qsdM1YFhRzTRhM1+VzS8XLDVrHPopg==" + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "2.0.3" + } + }, + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + }, + "bookmarks": { + "version": "https://www.atom.io/api/packages/bookmarks/versions/0.45.1/tarball", + "integrity": "sha512-BcKY7ujoJoQ6x0C0CPeV4e9cw0cqwjlKvCVh3T6XeDwZQ1Na8KMrjPHWp8dO7B1cnGFN1LCWWQGWqGH624Ymkw==", + "requires": { + "atom-select-list": "0.7.2" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "bracket-matcher": { + "version": "https://www.atom.io/api/packages/bracket-matcher/versions/0.89.2/tarball", + "integrity": "sha512-WW3ZdNhb2sioFXk+iGbsQb+mBubjY9/ME7hjkqfl4oOEHr3SqdzFFMdUau6GVr2eeWyROm7B1p0t4aUUwNY+Sw==", + "requires": { + "first-mate": "7.1.1", + "underscore-plus": "1.6.8" + } + }, + "breakable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/breakable/-/breakable-1.0.0.tgz", + "integrity": "sha1-eEp5eRWjjq0nutRWtVcstLuqeME=" + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cached-run-in-this-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cached-run-in-this-context/-/cached-run-in-this-context-0.4.1.tgz", + "integrity": "sha1-CMFYHi2cP2aba92poQCtYdqlRfM=", + "requires": { + "nan": "2.10.0" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "requires": { + "assertion-error": "1.1.0", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "chart.js": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.2.tgz", + "integrity": "sha512-90wl3V9xRZ8tnMvMlpcW+0Yg13BelsGS9P9t0ClaDxv/hdypHDr/YAGf+728m11P5ljwyB0ZHfPKCapZFqSqYA==", + "requires": { + "chartjs-color": "2.2.0", + "moment": "2.22.2" + } + }, + "chartjs-color": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz", + "integrity": "sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=", + "requires": { + "chartjs-color-string": "0.5.0", + "color-convert": "0.5.3" + } + }, + "chartjs-color-string": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz", + "integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==", + "requires": { + "color-name": "1.1.3" + } + }, + "checksum": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/checksum/-/checksum-0.1.1.tgz", + "integrity": "sha1-3GUn1MkL6FYNvR7Uzs8yl9Uo6ek=", + "requires": { + "optimist": "0.3.7" + }, + "dependencies": { + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "requires": { + "wordwrap": "0.0.3" + } + } + } + }, + "cheerio": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.15.0.tgz", + "integrity": "sha1-h3XsOrFvTGYZW5zGeX4MgrUeazQ=", + "requires": { + "CSSselect": "0.4.1", + "entities": "1.0.0", + "htmlparser2": "3.7.3", + "lodash": "2.4.2" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" + } + } + }, + "chevrotain": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-0.18.0.tgz", + "integrity": "sha1-sodxTjFZC64sXR4vYRZz7+xHnYA=" + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "circular-json": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.5.tgz", + "integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==" + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, + "clear-cut": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clear-cut/-/clear-cut-2.0.2.tgz", + "integrity": "sha1-CC2zLsqkSjWKewhoUv4dVIC77tE=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==" + }, + "coffeestack": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/coffeestack/-/coffeestack-1.1.2.tgz", + "integrity": "sha1-NSePO+uc5vXQraH7bgh4UrZXzpg=", + "requires": { + "coffee-script": "1.8.0", + "fs-plus": "2.10.1", + "source-map": "0.1.43" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "coffee-script": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.8.0.tgz", + "integrity": "sha1-nJ8dK0pSoADe0Vtll5FwNkgmPB0=", + "requires": { + "mkdirp": "0.3.5" + } + }, + "fs-plus": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-2.10.1.tgz", + "integrity": "sha1-MgR4HXhAYR5jZOe2+wWMljJ8WqU=", + "requires": { + "async": "1.5.2", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "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" + } + } + } + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "color": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/color/-/color-0.7.3.tgz", + "integrity": "sha1-qzrkvGy4z62110nEDzSuoIgQT4k=", + "requires": { + "color-convert": "0.5.3", + "color-string": "0.2.4" + } + }, + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.2.4.tgz", + "integrity": "sha1-Ih/2QjT3Gqo+E7yMfoyV883Y+Bo=", + "requires": { + "color-name": "1.0.1" + }, + "dependencies": { + "color-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.0.1.tgz", + "integrity": "sha1-azSyspt3FgE5crC51b7c+7Zxjfg=" + } + } + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "command-palette": { + "version": "https://www.atom.io/api/packages/command-palette/versions/0.43.5/tarball", + "integrity": "sha512-aEs5dLDyXmdoXP2EjUJoZ3lJCpvbzCg45+GehXquccHzxip1JQCZA67NTSf/ePAWncin+kvqJMm0uoZ37rgrtg==", + "requires": { + "atom-select-list": "0.7.2", + "fuzzaldrin": "2.1.0", + "fuzzaldrin-plus": "0.6.0", + "underscore-plus": "1.6.8" + } + }, + "commander": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", + "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==" + }, + "commoner": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", + "integrity": "sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=", + "requires": { + "commander": "2.16.0", + "detective": "4.7.1", + "glob": "5.0.15", + "graceful-fs": "4.1.11", + "iconv-lite": "0.4.23", + "mkdirp": "0.5.1", + "private": "0.1.8", + "q": "1.5.1", + "recast": "0.11.23" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "requires": { + "ast-types": "0.9.6", + "esprima": "3.1.3", + "private": "0.1.8", + "source-map": "0.5.7" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "compare-sets": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/compare-sets/-/compare-sets-1.0.1.tgz", + "integrity": "sha1-me1EydezCN54Uv8RFJcr1Poj5yc=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "optional": true, + "requires": { + "boom": "2.10.1" + } + }, + "cson-parser": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-1.3.5.tgz", + "integrity": "sha1-fsZ14DkUVTO/KmqFYHPxWZ2cLSQ=", + "requires": { + "coffee-script": "1.12.7" + } + }, + "ctags": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ctags/-/ctags-3.0.0.tgz", + "integrity": "sha1-sLckF9B0ZRcqiZ0C9y8/wnP4KjY=", + "requires": { + "event-stream": "3.1.7", + "nan": "2.10.0" + } + }, + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "requires": { + "es5-ext": "0.10.45" + } + }, + "dalek": { + "version": "https://www.atom.io/api/packages/dalek/versions/0.2.2/tarball", + "integrity": "sha512-7p7KFZFakk54JTKiP/gsXaEMAcsO30Y5dT3lrHZG3jeAMg201YSq5ayAd735i79S/RbpH32X5DaE6XC3Qf9BSw==", + "requires": { + "grim": "2.0.2" + }, + "dependencies": { + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "1.0.1" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=" + } + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "defs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/defs/-/defs-1.1.1.tgz", + "integrity": "sha1-siYJ8sehG6ej2xFoBcE5scr/qdI=", + "requires": { + "alter": "0.2.0", + "ast-traverse": "0.1.1", + "breakable": "1.0.0", + "esprima-fb": "15001.1001.0-dev-harmony-fb", + "simple-fmt": "0.1.0", + "simple-is": "0.2.0", + "stringmap": "0.2.2", + "stringset": "0.2.1", + "tryor": "0.1.2", + "yargs": "3.27.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "yargs": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.27.0.tgz", + "integrity": "sha1-ISBUaTFuk5Ex1Z8toMbX+YIh6kA=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "delegato": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegato/-/delegato-1.0.0.tgz", + "integrity": "sha1-xzJK2/Mfo9ltH9YL82jF/MomlRA=", + "requires": { + "mixto": "1.0.0" + } + }, + "deprecation-cop": { + "version": "https://www.atom.io/api/packages/deprecation-cop/versions/0.56.9/tarball", + "integrity": "sha512-dTKNhWcDgK6Y5cR8dwZ507QW15lob+Lp//P71wXoTVidXboDqH13Y1yQ7Av5qASscv7fqp5GcvLhQWF55W5yng==", + "requires": { + "etch": "0.9.0", + "fs-plus": "3.0.2", + "grim": "2.0.2", + "marked": "0.3.19", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "etch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.0.tgz", + "integrity": "sha1-CSJpiPLO4GkL3yCMyyXkFNXfrV8=" + }, + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "detect-indent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz", + "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=", + "requires": { + "get-stdin": "4.0.1", + "minimist": "1.2.0", + "repeating": "1.1.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "requires": { + "acorn": "5.7.1", + "defined": "1.0.0" + } + }, + "dev-live-reload": { + "version": "https://www.atom.io/api/packages/dev-live-reload/versions/0.48.1/tarball", + "integrity": "sha512-YSOLkdz7d/pETiG3raCzRKFmv64aErVC2d0cwDi7SLGtJyIGoR9+0OHMZjl8kcXCrX+u1s7awD8HhTDfZ56+iw==", + "requires": { + "fs-plus": "3.0.2" + } + }, + "devtron": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/devtron/-/devtron-1.3.0.tgz", + "integrity": "sha1-aaHFk5tmlrMSB1TMYMmAc9JNNic=", + "requires": { + "highlight.js": "9.12.0", + "humanize-plus": "1.8.2" + } + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=" + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" + }, + "domhandler": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.2.1.tgz", + "integrity": "sha1-Wd+dzSJ+gIs2Wuc+H2aErD2Ub8I=", + "requires": { + "domelementtype": "1.3.0" + } + }, + "dompurify": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-1.0.7.tgz", + "integrity": "sha512-1xK0JEda/jvIm3SgqHXKvRCh3AbEKCyBbUAGpNCMVIljBD145cPvBR66JSj3O4SdscFUx5NXsDkJpz6vDT8KLg==" + }, + "domutils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz", + "integrity": "sha1-CGVRN5bGswYDGFDhdVFrr4C3Km8=", + "requires": { + "domelementtype": "1.3.0" + } + }, + "dugite": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/dugite/-/dugite-1.73.0.tgz", + "integrity": "sha512-gM/DzOdu1LfPk7XLItR+wHDfj5HU5A6UW7b/mW/7fJIbpAx9kjvjE9k1M6S6i2rznfoyWFP/Gb19f2F4LSXkkQ==", + "requires": { + "checksum": "0.1.1", + "mkdirp": "0.5.1", + "progress": "2.0.0", + "request": "2.88.0", + "rimraf": "2.6.2", + "tar": "4.4.6" + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "element-resize-detector": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.1.14.tgz", + "integrity": "sha1-rwZKCmGKggrVcKlcXuxbd74BKME=", + "requires": { + "batch-processor": "1.0.0" + } + }, + "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.4", + "mixto": "1.0.0", + "property-accessors": "1.1.3", + "underscore-plus": "1.6.8" + } + }, + "emoji-images": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/emoji-images/-/emoji-images-0.0.2.tgz", + "integrity": "sha1-SJDwkf6rLldUWNINLp74hnBg5BU=" + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.23" + } + }, + "encoding-selector": { + "version": "https://www.atom.io/api/packages/encoding-selector/versions/0.23.9/tarball", + "integrity": "sha512-gR6sTS2/yyrGolNG9pTG8H7XviOzfzoI6NO//qAm2wyEVipbOWZIi2P+CW6Mh21+MTpXO8cvEMniXXtxghC4BA==", + "requires": { + "atom-select-list": "0.7.2", + "iconv-lite": "0.4.23", + "jschardet": "1.6.0" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "optional": true, + "requires": { + "prr": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.45", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "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=", + "requires": { + "es5-ext": "0.10.45" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45", + "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=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.45" + } + } + } + }, + "es6-iterator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "integrity": "sha1-1vWLjE/EE8JJtLqhl2j45NfIlE4=", + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.45", + "es6-symbol": "2.0.1" + } + }, + "es6-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "integrity": "sha1-dhtcZ8/U8dGK+yNPaR1nhoLLO/M=", + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.45" + } + }, + "es6-weak-map": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", + "integrity": "sha1-cGzvnpmqI2undmwjnIueKG6n0ig=", + "requires": { + "d": "0.1.1", + "es5-ext": "0.10.45", + "es6-iterator": "0.1.3", + "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=" + }, + "esprima-fb": { + "version": "15001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etch": { + "version": "0.12.8", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.12.8.tgz", + "integrity": "sha1-wkvJvTphSPYiBM6GQ9Lombnsud4=" + }, + "event-kit": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/event-kit/-/event-kit-2.5.0.tgz", + "integrity": "sha512-tUDxeNC9JzN2Tw/f8mLtksY34v1hHmaR7lV7X4p04XSjaeUhFMfzjF6Nwov9e0EKGEx63BaKcgXKxjpQaPo0wg==" + }, + "event-stream": { + "version": "3.1.7", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.1.7.tgz", + "integrity": "sha1-tMVAAS0P4UmEIPPYlGAI22OTw3o=", + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.2.10", + "stream-combiner": "0.0.4", + "through": "2.3.8" + }, + "dependencies": { + "split": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", + "requires": { + "through": "2.3.8" + } + } + } + }, + "exception-reporting": { + "version": "https://www.atom.io/api/packages/exception-reporting/versions/0.43.1/tarball", + "integrity": "sha512-IYDPs9MNXcbKJv+G/WH6FqkbikiaP9VBskWatMjCj6ca7aey0bbK/qEQwaMogzEGwh9C+n7f+4fAarpgWNKpsw==", + "requires": { + "fs-plus": "3.0.2", + "node-uuid": "1.4.8", + "stack-trace": "0.0.9", + "underscore-plus": "1.6.8" + } + }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "optional": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.4.0", + "object-assign": "4.1.1", + "promise": "7.3.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.18" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "1.2.0" + } + }, + "fileset": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.1.8.tgz", + "integrity": "sha1-UGuRqTluqn4y+0KoQHfHoMc2t0E=", + "requires": { + "glob": "3.2.11", + "minimatch": "0.4.0" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + }, + "dependencies": { + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "minimatch": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.4.0.tgz", + "integrity": "sha1-vSx9Bg0sjI/Xzefx8u0tWycP2xs=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "find-and-replace": { + "version": "https://www.atom.io/api/packages/find-and-replace/versions/0.215.12/tarball", + "integrity": "sha512-LASeKxjBD4duvI09jREDZkY9osbJtN97rZn6ko2F3Dr83TxR9NYqTRbea6bX3ZXsSf2e/dkbVx1jjM59Z6yMMw==", + "requires": { + "binary-search": "1.3.4", + "element-resize-detector": "1.1.14", + "etch": "0.9.3", + "fs-plus": "3.0.2", + "temp": "0.8.3", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "etch": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.3.tgz", + "integrity": "sha1-2uxSmVv2E1A9a5K0H1Si6qEuMis=" + } + } + }, + "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=" + }, + "first-mate": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/first-mate/-/first-mate-7.1.1.tgz", + "integrity": "sha512-Y3qum/WZt0V3uVaQnuoUqBiNXT8WA156ofqp1WTMjUsbUgrXso10vdRl8HzsFbQSjN06u3Q1r2Duo1RM+RqTAA==", + "requires": { + "emissary": "1.3.3", + "event-kit": "2.5.0", + "fs-plus": "3.0.2", + "grim": "2.0.2", + "oniguruma": "6.2.1", + "season": "6.0.2", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" + }, + "focus-trap": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-2.4.5.tgz", + "integrity": "sha512-jkz7Dh6Pb4ox+z24GhVABDE7lFT19z7KVrpYGH5qqI6KK3Y2IcXhBx844W6ZXYahD+jOEUcGz49dLakXg2sjOQ==", + "requires": { + "tabbable": "1.1.3" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "requires": { + "samsam": "1.1.2" + } + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, + "fs-admin": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/fs-admin/-/fs-admin-0.1.6.tgz", + "integrity": "sha512-JHRSPVRBrYggAGM6kpvNvFdxuFmoDxamnBVQT/JApZtVji7bHKbhLOka1Y2pNSQ/OVChbmZFKcWdpwuZEpA65w==", + "requires": { + "mocha": "3.5.3", + "nan": "2.10.0" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + } + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "requires": { + "minipass": "2.3.4" + } + }, + "fs-plus": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-3.0.2.tgz", + "integrity": "sha1-a19Sp3EolMTd6f2PgfqMYN8EHz0=", + "requires": { + "async": "1.5.2", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "fs-readdir-recursive": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz", + "integrity": "sha1-MVtPuMHKW4xH3v7zGdBz2tNWgFk=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fstream": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.24.tgz", + "integrity": "sha1-Jn/p0DT0a8mfgkeJ04uYetAb6IQ=", + "requires": { + "graceful-fs": "2.0.3", + "inherits": "2.0.3", + "mkdirp": "0.3.5", + "rimraf": "2.6.2" + }, + "dependencies": { + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=" + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" + } + } + }, + "fuzzaldrin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz", + "integrity": "sha1-kCBMPi/appQbso0WZF1BgGOpDps=" + }, + "fuzzaldrin-plus": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/fuzzaldrin-plus/-/fuzzaldrin-plus-0.6.0.tgz", + "integrity": "sha1-gy9kifvodnaUWVmckUpnDsIpR+4=" + }, + "fuzzy-finder": { + "version": "https://www.atom.io/api/packages/fuzzy-finder/versions/1.8.2/tarball", + "integrity": "sha512-wg3uX5fPtVItOByflO+vsQKHAqn3aSgutYM+xO3lEKQov9DuMdtMzMgbf/Tlam0YwjV+Qz/JV10LluJuliP03A==", + "requires": { + "async": "0.2.6", + "atom-select-list": "0.7.2", + "fs-plus": "3.0.2", + "fuzzaldrin": "2.1.0", + "fuzzaldrin-plus": "0.6.0", + "humanize-plus": "1.8.2", + "minimatch": "3.0.4", + "temp": "0.8.3", + "underscore-plus": "1.6.8", + "wrench": "1.5.9" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, + "gaze": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.3.4.tgz", + "integrity": "sha1-X5S92gr+U7xxCWm81vKCVI1gwnk=", + "requires": { + "fileset": "0.1.8", + "minimatch": "0.2.14" + }, + "dependencies": { + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "get-parameter-names": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/get-parameter-names/-/get-parameter-names-0.2.0.tgz", + "integrity": "sha1-ohY60JLjUNlL7ilYl0/OzhvFPJk=" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "git-diff": { + "version": "https://www.atom.io/api/packages/git-diff/versions/1.3.9/tarball", + "integrity": "sha512-BVo2faEzrjXdoesTl7CjVfjQawmCCTd6rzaWwernVDfsMz+xSAH5Yig5ukLYWzav13Tqt2su7pOtPQgp0af4yg==", + "requires": { + "atom-select-list": "0.7.2", + "fs-plus": "3.0.2", + "temp": "0.8.3" + } + }, + "git-utils": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/git-utils/-/git-utils-5.2.1.tgz", + "integrity": "sha512-PrXaX4qb6ti9yU4p15RWeWklHdyEXCEIcdjbm3X5mAWL1VCFpl1hPdxk7T2qcFRNhF7TVXq3giotnJVne+1htA==", + "requires": { + "fs-plus": "3.0.2", + "nan": "2.10.0" + } + }, + "github": { + "version": "https://www.atom.io/api/packages/github/versions/0.19.0/tarball", + "integrity": "sha512-JnAQGVCBXAmVW7qIrgw6a41G4MRAPIa81Mx3oFtnlZYC77sFA2vd6eUnWhujHBZpK1q2HmlihVsAhpvDKdkk0A==", + "requires": { + "atom-babel6-transpiler": "1.2.0", + "babel-generator": "6.26.1", + "babel-plugin-chai-assert-async": "0.1.0", + "babel-plugin-relay": "1.6.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-object-rest-spread": "6.26.0", + "babel-preset-react": "6.24.1", + "bytes": "3.0.0", + "classnames": "2.2.6", + "compare-sets": "1.0.1", + "dugite": "1.73.0", + "event-kit": "2.5.0", + "fs-extra": "4.0.3", + "graphql": "0.13.2", + "keytar": "4.2.1", + "lodash.memoize": "4.1.2", + "moment": "2.22.2", + "node-emoji": "1.8.1", + "prop-types": "15.6.2", + "react": "16.4.0", + "react-dom": "16.4.0", + "react-relay": "1.6.0", + "react-select": "1.2.1", + "relay-runtime": "1.6.0", + "temp": "0.8.3", + "tinycolor2": "1.4.1", + "tree-kill": "1.2.0", + "what-the-diff": "0.4.0", + "what-the-status": "1.0.3", + "yubikiri": "1.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.2" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "4.1.11" + } + } + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globals": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-6.4.1.tgz", + "integrity": "sha1-hJgDKzttHMge68X3lpDY/in6v08=" + }, + "go-to-line": { + "version": "https://www.atom.io/api/packages/go-to-line/versions/0.33.0/tarball", + "integrity": "sha512-YD5zEkGQRTl6jrgAIOQ0Zr0rB/f/yPifxhz4od2kN+JfGVeb76xD9FG5OkR9dr0vEtPfJeDbG2WWTJ1JGMShqQ==" + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "grammar-selector": { + "version": "https://www.atom.io/api/packages/grammar-selector/versions/0.50.1/tarball", + "integrity": "sha512-tXoxzu+RtJffRc6no/KsIyI9YX1qfpuQjmMI3RJ42qPHtGk54RsEpAuFku8oOW4sIrSy5c7suM7iKmh4aUnsZg==", + "requires": { + "atom-select-list": "0.7.2" + } + }, + "graphql": { + "version": "0.13.2", + "resolved": "http://registry.npmjs.org/graphql/-/graphql-0.13.2.tgz", + "integrity": "sha512-QZ5BL8ZO/B20VA8APauGBg3GyEgZ19eduvpLWoq5x7gMmWnHoy8rlQWPLmWgFvo1yNgjSEFMesmS4R6pPr7xog==", + "requires": { + "iterall": "1.2.2" + } + }, + "grim": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/grim/-/grim-1.5.0.tgz", + "integrity": "sha1-sysI71Z88YUvgXWe2caLDXE5ajI=", + "requires": { + "emissary": "1.3.3" + } + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "optional": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=" + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "home-or-tmp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz", + "integrity": "sha1-S58eQIAMPlDGwn94FnavzOcfOYU=", + "requires": { + "os-tmpdir": "1.0.2", + "user-home": "1.1.1" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "htmlparser2": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.7.3.tgz", + "integrity": "sha1-amTHdjfAjG8w7CqBV6UzM758sF4=", + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.2.1", + "domutils": "1.5.1", + "entities": "1.0.0", + "readable-stream": "1.1.14" + }, + "dependencies": { + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "humanize-plus": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/humanize-plus/-/humanize-plus-1.8.2.tgz", + "integrity": "sha1-pls0RZrWNnrbs3B6gqPJ+RYWcDA=" + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "requires": { + "minimatch": "3.0.4" + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "optional": true + }, + "image-view": { + "version": "https://www.atom.io/api/packages/image-view/versions/0.63.1/tarball", + "integrity": "sha512-KMtreZG1QLdCiCmkoHPKnP54oe2mEXDyoliM0wYTsVvaTOIfXW6Gi1rbQgGClqi+iHHWOBFKuJdmVGj/phbK9Q==", + "requires": { + "bytes": "2.5.0", + "etch": "0.9.0", + "fs-plus": "3.0.2", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "bytes": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.5.0.tgz", + "integrity": "sha1-TJQj6i0lLCcMQbK97+/5u2tiwGo=" + }, + "etch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.0.tgz", + "integrity": "sha1-CSJpiPLO4GkL3yCMyyXkFNXfrV8=" + } + } + }, + "incompatible-packages": { + "version": "https://www.atom.io/api/packages/incompatible-packages/versions/0.27.3/tarball", + "integrity": "sha512-OlkFBSpvHH7dUfYQTlcgTXEa+sjr9Es8d2lNPGPS2O5Rp5MiRKcnovQoMtaF3fkcuV2O7onim45ldFjbl4qdog==", + "requires": { + "etch": "0.12.8" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "1.4.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-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "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", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-integer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-integer/-/is-integer-1.0.7.tgz", + "integrity": "sha1-a96Bqs3feLZZtmKdYpytxRqIbVw=", + "requires": { + "is-finite": "1.0.2" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-2.0.4.tgz", + "integrity": "sha1-0jWS5qbwk++4TC5hUgVr4pTkFKE=" + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "1.7.3", + "whatwg-fetch": "2.0.4" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "iterall": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz", + "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=" + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" + } + } + }, + "jasmine-focused": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/jasmine-focused/-/jasmine-focused-1.0.7.tgz", + "integrity": "sha1-uDx1fIAOaOHW78GjoaE/85/23NI=", + "requires": { + "jasmine-node": "git+https://github.com/kevinsawicki/jasmine-node.git#81af4f953a2b7dfb5bde8331c05362a4b464c5ef", + "underscore-plus": "1.6.8", + "walkdir": "0.0.7" + } + }, + "jasmine-json": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/jasmine-json/-/jasmine-json-0.0.3.tgz", + "integrity": "sha1-Xi6P1QqlhXAOjzWa9pawupZPg4c=" + }, + "jasmine-node": { + "version": "git+https://github.com/kevinsawicki/jasmine-node.git#81af4f953a2b7dfb5bde8331c05362a4b464c5ef", + "requires": { + "coffee-script": "1.12.7", + "coffeestack": "1.1.2", + "gaze": "0.3.4", + "jasmine-reporters": "1.1.0", + "mkdirp": "0.3.5", + "requirejs": "2.3.5", + "underscore": "1.8.3", + "walkdir": "0.0.7" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" + } + } + }, + "jasmine-reporters": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-1.1.0.tgz", + "integrity": "sha1-8zUIhYkMntqtEqCHxi8swZ3PZsA=", + "requires": { + "mkdirp": "0.3.5" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" + } + } + }, + "jasmine-tagged": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/jasmine-tagged/-/jasmine-tagged-1.1.4.tgz", + "integrity": "sha1-vLlH2cWYWEolZRr8pXoT7YvvdNc=", + "requires": { + "jasmine-focused": "1.0.7" + } + }, + "js-base64": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.6.tgz", + "integrity": "sha512-O9SR2NVICx6rCqh1qsU91QZ5IoNa+2T1ROJ0OQlfvATKGmnjsAvg3r0E5ufPZ4a95jdKTPXhFWiE/sOZ7a5Rtg==" + }, + "js-tokens": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.1.tgz", + "integrity": "sha1-zENaXIuUrRWst5gxQPyAGCyJrq4=" + }, + "js-yaml": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "requires": { + "argparse": "1.0.10", + "esprima": "2.7.3" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jschardet": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz", + "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==" + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "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=", + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + }, + "json5": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", + "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "optional": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "key-path-helpers": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/key-path-helpers/-/key-path-helpers-0.4.0.tgz", + "integrity": "sha1-6H9qFZFErfJpLkbypGQc4mnAkRk=" + }, + "keybinding-resolver": { + "version": "https://www.atom.io/api/packages/keybinding-resolver/versions/0.38.2/tarball", + "integrity": "sha512-8D34ekA01kvIJyFqvwABK9J9FcQCoWaC2hLh99Tkf1h8DhPE6hkPuu6qb1tQucyVa4PYXuOA3jH9myGwJ2gWxw==", + "requires": { + "etch": "0.9.0", + "fs-plus": "3.0.2", + "temp": "0.8.3" + }, + "dependencies": { + "etch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.0.tgz", + "integrity": "sha1-CSJpiPLO4GkL3yCMyyXkFNXfrV8=" + } + } + }, + "keyboard-layout": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/keyboard-layout/-/keyboard-layout-2.0.13.tgz", + "integrity": "sha512-WxVc3bBITttHozSyEYPsyr5rN2KQuXtEaXMlQfQjEze1JrkLw30yH/bcNn1IGx48b+tdOdybpnq++JFLU2FaZg==", + "requires": { + "event-kit": "2.5.0", + "nan": "2.10.0" + } + }, + "keytar": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-4.2.1.tgz", + "integrity": "sha1-igamV3/fY3PgqmsRInfmPex3/RI=", + "requires": { + "nan": "2.8.0", + "prebuild-install": "2.5.3" + }, + "dependencies": { + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=" + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "language-c": { + "version": "https://www.atom.io/api/packages/language-c/versions/0.60.4/tarball", + "integrity": "sha512-6sgQUlfjGKkLcaMgz4hfRjty+JSYBUjDow7ayBOc+k87cB2UWn0skbvq4bwRZDf0bMUtmrJkDieagQGrsTW8DQ==", + "requires": { + "tree-sitter-c": "0.13.4", + "tree-sitter-cpp": "0.13.4" + } + }, + "language-clojure": { + "version": "https://www.atom.io/api/packages/language-clojure/versions/0.22.7/tarball", + "integrity": "sha512-HJfBRKbzOYGlEVQNnnRtx0BgiZ9pHlUioHUtG9pFV65EgO4jm4Q5cPHLDvBj+zEy0cm28eYgEYFjfacyBaZElg==" + }, + "language-coffee-script": { + "version": "https://www.atom.io/api/packages/language-coffee-script/versions/0.49.3/tarball", + "integrity": "sha512-2xXcSiiRySd0qE4lhsOTqMwcKlBVKc/0ru9HHGJSeTdp/On9iNrkcM1+asDYa/QmvppgAILC2/0xUS6+B/cnqQ==" + }, + "language-csharp": { + "version": "https://www.atom.io/api/packages/language-csharp/versions/1.1.0/tarball", + "integrity": "sha512-37RDzLiqSHJjopFg3T/Sqntx793OMQ4o7tkf3IuKe68Mshz3mwavJhIaIX/mca+0u/aWquySJFzlZ4D8EdtRSA==" + }, + "language-css": { + "version": "https://www.atom.io/api/packages/language-css/versions/0.42.11/tarball", + "integrity": "sha512-cvEdst9Q6wa9OLnMZksVBecb/gCPNXnGfKgyqQjHPKKl1WGFhpcPV+pVuOc4OdeF22Q6lH6fDBYv2rNjeioVsA==" + }, + "language-gfm": { + "version": "https://www.atom.io/api/packages/language-gfm/versions/0.90.5/tarball", + "integrity": "sha512-LqDgDy9hlu2yxL6Cobq7LWHZp7RkxWVngZ+Ga0b8aU9tGZvzsEoTm0pa8Z71c+f1UhwStNgPKFH4mHd8G4rb2g==" + }, + "language-git": { + "version": "https://www.atom.io/api/packages/language-git/versions/0.19.1/tarball", + "integrity": "sha512-xvsGO/d3/XsKJmwdAz9VGHo6t7A13VuJeuEoZaoLmvzwkVpFdpJcK8PNwVMPHav+lpNeu73qiXmqS+YIlvLwLQ==" + }, + "language-go": { + "version": "https://www.atom.io/api/packages/language-go/versions/0.46.2/tarball", + "integrity": "sha512-78llnZAhiNaMwshN9dvVaZ4kn5Sgne6CaZnI/pJJEGtWoaQJApNVHWWljpUVyGMBnI5tEIGIZD9ktO6zZXPteg==", + "requires": { + "tree-sitter-go": "0.13.1" + } + }, + "language-html": { + "version": "https://www.atom.io/api/packages/language-html/versions/0.51.5/tarball", + "integrity": "sha512-ZzYdXsmbcKpRHvkq2SyWVByVmzsVAx6UquYOFlN5R51Wn21WeAIHhvf0sz54WntkTXOCGoaII/4sLxrkeqNEKw==", + "requires": { + "atom-grammar-test": "0.6.4", + "tree-sitter-embedded-template": "0.13.0", + "tree-sitter-html": "0.13.4" + } + }, + "language-hyperlink": { + "version": "https://www.atom.io/api/packages/language-hyperlink/versions/0.16.3/tarball", + "integrity": "sha512-IDkh820N85GVgcP0EiU2QceAcmRHyYQCzJkaG7eSwWmOxvf5e+bO9g2U28sED14hQjH+No4MRfU5+grEmAnvuw==" + }, + "language-java": { + "version": "https://www.atom.io/api/packages/language-java/versions/0.30.0/tarball", + "integrity": "sha512-x0AmmqK0Q3YWUH7XhIvIiqY+0E54mj3y4pXP5QjdDpkdDE3D9eZno/J+DiNmpiP5/l8+MV0Qas/DsZoK/HgulQ==" + }, + "language-javascript": { + "version": "https://www.atom.io/api/packages/language-javascript/versions/0.129.9/tarball", + "integrity": "sha512-EW1MkZw1Vu67ZlEP73YemVwLyhPcBI1WXQAXY1piUksTjGWFDhHRl+SJRVXvad2c4dGeIqAbMu5bGwjqiTEH9g==", + "requires": { + "tree-sitter-javascript": "0.13.5", + "tree-sitter-regex": "0.13.0" + } + }, + "language-json": { + "version": "https://www.atom.io/api/packages/language-json/versions/0.19.2/tarball", + "integrity": "sha512-iJtZm5+vulzXeXgW4ig+8fGk1okZGCZPqlQwOGwlrQosLPx/h+fAhlZEAr4qt20hn8W9EFw/bUprf48XdJpVoQ==" + }, + "language-less": { + "version": "https://www.atom.io/api/packages/language-less/versions/0.34.2/tarball", + "integrity": "sha512-JEmNAPFFGXI1anCIB0ow96yUQAyQiIv9BfWBEZWxZVe3RrbfejTlg0ly2+ORbJhszFeKuIIQhUxJNzfY3KhXBA==" + }, + "language-make": { + "version": "https://www.atom.io/api/packages/language-make/versions/0.22.3/tarball", + "integrity": "sha512-G0KOZdbmApr253liQPN/4QjAg3Of06P2iJs9qGXStc8zz7dl++ZVcNmIrRCnS3EqmU/3Ui+678f2tK+urBpqtA==" + }, + "language-mustache": { + "version": "https://www.atom.io/api/packages/language-mustache/versions/0.14.5/tarball", + "integrity": "sha512-1aC1OAoYye+krEJ8t5RzXiLYTEA/RJ/Igv1efDsuxvZHnIkdrSDzS/UsssS3snqPkIGyLI+htRvU/v11famx6A==" + }, + "language-objective-c": { + "version": "https://www.atom.io/api/packages/language-objective-c/versions/0.15.1/tarball", + "integrity": "sha512-ZKlTy/xiyb+J7DnHztzM/ss8/rtwbPskSpd+Ox1gKc0k+NpiU7rmzfW6ki9/t/kFHGo1qX7QiImvdCavJ2LsgQ==" + }, + "language-perl": { + "version": "https://www.atom.io/api/packages/language-perl/versions/0.38.1/tarball", + "integrity": "sha512-XXHULyFvbxAiRoj+MxIXoeO//in3bQctHZbaD72p3vFxm3klxe2ebx7b3cFmFYqf/g0eajmLrR3tR5m1Rmz1XQ==" + }, + "language-php": { + "version": "https://www.atom.io/api/packages/language-php/versions/0.44.0/tarball", + "integrity": "sha512-sbspgPSLoe2SefY/tUMvu97MDJCLjretIicR2Rducf0DKWW38NpdHztP12DhKbaITmnix1LGDP/5pGsj20mISw==" + }, + "language-property-list": { + "version": "https://www.atom.io/api/packages/language-property-list/versions/0.9.1/tarball", + "integrity": "sha512-HD6HI41u57i0/Tu9catiriURhJsef0RDrzJDkGDtdFkE9F9KPxC9Fayq2JBLJrhIyADRVXFxwxsfwQ2Jmh6hxg==" + }, + "language-python": { + "version": "https://www.atom.io/api/packages/language-python/versions/0.51.4/tarball", + "integrity": "sha512-jSH0CCk+S3nvvKcDh2lqPP+OHsQYSedCy1JSOYirXVfXErwFMzbSIIZY8y+ChU+AvKDPUR2UOpe4uHPVQD2KDQ==", + "requires": { + "atom-grammar-test": "0.6.4", + "tree-sitter-python": "0.13.4" + } + }, + "language-ruby": { + "version": "https://www.atom.io/api/packages/language-ruby/versions/0.72.7/tarball", + "integrity": "sha512-k9wv7C/IVYoAP4EZ7DOQ4bGGu5pwaimCjSm6S1OqJZVz/R211f9W40VyfYyzpJ1n3LXPoEAIEDi1UVYcoSYIMw==", + "requires": { + "tree-sitter-ruby": "0.13.8" + } + }, + "language-ruby-on-rails": { + "version": "https://www.atom.io/api/packages/language-ruby-on-rails/versions/0.25.3/tarball", + "integrity": "sha512-uI4ItSsq1J0/5gBblVgLv69C8TzWMcAoL19H8iFuosWWDRUsh9va1PrPMLeSNnNbnOYkw2fE53fqLlJjrgxiGw==" + }, + "language-sass": { + "version": "https://www.atom.io/api/packages/language-sass/versions/0.62.0/tarball", + "integrity": "sha512-qaH8BDNBOkpbR4thmcRimEphnrzzhpDxeQM+WCM3Unp3a8r3aV2xcY9LlvbZxpclz8TOUyvuc5qgj1YI//ge9w==" + }, + "language-shellscript": { + "version": "https://www.atom.io/api/packages/language-shellscript/versions/0.27.4/tarball", + "integrity": "sha512-c/4QgfPLd8+yX0fHMD5F8DIohTFmNfexE0bZ/IH2n4uS6+BIrIAbud+jmFxjSv/Bii7xsLMss0bca1jjXuwO9w==", + "requires": { + "tree-sitter-bash": "0.13.2" + } + }, + "language-source": { + "version": "https://www.atom.io/api/packages/language-source/versions/0.9.0/tarball", + "integrity": "sha512-Uu/C5EQKdKgwUOiCWM95CkCUePhT93KpiqsrVqEgTV1TssLY/LRwT9fd1XJSZ5EDKSS71Tfzvbww/V117uoDWw==" + }, + "language-sql": { + "version": "https://www.atom.io/api/packages/language-sql/versions/0.25.10/tarball", + "integrity": "sha512-JXlwc9wV0qnhLn2fe3xRSNghxy/MtmCgy5+6xXN3Dqr9f6Q9Jh4vy3Kwrhz4xSgpPcHMocQwS72JcFuTI9CRdw==" + }, + "language-text": { + "version": "https://www.atom.io/api/packages/language-text/versions/0.7.4/tarball", + "integrity": "sha512-XPmROjdb8CvAznbyiDYNeJi0hKZegBA84bAyTSt/FbZR0enexxk+5NDlyjqYsmR7A1P+LtcMJJZdQYPgXr7mdw==" + }, + "language-todo": { + "version": "https://www.atom.io/api/packages/language-todo/versions/0.29.4/tarball", + "integrity": "sha512-mdSeM6hR7D9ZohrfMTA9wDH46MQbcbfTMxU5WpzYwvQXAvYEZyuhc2dzWZ827VsSOrUcOcAYVcOvTkTrx9nytg==" + }, + "language-toml": { + "version": "https://www.atom.io/api/packages/language-toml/versions/0.18.2/tarball", + "integrity": "sha512-r6eUkKAcfMa2Xv41zHILIZacf7TauLQH2D/lWl3CYekN1DcUMPPuyhUHutV/BpWX3wy5ZDXhhtIHFK4zsAyWtA==" + }, + "language-typescript": { + "version": "https://www.atom.io/api/packages/language-typescript/versions/0.4.6/tarball", + "integrity": "sha512-YEda7Z3azcmHVPhSmlUz6jtE/QviBxxyJdLiBU6sf+SEqE5Rb22XW/+pBi8xBPxBVtZ9O7GOtlVMWO9C3MJziw==", + "requires": { + "tree-sitter-typescript": "0.13.3" + } + }, + "language-xml": { + "version": "https://www.atom.io/api/packages/language-xml/versions/0.35.2/tarball", + "integrity": "sha512-N7Ptj3GRUVYZpE9AuLRglSoKv1eAzcEUCbkzOFfCBEeBGo5dGJJL7LRr2y6HXJYh/V7VdrGyhBbhIeu1WB//Eg==" + }, + "language-yaml": { + "version": "https://www.atom.io/api/packages/language-yaml/versions/0.32.0/tarball", + "integrity": "sha512-kx6Qj//j3PuFaf8yhlfPGdirRJ3NVvLJw+9Oi2Gg998K6vG/XecgvwyP5jVs4xExX8eYMOTlvN7n6dgkPf6LHQ==" + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "less": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", + "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", + "requires": { + "errno": "0.1.7", + "graceful-fs": "4.1.11", + "image-size": "0.5.5", + "mime": "1.6.0", + "mkdirp": "0.5.1", + "promise": "7.3.1", + "request": "2.81.0", + "source-map": "0.5.7" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "optional": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "optional": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "optional": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.2", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "optional": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "optional": true + } + } + }, + "less-cache": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/less-cache/-/less-cache-1.1.0.tgz", + "integrity": "sha1-fi9rOV+lx6l0N0kFyFjy0+nRUyA=", + "requires": { + "fs-plus": "3.0.2", + "less": "2.7.3", + "underscore-plus": "1.6.8", + "walkdir": "0.0.11" + }, + "dependencies": { + "walkdir": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", + "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=" + } + } + }, + "leven": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/leven/-/leven-1.0.2.tgz", + "integrity": "sha1-kUS27ryl8dBoAWnxpncNzqYLdcM=" + }, + "line-ending-selector": { + "version": "https://www.atom.io/api/packages/line-ending-selector/versions/0.7.7/tarball", + "integrity": "sha512-cep3HJDiR3NI3WCO+j2L7ZGnCr34hPUJmmDZtU21S/ntGO9xaBx0EfmAgtF4W9sX2rKDWZHhVDRF/zEGOXOnmA==", + "requires": { + "atom-select-list": "0.7.2", + "underscore-plus": "1.6.8" + } + }, + "line-top-index": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/line-top-index/-/line-top-index-0.3.1.tgz", + "integrity": "sha1-hF9tiLaTmUjzia5t4B0miHJVlu4=", + "requires": { + "random-seed": "0.2.0" + } + }, + "link": { + "version": "https://www.atom.io/api/packages/link/versions/0.31.4/tarball", + "integrity": "sha512-5GCYLIyLf2/3hiCP6crSDxtTmDEZzWkJfDpfs2MV1nBvgLZ6CUInWbPzS/z3a0eL9+k/uvBHtIQDGj9wckih8w==", + "requires": { + "first-mate": "7.1.1", + "underscore-plus": "1.6.8" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "log4js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.5.tgz", + "integrity": "sha512-IX5c3G/7fuTtdr0JjOT2OIR12aTESVhsH6cEsijloYwKgcPRlO6DgOU72v0UFhWcoV1HN6+M3dwT89qVPLXm0w==", + "requires": { + "circular-json": "0.5.5", + "date-format": "1.2.0", + "debug": "3.1.0", + "rfdc": "1.1.2", + "streamroller": "0.7.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "lokijs": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/lokijs/-/lokijs-1.5.5.tgz", + "integrity": "sha1-HCH4KvdXkDf63nueSBNIXCNwi7Y=" + }, + "lolex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loophole": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loophole/-/loophole-1.1.0.tgz", + "integrity": "sha1-N5Sf6kU7YlasxyXDIM4MWn9wor0=" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + } + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + }, + "ls-archive": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/ls-archive/-/ls-archive-1.3.1.tgz", + "integrity": "sha512-qIzKetZtGFQtR+CQj7VI0f8BpctLPmbaJU9NfKUvTB6oxn51cgV53PBfP2KvfI4EbRxlqyQ8XgC8XqyqN4pMgQ==", + "requires": { + "async": "0.2.10", + "colors": "0.6.2", + "optimist": "0.5.2", + "rimraf": "2.2.8", + "tar": "2.2.1", + "yauzl": "2.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.2.8" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + } + } + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + }, + "markdown-preview": { + "version": "https://www.atom.io/api/packages/markdown-preview/versions/0.159.23/tarball", + "integrity": "sha512-Sa/XmtVqUbe918TsYpdUUadSpxu3+IskKkPmStcQhNDf5Y20Sd5cNbWuKYMTvQePTRV/9/lsZdXGOkQx1pHcmw==", + "requires": { + "dompurify": "1.0.7", + "fs-plus": "3.0.2", + "roaster": "1.2.1", + "underscore-plus": "1.6.8" + } + }, + "marked": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" + }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "1.1.6" + } + }, + "metrics": { + "version": "https://www.atom.io/api/packages/metrics/versions/1.6.2/tarball", + "integrity": "sha512-UXJtTlpUPUIEJF7tYd5XSKeYzwM3e8kkbbIc6240QFqU418teooVImMTQHDPuE/nTMRZCSXKh3QyRHrtlJaTRQ==", + "requires": { + "fs-plus": "3.0.2", + "grim": "2.0.2", + "telemetry-github": "0.0.13" + }, + "dependencies": { + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "optional": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "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.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "minipass": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.4.tgz", + "integrity": "sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w==", + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", + "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "requires": { + "minipass": "2.3.4" + } + }, + "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" + } + }, + "mocha": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.1.tgz", + "integrity": "sha1-qdRqzkDvKfMlgnX/zLiXb2OU6j0=", + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" + }, + "dependencies": { + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=" + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=" + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=" + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + } + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "supports-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=" + } + } + }, + "mocha-junit-reporter": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.17.0.tgz", + "integrity": "sha1-LlFJ7UD8XS48px5C21qx/snG2Fw=", + "requires": { + "debug": "2.6.9", + "md5": "2.2.1", + "mkdirp": "0.5.1", + "strip-ansi": "4.0.0", + "xml": "1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "mocha-multi-reporters": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz", + "integrity": "sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI=", + "requires": { + "debug": "3.1.0", + "lodash": "4.17.10" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + } + } + }, + "mock-spawn": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/mock-spawn/-/mock-spawn-0.2.6.tgz", + "integrity": "sha1-s5wVocBnUEMQFEFR8sHeNE0Dk38=", + "requires": { + "through": "2.3.8" + } + }, + "moment": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multi-integer-range": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multi-integer-range/-/multi-integer-range-2.1.0.tgz", + "integrity": "sha1-c2dVGbohRtuiLNNZYOnF6AT/4vw=" + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "natural": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/natural/-/natural-0.4.0.tgz", + "integrity": "sha1-PraS2Vanb/BfSjeaJ31FUzOQZ2Q=", + "requires": { + "apparatus": "0.0.10", + "log4js": "3.0.5", + "sylvester": "0.0.21", + "underscore": "1.8.3" + } + }, + "needle": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.2.tgz", + "integrity": "sha512-mW7W8dKuVYefCpNzE3Z7xUmPI9wSrSL/1qH31YGMxmSOAnjatS3S9Zv3cmiHrhx3Jkp1SrWWBdOFXjfF48Uq3A==", + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.23", + "sax": "1.2.4" + } + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "node-abi": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz", + "integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==", + "requires": { + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + } + } + }, + "node-emoji": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", + "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", + "requires": { + "lodash.toarray": "4.4.0" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", + "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.2", + "nopt": "4.0.1", + "npm-packlist": "1.1.11", + "npmlog": "4.1.2", + "rc": "1.2.8", + "rimraf": "2.6.2", + "semver": "5.5.1", + "tar": "4.4.6" + }, + "dependencies": { + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + } + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "nodegit-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nodegit-promise/-/nodegit-promise-4.0.0.tgz", + "integrity": "sha1-VyKxhPLfcycWEGSnkdLoQskWezQ=", + "requires": { + "asap": "2.0.6" + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.3" + } + }, + "notifications": { + "version": "https://www.atom.io/api/packages/notifications/versions/0.70.5/tarball", + "integrity": "sha512-Eye5knLSgDXOr4qQNv/mnSp+rfmckK+J3Gok6j+tQuaiIYwCPPmJ2rRjy5t6gaJo81yZRuheBf0ur3TpKTXuUw==", + "requires": { + "dompurify": "1.0.7", + "fs-plus": "3.0.2", + "marked": "0.3.19", + "moment": "2.22.2", + "semver": "4.3.6", + "stacktrace-parser": "0.1.4", + "temp": "0.8.3" + } + }, + "npm-bundled": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz", + "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==" + }, + "npm-packlist": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.11.tgz", + "integrity": "sha512-CxKlZ24urLkJk+9kCm48RTQ7L4hsmgSVzEk0TLGPzzyuFxD7VNgy5Sl24tOLMzQv773a/NeJ1ce1DKeacqffEA==", + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.5" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "nslog": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/nslog/-/nslog-3.0.0.tgz", + "integrity": "sha1-nvfjpGveHnVyRFQcyhP/K2dvexk=", + "requires": { + "nan": "2.10.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=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "one-dark-syntax": { + "version": "https://www.atom.io/api/packages/one-dark-syntax/versions/1.8.4/tarball", + "integrity": "sha512-zBdZ/IQVmU/pw6nOPIOGnDXwFRMQ9uwuaLoW5xCznMoMR89nIFFVc+WhZC7K/E+RICCrSdrzH18Afr3RJS0sjA==" + }, + "one-dark-ui": { + "version": "https://www.atom.io/api/packages/one-dark-ui/versions/1.12.5/tarball", + "integrity": "sha512-NKHHSijacvlzz2rFAlky4Eu+W0yAmeJadZ+d0z7TYopI2DmKmGcM+TautMUmw6wzjoE70MLE9lpJxGM7TrYjCg==" + }, + "one-light-syntax": { + "version": "https://www.atom.io/api/packages/one-light-syntax/versions/1.8.4/tarball", + "integrity": "sha512-fXUzR34G+uepHq9vzmZZyKK6bGehOt2shX91iNqdecPvoHxR3lwWmAHoUMux7O0rXvClz5z0efVmnxgiDml6hQ==" + }, + "one-light-ui": { + "version": "file:packages/one-light-ui" + }, + "oniguruma": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/oniguruma/-/oniguruma-6.2.1.tgz", + "integrity": "sha1-pQ7mlkKEStHSUmhaqxhxcbBuzgQ=", + "requires": { + "nan": "2.10.0" + } + }, + "open-on-github": { + "version": "https://www.atom.io/api/packages/open-on-github/versions/1.3.1/tarball", + "integrity": "sha512-g99P4spSqC2HhNXeBNCBHEFqKQITUbX1AHRPiVHSdGFQpTXbv8sfmIw4N1IT8RcVuZA8YRH8T2YIGhII3JqTWQ==" + }, + "optimist": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.5.2.tgz", + "integrity": "sha1-hcjBRUszFeSniUfoV7HfAzRQv7w=", + "requires": { + "wordwrap": "0.0.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://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=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "package-generator": { + "version": "https://www.atom.io/api/packages/package-generator/versions/1.3.0/tarball", + "integrity": "sha512-twt7ewPEcSBJASqEytVeVSP14BGT3SiUhMhL4VmAIVpv+YttFo2UTaxNTHdubjYrNMV0we+J1la2CxoX/bx6Bg==", + "requires": { + "fs-plus": "3.0.2", + "temp": "0.8.3", + "underscore-plus": "1.6.8" + } + }, + "path-exists": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=" + }, + "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-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "pathwatcher": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/pathwatcher/-/pathwatcher-8.0.1.tgz", + "integrity": "sha512-NN+P7PRWdT8Zd1FwGOX/eLFD8tNuFBdDW/ysL5ufi9BFqAgOfQrV0pMMY/oRDFOZEUR4Y8RudXpLuPjE9b2pmQ==", + "requires": { + "async": "0.2.10", + "emissary": "1.3.3", + "event-kit": "2.5.0", + "fs-plus": "3.0.2", + "grim": "2.0.2", + "iconv-lite": "0.4.23", + "nan": "2.10.0", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "2.3.8" + } + }, + "pegjs": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.8.0.tgz", + "integrity": "sha1-l28GfaE+XFsVAcAXklZoolOBFWE=" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "postcss": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.4.tgz", + "integrity": "sha1-jrS+4+XE4JFYWxFt8y2NskpTXyE=", + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.6", + "source-map": "0.5.7", + "supports-color": "3.2.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-selector-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.1.tgz", + "integrity": "sha1-/b9pYQOxKwpkBg5WEFB/QQSR98g=", + "requires": { + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" + } + }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.3", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.8.1", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "2.0.6" + } + }, + "promisify-node": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/promisify-node/-/promisify-node-0.3.0.tgz", + "integrity": "sha1-tLVaz5D6p9K4uQyjlomQhsAwYM8=", + "requires": { + "nodegit-promise": "4.0.0" + } + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "requires": { + "loose-envify": "1.4.0", + "object-assign": "4.1.1" + } + }, + "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.4", + "mixto": "1.0.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "optional": true + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "random-seed": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/random-seed/-/random-seed-0.2.0.tgz", + "integrity": "sha1-TRiJtG3ITvUjFs63dysM4KVE844=" + }, + "random-words": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/random-words/-/random-words-0.0.1.tgz", + "integrity": "sha1-QOMAkgM62Ptg1mrRW+NiDTwlxB8=" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "react": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.4.0.tgz", + "integrity": "sha512-K0UrkLXSAekf5nJu89obKUM7o2vc6MMN9LYoKnCa+c+8MJRAT120xzPLENcWSRc7GYKIg0LlgJRDorrufdglQQ==", + "requires": { + "fbjs": "0.8.17", + "loose-envify": "1.4.0", + "object-assign": "4.1.1", + "prop-types": "15.6.2" + } + }, + "react-dom": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.4.0.tgz", + "integrity": "sha512-bbLd+HYpBEnYoNyxDe9XpSG2t9wypMohwQPvKw8Hov3nF7SJiJIgK56b46zHpBUpHb06a1iEuw7G3rbrsnNL6w==", + "requires": { + "fbjs": "0.8.17", + "loose-envify": "1.4.0", + "object-assign": "4.1.1", + "prop-types": "15.6.2" + } + }, + "react-input-autosize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.1.tgz", + "integrity": "sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA==", + "requires": { + "prop-types": "15.6.2" + } + }, + "react-relay": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/react-relay/-/react-relay-1.6.0.tgz", + "integrity": "sha512-8clmRHXNo96pcdkA8ZeiqF7xGjE+mjSbdX/INj5upRm2M8AprSrFk2Oz5nH084O+0hvXQhZtFyraXJWQO9ld3A==", + "requires": { + "babel-runtime": "6.26.0", + "fbjs": "0.8.17", + "prop-types": "15.6.2", + "relay-runtime": "1.6.0" + } + }, + "react-select": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-1.2.1.tgz", + "integrity": "sha512-vaCgT2bEl+uTyE/uKOEgzE5Dc/wLtzhnBvoHCeuLoJWc4WuadN6WQDhoL42DW+TziniZK2Gaqe/wUXydI3NSaQ==", + "requires": { + "classnames": "2.2.6", + "prop-types": "15.6.2", + "react-input-autosize": "2.2.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "recast": { + "version": "0.10.33", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.10.33.tgz", + "integrity": "sha1-lCgI96oBbx+nFCxGHX5XBKqo1pc=", + "requires": { + "ast-types": "0.8.12", + "esprima-fb": "15001.1001.0-dev-harmony-fb", + "private": "0.1.8", + "source-map": "0.5.7" + }, + "dependencies": { + "ast-types": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.12.tgz", + "integrity": "sha1-oNkOQ1G7iHcWyD/WN+v4GK9K38w=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerator": { + "version": "0.8.40", + "resolved": "https://registry.npmjs.org/regenerator/-/regenerator-0.8.40.tgz", + "integrity": "sha1-oORXxY69uuV1yfjNdRJ+k3VkNdg=", + "requires": { + "commoner": "0.10.8", + "defs": "1.1.1", + "esprima-fb": "15001.1001.0-dev-harmony-fb", + "private": "0.1.8", + "recast": "0.10.33", + "through": "2.3.8" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regexpu": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexpu/-/regexpu-1.3.0.tgz", + "integrity": "sha1-5TTcmRqeWEYFDJjebX3UpVyeoW0=", + "requires": { + "esprima": "2.7.3", + "recast": "0.10.33", + "regenerate": "1.4.0", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + } + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "0.5.0" + } + }, + "relay-runtime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-1.6.0.tgz", + "integrity": "sha512-UJiEHp8CX2uFxXdM0nVLTCQ6yAT0GLmyMceXLISuW/l2a9jrS9a4MdZgdr/9UkkYno7Sj1hU/EUIQ0GaVkou8g==", + "requires": { + "babel-runtime": "6.26.0", + "fbjs": "0.8.17" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "requires": { + "is-finite": "1.0.2" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.1.0", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.20", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + }, + "dependencies": { + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "requires": { + "mime-db": "1.36.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "1.1.29", + "punycode": "1.4.1" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "requirejs": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.5.tgz", + "integrity": "sha512-svnO+aNcR/an9Dpi44C7KSAy5fFGLtmPbaaCeQaklUz8BQhS64tWWIIlvEA5jrWICzlO/X9KSzSeXFnZdBu8nw==" + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "requires": { + "path-parse": "1.0.5" + } + }, + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "roaster": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/roaster/-/roaster-1.2.1.tgz", + "integrity": "sha1-EXa/oyoZAWUvsRBo8cDqUn9jIGg=", + "requires": { + "cheerio": "0.15.0", + "emoji-images": "0.0.2", + "js-yaml": "3.6.1", + "marked": "0.3.19", + "task-lists": "0.2.0", + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "samsam": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "scandal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scandal/-/scandal-3.1.0.tgz", + "integrity": "sha1-m0AkuXxxm74lAIzAm6rHn7tdNQE=", + "requires": { + "argparse": "1.0.10", + "git-utils": "5.2.1", + "isbinaryfile": "2.0.4", + "minimatch": "2.0.10", + "split": "1.0.1", + "temp": "0.8.3" + }, + "dependencies": { + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, + "scoped-property-store": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/scoped-property-store/-/scoped-property-store-0.17.0.tgz", + "integrity": "sha1-raAsANYC/SBQlh4nF92dArozGDE=", + "requires": { + "atom-slick": "2.0.0", + "event-kit": "1.5.0", + "grim": "1.5.0", + "key-path-helpers": "0.1.0", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "event-kit": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/event-kit/-/event-kit-1.5.0.tgz", + "integrity": "sha1-Ek72qtgyjcsmtxxHWQtbjmPrxIc=", + "requires": { + "grim": "1.5.0" + } + }, + "key-path-helpers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/key-path-helpers/-/key-path-helpers-0.1.0.tgz", + "integrity": "sha1-zYFJULeZzHRaNGqlIfkilK9du6Q=" + } + } + }, + "scrollbar-style": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/scrollbar-style/-/scrollbar-style-3.2.0.tgz", + "integrity": "sha1-BmK2GJM2QWDLtbDEZxmAmwKHGKE=", + "requires": { + "event-kit": "1.5.0", + "nan": "2.10.0" + }, + "dependencies": { + "event-kit": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/event-kit/-/event-kit-1.5.0.tgz", + "integrity": "sha1-Ek72qtgyjcsmtxxHWQtbjmPrxIc=", + "requires": { + "grim": "1.5.0" + } + } + } + }, + "season": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/season/-/season-6.0.2.tgz", + "integrity": "sha1-naWPsd3SSCTXYhstxjpxI7UCF7Y=", + "requires": { + "cson-parser": "1.3.5", + "fs-plus": "3.0.2", + "yargs": "3.32.0" + } + }, + "selector-kit": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/selector-kit/-/selector-kit-0.1.0.tgz", + "integrity": "sha1-MEM4/OzOo17Cj/rdt5KrdxVjPm8=", + "requires": { + "atom-slick": "2.0.0" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + }, + "serializable": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/serializable/-/serializable-1.0.3.tgz", + "integrity": "sha1-ClqLa3d3yyRUTfEab4iabSs+EYk=", + "requires": { + "get-parameter-names": "0.2.0", + "mixto": "1.0.0", + "underscore-plus": "1.6.8" + } + }, + "service-hub": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/service-hub/-/service-hub-0.7.4.tgz", + "integrity": "sha1-ttodHn6SkcpW1PPLPVwfzjKFoWI=", + "requires": { + "event-kit": "1.5.0", + "semver": "5.5.0" + }, + "dependencies": { + "event-kit": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/event-kit/-/event-kit-1.5.0.tgz", + "integrity": "sha1-Ek72qtgyjcsmtxxHWQtbjmPrxIc=", + "requires": { + "grim": "1.5.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + } + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "settings-view": { + "version": "https://www.atom.io/api/packages/settings-view/versions/0.256.0/tarball", + "integrity": "sha512-GFEpDDXocS99eH9wNH0NA+9HRdP/OgZzNVEqmJXXBJ1e22oDxB4cAkG9vXDrenY62DfBKOvCIiz7qdNPPpZeJQ==", + "requires": { + "async": "0.2.10", + "dompurify": "1.0.7", + "etch": "0.9.0", + "fs-plus": "3.0.2", + "fuzzaldrin": "2.1.0", + "glob": "4.3.1", + "hosted-git-info": "2.7.1", + "marked": "0.3.19", + "request": "2.88.0", + "roaster": "1.2.1", + "season": "6.0.2", + "semver": "5.5.1", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "etch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.0.tgz", + "integrity": "sha1-CSJpiPLO4GkL3yCMyyXkFNXfrV8=" + }, + "glob": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.1.tgz", + "integrity": "sha1-nQkJb4m00wlJ54ToPzEq88oE7BQ=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + } + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-fmt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz", + "integrity": "sha1-GRv1ZqWeZTBILLJatTtKjchcOms=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" + } + }, + "simple-is": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz", + "integrity": "sha1-Krt1qt453rXMgVzhDmGRFkhQuvA=" + }, + "sinon": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.4.tgz", + "integrity": "sha1-Tk/02Esgre4TE482rLEyyhzXLIM=", + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": "0.11.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "snippets": { + "version": "https://www.atom.io/api/packages/snippets/versions/1.3.5/tarball", + "integrity": "sha512-2HNSTs6QbMlbcEFr5H8EilU1B3IZdQesv52UDQpVSVP21x6wPJCv9vB1isP7NoLM0+1bgslQv/l0vsGt3cLKwg==", + "requires": { + "async": "0.2.6", + "atom-select-list": "0.7.2", + "fs-plus": "3.0.2", + "loophole": "1.1.0", + "pegjs": "0.8.0", + "scoped-property-store": "0.17.0", + "season": "6.0.2", + "temp": "0.8.3", + "underscore-plus": "1.6.8" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "optional": true, + "requires": { + "hoek": "2.16.3" + } + }, + "solarized-dark-syntax": { + "version": "https://www.atom.io/api/packages/solarized-dark-syntax/versions/1.2.0/tarball", + "integrity": "sha512-2cB5r7BiKmNOPgrIEoEqwsqaogvbWjqIFtpPYPyx6Bep0UqBlmibjmmBFOJ5liG97XT9KwqFTp5JOe6FzdMufQ==" + }, + "solarized-light-syntax": { + "version": "https://www.atom.io/api/packages/solarized-light-syntax/versions/1.2.0/tarball", + "integrity": "sha512-iRtmN2+pHyza9JSXpkeRMdEmKP9hfNgMBGZRlxJJlkQtgQIvLUU20OJoUbvTv0R2QiYB0Z+W8k7eZAAtF6bpbQ==" + }, + "source-map": { + "version": "0.1.32", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", + "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", + "requires": { + "amdefine": "1.0.1" + } + }, + "source-map-support": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", + "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", + "requires": { + "source-map": "0.1.32" + } + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + }, + "spell-check": { + "version": "https://www.atom.io/api/packages/spell-check/versions/0.74.1/tarball", + "integrity": "sha512-pDBe/rcxf1kcniq3hv3MxnF6SKdZDm3iYFZc7aDPKDRxXnU5GyCYSU/PiEGP670drYok+pki7+/7+PFIhJmhTA==", + "requires": { + "atom-pathspec": "0.0.0", + "atom-select-list": "0.7.2", + "multi-integer-range": "2.1.0", + "natural": "0.4.0", + "spellchecker": "3.4.4", + "spelling-manager": "1.1.0", + "underscore-plus": "1.6.8" + } + }, + "spellchecker": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/spellchecker/-/spellchecker-3.4.4.tgz", + "integrity": "sha512-l0s86YZs5+PzATeFbqD0sTSMEF7bgzqUYgxrU8+nBSw3V19tzRYKMi+hDGG6v8MskWeG2dRK0Q79sqs1eGIKwQ==", + "requires": { + "any-promise": "1.3.0", + "nan": "2.10.0" + } + }, + "spelling-manager": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/spelling-manager/-/spelling-manager-1.1.0.tgz", + "integrity": "sha512-PpTP6XUZflCWO9YZO3wBSGAmqrUP6BFwSdmVFS6WBT9rFYg3ysmrIfyD1KnaVcnW6wuIKf+FDwefvU8PsD8Smg==", + "requires": { + "natural": "0.5.0", + "xregexp": "3.2.0" + }, + "dependencies": { + "natural": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/natural/-/natural-0.5.0.tgz", + "integrity": "sha1-Vam7aOzPXs5VNUhgBKV94mSuMYA=", + "requires": { + "apparatus": "0.0.10", + "sylvester": "0.0.21", + "underscore": "1.8.3" + } + } + } + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2.3.8" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "stack-trace": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" + }, + "stacktrace-parser": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.4.tgz", + "integrity": "sha1-ATl5IuX2Ls8whFUiyVxP4dJefU4=" + }, + "status-bar": { + "version": "https://www.atom.io/api/packages/status-bar/versions/1.8.15/tarball", + "integrity": "sha512-zQa+fdr6pAnix4Lw3tKiU6Uq8Hx1dLsb+w2SaxIDbJaZatO25rN9FTZqNrw0ZchJpCEiSkuLolqUutPB4iNydQ==", + "requires": { + "fs-plus": "3.0.2", + "grim": "2.0.2", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "0.1.1" + } + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "requires": { + "date-format": "1.2.0", + "debug": "3.1.0", + "mkdirp": "0.5.1", + "readable-stream": "2.3.6" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "stringmap": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz", + "integrity": "sha1-VWwTeyWPlCuHdvWy71gqoGnX0bE=" + }, + "stringset": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/stringset/-/stringset-0.2.1.tgz", + "integrity": "sha1-7yWcTjSTRDd/zRyRPdLoSMnAQrU=" + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "styleguide": { + "version": "https://www.atom.io/api/packages/styleguide/versions/0.49.12/tarball", + "integrity": "sha512-fmLcnTfHIb6nU5k/ccJHwK7J+iSbw7MutpTm4W4oNXlFOW5wbyphcJD7XsXgLKv4XZT2jWEDYZWox3ZIhxK7zg==", + "requires": { + "atom-select-list": "0.7.2", + "dedent": "0.7.0", + "etch": "0.9.0" + }, + "dependencies": { + "etch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.0.tgz", + "integrity": "sha1-CSJpiPLO4GkL3yCMyyXkFNXfrV8=" + } + } + }, + "superstring": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/superstring/-/superstring-2.3.4.tgz", + "integrity": "sha512-DcNkTCdB9F3FMZRdURSALsHi+7DWqFCI0cH+Eg8mwBg+kxQs6GeB3LrGUvCI5bEB6Dtlu2ox8UYN0onPN4JeZQ==", + "requires": { + "nan": "2.10.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "sylvester": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/sylvester/-/sylvester-0.0.21.tgz", + "integrity": "sha1-KYexzivS84sNzio0OIiEv6RADqc=" + }, + "symbols-view": { + "version": "https://www.atom.io/api/packages/symbols-view/versions/0.118.2/tarball", + "integrity": "sha512-F83LvcjRLYqcxXD9z++jX28Vdj7fkcYRa2vhCo9A2m9PSZkt8kAfas5kJ95F2LFXvkFCjfWRqVVVrQ8gMumKsA==", + "requires": { + "async": "0.2.6", + "atom-select-list": "0.7.2", + "ctags": "3.0.0", + "fs-plus": "3.0.2", + "fuzzaldrin": "2.1.0", + "humanize-plus": "1.8.2", + "temp": "0.8.3", + "underscore-plus": "1.6.8" + } + }, + "tabbable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-1.1.3.tgz", + "integrity": "sha512-nOWwx35/JuDI4ONuF0ZTo6lYvI0fY0tZCH1ErzY2EXfu4az50ZyiUX8X073FLiZtmWUVlkRnuXsehjJgCw9tYg==" + }, + "tabs": { + "version": "https://www.atom.io/api/packages/tabs/versions/0.109.2/tarball", + "integrity": "sha512-IdKT8s9Wm4++Sm5wLzrI+nLCB57DMUtTMYnLGlA9Y/C/IRlfMp3PQC2aM/dHGuIzf9JsXsI2wfPsJcU4YXKFoQ==", + "requires": { + "fs-plus": "3.0.2", + "temp": "0.8.3", + "underscore-plus": "1.6.8" + } + }, + "tar": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.6.tgz", + "integrity": "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg==", + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.6.1" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.6", + "to-buffer": "1.1.1", + "xtend": "4.0.1" + } + }, + "task-lists": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/task-lists/-/task-lists-0.2.0.tgz", + "integrity": "sha1-dICLohPz4S9aexrn1oI5e/jpD74=", + "requires": { + "cheerio": "0.15.0" + } + }, + "telemetry-github": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/telemetry-github/-/telemetry-github-0.0.13.tgz", + "integrity": "sha512-35+r699XSRdvuNf27WadJggsY4x9sTLEuoBdc8WRS0BdkHMKOodN+wzlbwk780iWVvG5ccZPPPKGw9VwkXCTGw==", + "requires": { + "lokijs": "1.5.5", + "uuid": "3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "text-buffer": { + "version": "13.14.8", + "resolved": "https://registry.npmjs.org/text-buffer/-/text-buffer-13.14.8.tgz", + "integrity": "sha512-hl2adF6WZf4fjy1AuIRZtPqRQ6in9V+KSM7I5eUp0FEI/PBH1EwaTzO1UWrnslI7Lybiiwx4TELOQXOVjFqfQg==", + "requires": { + "delegato": "1.0.0", + "diff": "2.2.3", + "emissary": "1.3.3", + "event-kit": "2.5.0", + "fs-admin": "0.1.6", + "fs-plus": "3.0.2", + "grim": "2.0.2", + "mkdirp": "0.5.1", + "pathwatcher": "8.0.1", + "serializable": "1.0.3", + "superstring": "2.3.4", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "diff": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", + "integrity": "sha1-YOr9DSjukG5Oj/ClLBIpUhAzv5k=" + }, + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "timecop": { + "version": "https://www.atom.io/api/packages/timecop/versions/0.36.2/tarball", + "integrity": "sha512-m8FkLOjmzV5e0LiycEh+IwOiHXbD6odk6DSbBxWL3hSPF89eHkaFT8Ea/NT6g/ufYO4ZSzAbvlXpuFuskAb/1w==", + "requires": { + "dedent": "0.7.0", + "etch": "0.12.8", + "underscore-plus": "1.6.8" + } + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "to-iso-string": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", + "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=" + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" + }, + "tree-sitter": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.13.9.tgz", + "integrity": "sha512-We9UlKA2f374V8JNumCVd0Nc9JrsgxyD1Llcat+eRsalNRWRxLFPOepkR3Q7snz3AXB0BEN+X+nW9vZdLNbQqQ==", + "requires": { + "nan": "2.10.0", + "prebuild-install": "5.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "prebuild-install": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.1.0.tgz", + "integrity": "sha512-jGdh2Ws5OUCvBm+aQ/je7hgOBfLIFcgnF9DZ1PIEvht0JKfMwn3Gy0MPHL16JcAUI6tu7LX0D3VxmvMm1XZwAw==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.3", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.8.1", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + } + } + } + }, + "tree-sitter-bash": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/tree-sitter-bash/-/tree-sitter-bash-0.13.2.tgz", + "integrity": "sha512-6viPvaHwTLRVYLeUXyCSvu+ybLAOVDbkqhvNcp5Ak+GQMqzkflpsuuVIIriyl2lSumrkbUShHnrWiQw4yoZl4g==", + "requires": { + "nan": "2.10.0", + "prebuild-install": "5.1.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "prebuild-install": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.1.0.tgz", + "integrity": "sha512-jGdh2Ws5OUCvBm+aQ/je7hgOBfLIFcgnF9DZ1PIEvht0JKfMwn3Gy0MPHL16JcAUI6tu7LX0D3VxmvMm1XZwAw==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.3", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.8.1", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + } + } + } + }, + "tree-sitter-c": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/tree-sitter-c/-/tree-sitter-c-0.13.4.tgz", + "integrity": "sha512-wtu4PczfuG05GD4M0+2n2F1FytFN4Jra6UVwPqDjrzfoRUvfYcvtIgIlKmO5s/Oyd8sY5jEn1dKdC/lX1DEi4g==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-sitter-cpp": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/tree-sitter-cpp/-/tree-sitter-cpp-0.13.4.tgz", + "integrity": "sha512-WkPeb7r83lexK5nbpo7tfjgkSPhIDIo+Gl1ZOHBbRwG/r+O1xnsy2xgp7Gby5O/yAH0Mz5JgEGvoy+V6qBS8LQ==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-sitter-embedded-template": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/tree-sitter-embedded-template/-/tree-sitter-embedded-template-0.13.0.tgz", + "integrity": "sha512-IJVjMcL2Bg+qF+HibtEXTF4CE6A66ppGSqU8E+2ddn2pCqDtZGREhI+KfqerF9NpKSo1OtbvhXiEXPdXQANLGg==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-sitter-go": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/tree-sitter-go/-/tree-sitter-go-0.13.1.tgz", + "integrity": "sha512-lWcwS6cEvS42Ayo3m4uqQnpEmIjlex/Tb2BSNZ9ppxhiIVJrntR6/sirlYmhYVj7Zhu7eOWSVFfNX9y7PKw/2w==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-sitter-html": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/tree-sitter-html/-/tree-sitter-html-0.13.4.tgz", + "integrity": "sha512-l52UJ27BmGdwUgEC3d7UJKTtAJDIQ9GL+du8qQoDt2oJg/iSRxckZeevwJ+YyCfYjBlqFH7nXDLtVJxEzhdM/g==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-sitter-javascript": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/tree-sitter-javascript/-/tree-sitter-javascript-0.13.5.tgz", + "integrity": "sha512-80sUl2+kj0evGTueODpDmJksTNQbGtkG4EOxIygsjZ5Q6kFW/uBRHXHSlBtX5vkEIjljApZ8qse4C7cmG1CIFA==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-sitter-python": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/tree-sitter-python/-/tree-sitter-python-0.13.4.tgz", + "integrity": "sha512-JQ75/68VsPMSWteoitNxgdTlAw5spbTFGK2XgiR41tiTtkk8cONdtfB7Pe2yWSgoXGDNtcu0/Tkq4HrKrWrKfQ==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-sitter-regex": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/tree-sitter-regex/-/tree-sitter-regex-0.13.0.tgz", + "integrity": "sha512-b8EnSNTAYGSlfP4sHEA0NfVf+mn2eyCqWIyTaBHKkEUlxkKloo7551tY7LzxicetG4R6WMzPG/ZsI+jrIyFplQ==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-sitter-ruby": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/tree-sitter-ruby/-/tree-sitter-ruby-0.13.8.tgz", + "integrity": "sha512-yNww+yq72eDAZsgSx9tb3G0pPWb8zcY7LjeATfKxOLw5tls7eXIWfVfCkv9bO1OBNqE0m/abTz3oZfM0iIrHUQ==", + "requires": { + "nan": "2.10.0", + "prebuild-install": "5.1.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "prebuild-install": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.1.0.tgz", + "integrity": "sha512-jGdh2Ws5OUCvBm+aQ/je7hgOBfLIFcgnF9DZ1PIEvht0JKfMwn3Gy0MPHL16JcAUI6tu7LX0D3VxmvMm1XZwAw==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.1", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.3", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.8", + "simple-get": "2.8.1", + "tar-fs": "1.16.3", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + } + } + } + }, + "tree-sitter-typescript": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/tree-sitter-typescript/-/tree-sitter-typescript-0.13.3.tgz", + "integrity": "sha512-PF/yDQNtjOU0pDHdy4QqYB8yPgfEeZz7PsG+IwYYC6xt3XQBRKJDIGyPPSHSvSZFE2ln4GBnJ7/EDneiNXqrlA==", + "requires": { + "nan": "2.10.0" + } + }, + "tree-view": { + "version": "https://www.atom.io/api/packages/tree-view/versions/0.224.2/tarball", + "integrity": "sha512-zQgrwWo2aBInkSCsldNP9sZJA4OnzznQgKJzQNhClMZJMWEr1Pl1tWnq3x67ie6dINkJ/JWqzbjxz2v2T5U2ig==", + "requires": { + "@atom/temp": "0.8.4", + "fs-plus": "3.0.2", + "minimatch": "0.3.0", + "pathwatcher": "8.0.1", + "underscore-plus": "1.6.8" + }, + "dependencies": { + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "try-resolve": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/try-resolve/-/try-resolve-1.0.1.tgz", + "integrity": "sha1-z95vq9ctY+V5fPqrhzq76OcA6RI=" + }, + "tryor": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz", + "integrity": "sha1-gUXkynyv9ArN48z5Rui4u3W0Fys=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=" + }, + "typescript": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-1.4.1.tgz", + "integrity": "sha1-602phtG38BRS6vtXVZ4MyPUWzUg=" + }, + "typescript-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typescript-simple/-/typescript-simple-1.0.0.tgz", + "integrity": "sha1-/eFtnJxJTvc9OtOdgHEZsI8sOZg=", + "requires": { + "typescript": "1.4.1" + } + }, + "ua-parser-js": { + "version": "0.7.18", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", + "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "underscore-plus": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.6.8.tgz", + "integrity": "sha512-88PrCeMKeAAC1L4xjSiiZ3Fg6kZOYrLpLGVPPeqKq/662DfQe/KTSKdSR/Q/tucKNnfW2MNAUGSCkDf8HmXC5Q==", + "requires": { + "underscore": "1.8.3" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "update-package-dependencies": { + "version": "https://www.atom.io/api/packages/update-package-dependencies/versions/0.13.1/tarball", + "integrity": "sha512-A0mvGI/fSHKsGPOTz/HVZ94UHUJOOJuwI4lAaauPeyZlEDHC2+VGoRDHcvLYxTyamumCGRhSVPDK3Gp8KItF9A==" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" + }, + "util": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.0.tgz", + "integrity": "sha512-5n12uMzKCjvB2HPFHnbQSjaqAa98L5iIXmHrZCLavuZVe0qe/SJGbDGWlpaHk5lnBkWRDO+dRu1/PgmUYKPPTw==", + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "walkdir": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.7.tgz", + "integrity": "sha1-BNoCcKh6d4VAFzzb8KLbSZqNnik=" + }, + "welcome": { + "version": "https://www.atom.io/api/packages/welcome/versions/0.36.7/tarball", + "integrity": "sha512-z1EOTRYfN23fBL75Shrbe/j2VDelw2c8oKRXC2MqLLBiWUCFDkxsEo1R7OfiCaNZi7q/0ue0fqLCpENHker4FA==", + "requires": { + "etch": "0.9.0" + }, + "dependencies": { + "etch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.0.tgz", + "integrity": "sha1-CSJpiPLO4GkL3yCMyyXkFNXfrV8=" + } + } + }, + "what-the-diff": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/what-the-diff/-/what-the-diff-0.4.0.tgz", + "integrity": "sha512-Aw5OoYs5pY4RcZhD9UrS/brg/YRFm/SRRwJEI3f12PTWYadXzkvmf2eGDggSwcZuH2OH8J5HmtUK6LH+jRc2aA==" + }, + "what-the-status": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/what-the-status/-/what-the-status-1.0.3.tgz", + "integrity": "sha512-6zNdYtQtHTpLVPomSrr+Eyt5Ci4H40ytwScwp7Moi2iqxztV6+juQV9Orj2szAo0ZrV9tphk6WtL+BY3ukCS/Q==", + "requires": { + "split": "1.0.1" + } + }, + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "whitespace": { + "version": "https://www.atom.io/api/packages/whitespace/versions/0.37.6/tarball", + "integrity": "sha512-I5xkJnYf/Pqs1LgXihzVBsiRddVTAGFluDruwZR6fg6c3r0shVwSOxoYX0Ba+xxRVEcAixahnq0lOp68tnl7oA==" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "1.0.2" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "winreg": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.4.tgz", + "integrity": "sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrap-guide": { + "version": "https://www.atom.io/api/packages/wrap-guide/versions/0.40.3/tarball", + "integrity": "sha512-TQdO+E8t8sS3c4UUym2Orrf4s6/AYGrfu32lUHLMgnSYcBov/t8J3jYJfPImNkCq7kgYgfycQZM5UryW54J4KA==", + "requires": { + "grim": "2.0.2" + }, + "dependencies": { + "grim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grim/-/grim-2.0.2.tgz", + "integrity": "sha512-Qj7hTJRfd87E/gUgfvM0YIH/g2UA2SV6niv6BYXk1o6w4mhgv+QyYM1EjOJQljvzgEj4SqSsRWldXIeKHz3e3Q==", + "requires": { + "event-kit": "2.5.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "wrench": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/wrench/-/wrench-1.5.9.tgz", + "integrity": "sha1-QRaRxjqbJTGxcAJnJ5veyiOyFCo=" + }, + "xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=" + }, + "xregexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.2.0.tgz", + "integrity": "sha1-yzYBmHv+JpW1hAAMGPHEqMMih44=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.1.0" + } + }, + "yubikiri": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yubikiri/-/yubikiri-1.0.0.tgz", + "integrity": "sha1-TQ+EGugA10f11pM/fVQvVQJiw64=" + } + } +} diff --git a/package.json b/package.json index 0958b3fc5..af0b1d71b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.26.0-dev", + "version": "1.32.0-dev", "description": "A hackable text editor for the 21st Century.", "main": "./src/main-process/main.js", "repository": { @@ -12,51 +12,128 @@ "url": "https://github.com/atom/atom/issues" }, "license": "MIT", - "electronVersion": "1.7.11", + "electronVersion": "2.0.7", "dependencies": { "@atom/nsfw": "^1.0.18", - "@atom/watcher": "1.0.3", "@atom/source-map-support": "^0.3.4", + "@atom/watcher": "1.0.8", + "about": "file:packages/about", + "archive-view": "https://www.atom.io/api/packages/archive-view/versions/0.65.1/tarball", "async": "0.2.6", + "atom-dark-syntax": "https://www.atom.io/api/packages/atom-dark-syntax/versions/0.29.1/tarball", + "atom-dark-ui": "https://www.atom.io/api/packages/atom-dark-ui/versions/0.53.3/tarball", "atom-keymap": "8.2.10", - "atom-select-list": "^0.7.0", + "atom-light-syntax": "https://www.atom.io/api/packages/atom-light-syntax/versions/0.29.1/tarball", + "atom-light-ui": "https://www.atom.io/api/packages/atom-light-ui/versions/0.46.3/tarball", + "atom-select-list": "^0.7.2", "atom-ui": "0.4.1", + "autocomplete-atom-api": "https://www.atom.io/api/packages/autocomplete-atom-api/versions/0.10.7/tarball", + "autocomplete-css": "https://www.atom.io/api/packages/autocomplete-css/versions/0.17.5/tarball", + "autocomplete-html": "https://www.atom.io/api/packages/autocomplete-html/versions/0.8.5/tarball", + "autocomplete-plus": "https://www.atom.io/api/packages/autocomplete-plus/versions/2.41.0/tarball", + "autocomplete-snippets": "https://www.atom.io/api/packages/autocomplete-snippets/versions/1.12.0/tarball", + "autoflow": "https://www.atom.io/api/packages/autoflow/versions/0.29.4/tarball", + "autosave": "https://www.atom.io/api/packages/autosave/versions/0.24.6/tarball", "babel-core": "5.8.38", + "background-tips": "https://www.atom.io/api/packages/background-tips/versions/0.28.0/tarball", + "base16-tomorrow-dark-theme": "https://www.atom.io/api/packages/base16-tomorrow-dark-theme/versions/1.6.0/tarball", + "base16-tomorrow-light-theme": "https://www.atom.io/api/packages/base16-tomorrow-light-theme/versions/1.6.0/tarball", + "bookmarks": "https://www.atom.io/api/packages/bookmarks/versions/0.45.1/tarball", + "bracket-matcher": "https://www.atom.io/api/packages/bracket-matcher/versions/0.89.2/tarball", "cached-run-in-this-context": "0.4.1", "chai": "3.5.0", "chart.js": "^2.3.0", "clear-cut": "^2.0.2", "coffee-script": "1.12.7", "color": "^0.7.3", + "command-palette": "https://www.atom.io/api/packages/command-palette/versions/0.43.5/tarball", + "dalek": "https://www.atom.io/api/packages/dalek/versions/0.2.2/tarball", "dedent": "^0.7.0", + "deprecation-cop": "https://www.atom.io/api/packages/deprecation-cop/versions/0.56.9/tarball", + "dev-live-reload": "https://www.atom.io/api/packages/dev-live-reload/versions/0.48.1/tarball", "devtron": "1.3.0", + "encoding-selector": "https://www.atom.io/api/packages/encoding-selector/versions/0.23.9/tarball", "etch": "^0.12.6", - "event-kit": "^2.4.0", + "event-kit": "^2.5.0", + "exception-reporting": "https://www.atom.io/api/packages/exception-reporting/versions/0.43.1/tarball", + "find-and-replace": "https://www.atom.io/api/packages/find-and-replace/versions/0.215.12/tarball", "find-parent-dir": "^0.3.0", - "first-mate": "7.1.0", - "focus-trap": "^2.3.0", + "first-mate": "7.1.1", + "focus-trap": "2.4.5", "fs-admin": "^0.1.6", "fs-plus": "^3.0.1", "fstream": "0.1.24", "fuzzaldrin": "^2.1", - "git-utils": "5.3.1", + "fuzzy-finder": "https://www.atom.io/api/packages/fuzzy-finder/versions/1.8.2/tarball", + "git-diff": "https://www.atom.io/api/packages/git-diff/versions/1.3.9/tarball", + "git-utils": "5.2.1", + "github": "https://www.atom.io/api/packages/github/versions/0.19.0/tarball", "glob": "^7.1.1", + "go-to-line": "https://www.atom.io/api/packages/go-to-line/versions/0.33.0/tarball", + "grammar-selector": "https://www.atom.io/api/packages/grammar-selector/versions/0.50.1/tarball", "grim": "1.5.0", + "image-view": "https://www.atom.io/api/packages/image-view/versions/0.63.1/tarball", + "incompatible-packages": "https://www.atom.io/api/packages/incompatible-packages/versions/0.27.3/tarball", "jasmine-json": "~0.0", "jasmine-reporters": "1.1.0", "jasmine-tagged": "^1.1.4", "key-path-helpers": "^0.4.0", + "keybinding-resolver": "https://www.atom.io/api/packages/keybinding-resolver/versions/0.38.2/tarball", + "language-c": "https://www.atom.io/api/packages/language-c/versions/0.60.4/tarball", + "language-clojure": "https://www.atom.io/api/packages/language-clojure/versions/0.22.7/tarball", + "language-coffee-script": "https://www.atom.io/api/packages/language-coffee-script/versions/0.49.3/tarball", + "language-csharp": "https://www.atom.io/api/packages/language-csharp/versions/1.1.0/tarball", + "language-css": "https://www.atom.io/api/packages/language-css/versions/0.42.11/tarball", + "language-gfm": "https://www.atom.io/api/packages/language-gfm/versions/0.90.5/tarball", + "language-git": "https://www.atom.io/api/packages/language-git/versions/0.19.1/tarball", + "language-go": "https://www.atom.io/api/packages/language-go/versions/0.46.2/tarball", + "language-html": "https://www.atom.io/api/packages/language-html/versions/0.51.5/tarball", + "language-hyperlink": "https://www.atom.io/api/packages/language-hyperlink/versions/0.16.3/tarball", + "language-java": "https://www.atom.io/api/packages/language-java/versions/0.30.0/tarball", + "language-javascript": "https://www.atom.io/api/packages/language-javascript/versions/0.129.9/tarball", + "language-json": "https://www.atom.io/api/packages/language-json/versions/0.19.2/tarball", + "language-less": "https://www.atom.io/api/packages/language-less/versions/0.34.2/tarball", + "language-make": "https://www.atom.io/api/packages/language-make/versions/0.22.3/tarball", + "language-mustache": "https://www.atom.io/api/packages/language-mustache/versions/0.14.5/tarball", + "language-objective-c": "https://www.atom.io/api/packages/language-objective-c/versions/0.15.1/tarball", + "language-perl": "https://www.atom.io/api/packages/language-perl/versions/0.38.1/tarball", + "language-php": "https://www.atom.io/api/packages/language-php/versions/0.44.0/tarball", + "language-property-list": "https://www.atom.io/api/packages/language-property-list/versions/0.9.1/tarball", + "language-python": "https://www.atom.io/api/packages/language-python/versions/0.51.4/tarball", + "language-ruby": "https://www.atom.io/api/packages/language-ruby/versions/0.72.7/tarball", + "language-ruby-on-rails": "https://www.atom.io/api/packages/language-ruby-on-rails/versions/0.25.3/tarball", + "language-sass": "https://www.atom.io/api/packages/language-sass/versions/0.62.0/tarball", + "language-shellscript": "https://www.atom.io/api/packages/language-shellscript/versions/0.27.4/tarball", + "language-source": "https://www.atom.io/api/packages/language-source/versions/0.9.0/tarball", + "language-sql": "https://www.atom.io/api/packages/language-sql/versions/0.25.10/tarball", + "language-text": "https://www.atom.io/api/packages/language-text/versions/0.7.4/tarball", + "language-todo": "https://www.atom.io/api/packages/language-todo/versions/0.29.4/tarball", + "language-toml": "https://www.atom.io/api/packages/language-toml/versions/0.18.2/tarball", + "language-typescript": "https://www.atom.io/api/packages/language-typescript/versions/0.4.6/tarball", + "language-xml": "https://www.atom.io/api/packages/language-xml/versions/0.35.2/tarball", + "language-yaml": "https://www.atom.io/api/packages/language-yaml/versions/0.32.0/tarball", "less-cache": "1.1.0", + "line-ending-selector": "https://www.atom.io/api/packages/line-ending-selector/versions/0.7.7/tarball", "line-top-index": "0.3.1", + "link": "https://www.atom.io/api/packages/link/versions/0.31.4/tarball", + "markdown-preview": "https://www.atom.io/api/packages/markdown-preview/versions/0.159.23/tarball", "marked": "^0.3.12", + "metrics": "https://www.atom.io/api/packages/metrics/versions/1.6.2/tarball", "minimatch": "^3.0.3", "mocha": "2.5.1", "mocha-junit-reporter": "^1.13.0", "mocha-multi-reporters": "^1.1.4", "mock-spawn": "^0.2.6", "normalize-package-data": "^2.0.0", + "notifications": "https://www.atom.io/api/packages/notifications/versions/0.70.5/tarball", "nslog": "^3", + "one-dark-syntax": "https://www.atom.io/api/packages/one-dark-syntax/versions/1.8.4/tarball", + "one-dark-ui": "https://www.atom.io/api/packages/one-dark-ui/versions/1.12.5/tarball", + "one-light-syntax": "https://www.atom.io/api/packages/one-light-syntax/versions/1.8.4/tarball", + "one-light-ui": "file:packages/one-light-ui", "oniguruma": "6.2.1", + "open-on-github": "https://www.atom.io/api/packages/open-on-github/versions/1.3.1/tarball", + "package-generator": "https://www.atom.io/api/packages/package-generator/versions/1.3.0/tarball", "pathwatcher": "8.0.1", "postcss": "5.2.4", "postcss-selector-parser": "2.2.1", @@ -69,106 +146,121 @@ "season": "^6.0.2", "semver": "^4.3.3", "service-hub": "^0.7.4", + "settings-view": "https://www.atom.io/api/packages/settings-view/versions/0.256.0/tarball", "sinon": "1.17.4", + "snippets": "https://www.atom.io/api/packages/snippets/versions/1.3.5/tarball", + "solarized-dark-syntax": "https://www.atom.io/api/packages/solarized-dark-syntax/versions/1.2.0/tarball", + "solarized-light-syntax": "https://www.atom.io/api/packages/solarized-light-syntax/versions/1.2.0/tarball", + "spell-check": "https://www.atom.io/api/packages/spell-check/versions/0.74.1/tarball", + "status-bar": "https://www.atom.io/api/packages/status-bar/versions/1.8.15/tarball", + "styleguide": "https://www.atom.io/api/packages/styleguide/versions/0.49.12/tarball", + "symbols-view": "https://www.atom.io/api/packages/symbols-view/versions/0.118.2/tarball", + "tabs": "https://www.atom.io/api/packages/tabs/versions/0.109.2/tarball", "temp": "^0.8.3", - "text-buffer": "13.11.8", - "tree-sitter": "^0.9.2", + "text-buffer": "13.14.8", + "timecop": "https://www.atom.io/api/packages/timecop/versions/0.36.2/tarball", + "tree-sitter": "0.13.9", + "tree-view": "https://www.atom.io/api/packages/tree-view/versions/0.224.2/tarball", "typescript-simple": "1.0.0", - "underscore-plus": "^1.6.6", + "underscore-plus": "^1.6.8", + "update-package-dependencies": "https://www.atom.io/api/packages/update-package-dependencies/versions/0.13.1/tarball", + "welcome": "https://www.atom.io/api/packages/welcome/versions/0.36.7/tarball", + "whitespace": "https://www.atom.io/api/packages/whitespace/versions/0.37.6/tarball", "winreg": "^1.2.1", + "wrap-guide": "https://www.atom.io/api/packages/wrap-guide/versions/0.40.3/tarball", "yargs": "^3.23.0" }, "packageDependencies": { - "atom-dark-syntax": "0.29.0", - "atom-dark-ui": "0.53.2", - "atom-light-syntax": "0.29.0", - "atom-light-ui": "0.46.2", - "base16-tomorrow-dark-theme": "1.5.0", - "base16-tomorrow-light-theme": "1.5.0", - "one-dark-ui": "1.11.0", - "one-light-ui": "1.11.0", - "one-dark-syntax": "1.8.2", - "one-light-syntax": "1.8.2", - "solarized-dark-syntax": "1.1.4", - "solarized-light-syntax": "1.1.4", - "about": "1.8.0", - "archive-view": "0.64.3", + "atom-dark-syntax": "0.29.1", + "atom-dark-ui": "0.53.3", + "atom-light-syntax": "0.29.1", + "atom-light-ui": "0.46.3", + "base16-tomorrow-dark-theme": "1.6.0", + "base16-tomorrow-light-theme": "1.6.0", + "one-dark-ui": "1.12.5", + "one-light-ui": "file:./packages/one-light-ui", + "one-dark-syntax": "1.8.4", + "one-light-syntax": "1.8.4", + "solarized-dark-syntax": "1.2.0", + "solarized-light-syntax": "1.2.0", + "about": "file:./packages/about", + "archive-view": "0.65.1", "autocomplete-atom-api": "0.10.7", "autocomplete-css": "0.17.5", - "autocomplete-html": "0.8.4", - "autocomplete-plus": "2.40.5", + "autocomplete-html": "0.8.5", + "autocomplete-plus": "2.41.0", "autocomplete-snippets": "1.12.0", - "autoflow": "0.29.3", + "autoflow": "0.29.4", "autosave": "0.24.6", "background-tips": "0.28.0", "bookmarks": "0.45.1", - "bracket-matcher": "0.89.1", + "bracket-matcher": "0.89.2", "command-palette": "0.43.5", "dalek": "0.2.2", "deprecation-cop": "0.56.9", "dev-live-reload": "0.48.1", - "encoding-selector": "0.23.8", + "encoding-selector": "0.23.9", "exception-reporting": "0.43.1", - "find-and-replace": "0.215.5", - "fuzzy-finder": "1.8.0", - "github": "0.12.0", + "find-and-replace": "0.215.12", + "fuzzy-finder": "1.8.2", + "github": "0.19.0", "git-diff": "1.3.9", "go-to-line": "0.33.0", - "grammar-selector": "0.50.0", - "image-view": "0.62.4", + "grammar-selector": "0.50.1", + "image-view": "0.63.1", "incompatible-packages": "0.27.3", - "keybinding-resolver": "0.38.1", - "line-ending-selector": "0.7.5", + "keybinding-resolver": "0.38.2", + "line-ending-selector": "0.7.7", "link": "0.31.4", - "markdown-preview": "0.159.20", - "metrics": "1.2.6", - "notifications": "0.70.2", + "markdown-preview": "0.159.23", + "metrics": "1.6.2", + "notifications": "0.70.5", "open-on-github": "1.3.1", "package-generator": "1.3.0", - "settings-view": "0.254.2", - "snippets": "1.3.1", - "spell-check": "0.73.1", + "settings-view": "0.256.0", + "snippets": "1.3.5", + "spell-check": "0.74.1", "status-bar": "1.8.15", - "styleguide": "0.49.10", + "styleguide": "0.49.12", "symbols-view": "0.118.2", - "tabs": "0.109.1", + "tabs": "0.109.2", "timecop": "0.36.2", - "tree-view": "0.221.3", + "tree-view": "0.224.2", "update-package-dependencies": "0.13.1", - "welcome": "0.36.6", - "whitespace": "0.37.5", + "welcome": "0.36.7", + "whitespace": "0.37.6", "wrap-guide": "0.40.3", - "language-c": "0.59.2", + "language-c": "0.60.4", "language-clojure": "0.22.7", "language-coffee-script": "0.49.3", - "language-csharp": "1.0.1", - "language-css": "0.42.10", - "language-gfm": "0.90.3", + "language-csharp": "1.1.0", + "language-css": "0.42.11", + "language-gfm": "0.90.5", "language-git": "0.19.1", - "language-go": "0.45.2", - "language-html": "0.49.0", + "language-go": "0.46.2", + "language-html": "0.51.5", "language-hyperlink": "0.16.3", - "language-java": "0.29.0", - "language-javascript": "0.128.4", - "language-json": "0.19.1", + "language-java": "0.30.0", + "language-javascript": "0.129.9", + "language-json": "0.19.2", "language-less": "0.34.2", "language-make": "0.22.3", "language-mustache": "0.14.5", "language-objective-c": "0.15.1", "language-perl": "0.38.1", - "language-php": "0.43.2", + "language-php": "0.44.0", "language-property-list": "0.9.1", - "language-python": "0.49.2", - "language-ruby": "0.71.4", + "language-python": "0.51.4", + "language-ruby": "0.72.7", "language-ruby-on-rails": "0.25.3", - "language-sass": "0.61.4", - "language-shellscript": "0.26.2", + "language-sass": "0.62.0", + "language-shellscript": "0.27.4", "language-source": "0.9.0", "language-sql": "0.25.10", "language-text": "0.7.4", "language-todo": "0.29.4", "language-toml": "0.18.2", - "language-typescript": "0.3.2", + "language-typescript": "0.4.6", "language-xml": "0.35.2", "language-yaml": "0.32.0" }, diff --git a/packages/README.md b/packages/README.md new file mode 100644 index 000000000..12ff907c5 --- /dev/null +++ b/packages/README.md @@ -0,0 +1,194 @@ +# Atom Core Packages + +This folder contains core packages that are bundled with Atom releases. Not all Atom core packages are kept here; please +see the table below for the location of every core Atom package. + +> **NOTE:** There is an ongoing effort to migrate more Atom packages from their individual repositories to this folder. +See [RFC 003](https://github.com/atom/atom/blob/master/docs/rfcs/003-consolidate-core-packages.md) for more details. + +| Package | Where to find it | Migration issue | +|---------|------------------|-----------------| +| **about** | [`./packages/about`](./about) | [#17832](https://github.com/atom/atom/issues/17832) | +| **atom-dark-syntax** | [`atom/atom-dark-syntax`][atom-dark-syntax] | [#17849](https://github.com/atom/atom/issues/17849) | +| **atom-dark-ui** | [`atom/atom-dark-ui`][atom-dark-ui] | [#17850](https://github.com/atom/atom/issues/17850) | +| **atom-light-syntax** | [`atom/atom-light-syntax`][atom-light-syntax] | [#17851](https://github.com/atom/atom/issues/17851) | +| **atom-light-ui** | [`atom/atom-light-ui`][atom-light-ui] | [#17852](https://github.com/atom/atom/issues/17852) | +| **autocomplete-atom-api** | [`atom/autocomplete-atom-api`][autocomplete-atom-api] | | +| **autocomplete-css** | [`atom/autocomplete-css`][autocomplete-css] | | +| **autocomplete-html** | [`atom/autocomplete-html`][autocomplete-html] | | +| **autocomplete-plus** | [`atom/autocomplete-plus`][autocomplete-plus] | | +| **autocomplete-snippets** | [`atom/autocomplete-snippets`][autocomplete-snippets] | | +| **autoflow** | [`atom/autoflow`][autoflow] | [#17833](https://github.com/atom/atom/issues/17833) | +| **autosave** | [`atom/autosave`][autosave] | [#17834](https://github.com/atom/atom/issues/17834) | +| **background-tips** | [`atom/background-tips`][background-tips] | [#17835](https://github.com/atom/atom/issues/17835) | +| **base16-tomorrow-dark-theme** | [`atom/base16-tomorrow-dark-theme`][base16-tomorrow-dark-theme] | [#17836](https://github.com/atom/atom/issues/17836) | +| **base16-tomorrow-light-theme** | [`atom/base16-tomorrow-light-theme`][base16-tomorrow-light-theme] | [#17837](https://github.com/atom/atom/issues/17837) | +| **bookmarks** | [`atom/bookmarks`][bookmarks] | | +| **bracket-matcher** | [`atom/bracket-matcher`][bracket-matcher] | | +| **command-palette** | [`atom/command-palette`][command-palette] | | +| **dalek** | [`atom/dalek`][dalek] | [#17838](https://github.com/atom/atom/issues/17838) | +| **deprecation-cop** | [`atom/deprecation-cop`][deprecation-cop] | [#17839](https://github.com/atom/atom/issues/17839) | +| **dev-live-reload** | [`atom/dev-live-reload`][dev-live-reload] | [#17840](https://github.com/atom/atom/issues/17840) | +| **encoding-selector** | [`atom/encoding-selector`][encoding-selector] | [#17841](https://github.com/atom/atom/issues/17841) | +| **exception-reporting** | [`atom/exception-reporting`][exception-reporting] | [#17842](https://github.com/atom/atom/issues/17842) | +| **find-and-replace** | [`atom/find-and-replace`][find-and-replace] | | +| **fuzzy-finder** | [`atom/fuzzy-finder`][fuzzy-finder] | | +| **github** | [`atom/github`][github] | | +| **git-diff** | [`atom/git-diff`][git-diff] | [#17843](https://github.com/atom/atom/issues/17843) | +| **go-to-line** | [`atom/go-to-line`][go-to-line] | [#17844](https://github.com/atom/atom/issues/17844) | +| **grammar-selector** | [`atom/grammar-selector`][grammar-selector] | [#17845](https://github.com/atom/atom/issues/17845) | +| **image-view** | [`atom/image-view`][image-view] | | +| **incompatible-packages** | [`atom/incompatible-packages`][incompatible-packages] | [#17846](https://github.com/atom/atom/issues/17846) | +| **keybinding-resolver** | [`atom/keybinding-resolver`][keybinding-resolver] | | +| **language-c** | [`atom/language-c`][language-c] | | +| **language-clojure** | [`atom/language-clojure`][language-clojure] | | +| **language-coffee-script** | [`atom/language-coffee-script`][language-coffee-script] | | +| **language-csharp** | [`atom/language-csharp`][language-csharp] | | +| **language-css** | [`atom/language-css`][language-css] | | +| **language-gfm** | [`atom/language-gfm`][language-gfm] | | +| **language-git** | [`atom/language-git`][language-git] | | +| **language-go** | [`atom/language-go`][language-go] | | +| **language-html** | [`atom/language-html`][language-html] | | +| **language-hyperlink** | [`atom/language-hyperlink`][language-hyperlink] | | +| **language-java** | [`atom/language-java`][language-java] | | +| **language-javascript** | [`atom/language-javascript`][language-javascript] | | +| **language-json** | [`atom/language-json`][language-json] | | +| **language-less** | [`atom/language-less`][language-less] | | +| **language-make** | [`atom/language-make`][language-make] | | +| **language-mustache** | [`atom/language-mustache`][language-mustache] | | +| **language-objective-c** | [`atom/language-objective-c`][language-objective-c] | | +| **language-perl** | [`atom/language-perl`][language-perl] | | +| **language-php** | [`atom/language-php`][language-php] | | +| **language-property-list** | [`atom/language-property-list`][language-property-list] | | +| **language-python** | [`atom/language-python`][language-python] | | +| **language-ruby** | [`atom/language-ruby`][language-ruby] | | +| **language-ruby-on-rails** | [`atom/language-ruby-on-rails`][language-ruby-on-rails] | | +| **language-sass** | [`atom/language-sass`][language-sass] | | +| **language-shellscript** | [`atom/language-shellscript`][language-shellscript] | | +| **language-source** | [`atom/language-source`][language-source] | | +| **language-sql** | [`atom/language-sql`][language-sql] | | +| **language-text** | [`atom/language-text`][language-text] | | +| **language-todo** | [`atom/language-todo`][language-todo] | | +| **language-toml** | [`atom/language-toml`][language-toml] | | +| **language-typescript** | [`atom/language-typescript`][language-typescript] | | +| **language-xml** | [`atom/language-xml`][language-xml] | | +| **language-yaml** | [`atom/language-yaml`][language-yaml] | | +| **line-ending-selector** | [`atom/line-ending-selector`][line-ending-selector] | [#17847](https://github.com/atom/atom/issues/17847) | +| **link** | [`atom/link`][link] | [#17848](https://github.com/atom/atom/issues/17848) | +| **markdown-preview** | [`atom/markdown-preview`][markdown-preview] | | +| **metrics** | [`atom/metrics`][metrics] | | +| **notifications** | [`atom/notifications`][notifications] | | +| **one-dark-syntax** | [`atom/one-dark-syntax`][one-dark-syntax] | [#17853](https://github.com/atom/atom/issues/17853) | +| **one-dark-ui** | [`atom/one-dark-ui`][one-dark-ui] | [#17854](https://github.com/atom/atom/issues/17854) | +| **one-light-syntax** | [`atom/one-light-syntax`][one-light-syntax] | [#17855](https://github.com/atom/atom/issues/17855) | +| **one-light-ui** | [`./packages/one-light-ui`](./one-light-ui) | [#17856](https://github.com/atom/atom/issues/17856) | +| **open-on-github** | [`atom/open-on-github`][open-on-github] | | +| **package-generator** | [`atom/package-generator`][package-generator] | | +| **settings-view** | [`atom/settings-view`][settings-view] | | +| **snippets** | [`atom/snippets`][snippets] | | +| **solarized-dark-syntax** | [`atom/solarized-dark-syntax`][solarized-dark-syntax] | | +| **solarized-light-syntax** | [`atom/solarized-light-syntax`][solarized-light-syntax] | | +| **spell-check** | [`atom/spell-check`][spell-check] | | +| **status-bar** | [`atom/status-bar`][status-bar] | | +| **styleguide** | [`atom/styleguide`][styleguide] | | +| **symbols-view** | [`atom/symbols-view`][symbols-view] | | +| **tabs** | [`atom/tabs`][tabs] | | +| **timecop** | [`atom/timecop`][timecop] | | +| **tree-view** | [`atom/tree-view`][tree-view] | | +| **update-package-dependencies** | [`atom/update-package-dependencies`][update-package-dependencies] | | +| **welcome** | [`atom/welcome`][welcome] | | +| **whitespace** | [`atom/whitespace`][whitespace] | | +| **wrap-guide** | [`atom/wrap-guide`][wrap-guide] | | + +[about]: https://github.com/atom/about +[archive-view]: https://github.com/atom/archive-view +[atom-dark-syntax]: https://github.com/atom/atom-dark-syntax +[atom-dark-ui]: https://github.com/atom/atom-dark-ui +[atom-light-syntax]: https://github.com/atom/atom-light-syntax +[atom-light-ui]: https://github.com/atom/atom-light-ui +[autocomplete-atom-api]: https://github.com/atom/autocomplete-atom-api +[autocomplete-css]: https://github.com/atom/autocomplete-css +[autocomplete-html]: https://github.com/atom/autocomplete-html +[autocomplete-plus]: https://github.com/atom/autocomplete-plus +[autocomplete-snippets]: https://github.com/atom/autocomplete-snippets +[autoflow]: https://github.com/atom/autoflow +[autosave]: https://github.com/atom/autosave +[background-tips]: https://github.com/atom/background-tips +[base16-tomorrow-dark-theme]: https://github.com/atom/base16-tomorrow-dark-theme +[base16-tomorrow-light-theme]: https://github.com/atom/base16-tomorrow-light-theme +[bookmarks]: https://github.com/atom/bookmarks +[bracket-matcher]: https://github.com/atom/bracket-matcher +[command-palette]: https://github.com/atom/command-palette +[dalek]: https://github.com/atom/dalek +[deprecation-cop]: https://github.com/atom/deprecation-cop +[dev-live-reload]: https://github.com/atom/dev-live-reload +[encoding-selector]: https://github.com/atom/encoding-selector +[exception-reporting]: https://github.com/atom/exception-reporting +[find-and-replace]: https://github.com/atom/find-and-replace +[fuzzy-finder]: https://github.com/atom/fuzzy-finder +[git-diff]: https://github.com/atom/git-diff +[github]: https://github.com/atom/github +[go-to-line]: https://github.com/atom/go-to-line +[grammar-selector]: https://github.com/atom/grammar-selector +[image-view]: https://github.com/atom/image-view +[incompatible-packages]: https://github.com/atom/incompatible-packages +[keybinding-resolver]: https://github.com/atom/keybinding-resolver +[language-c]: https://github.com/atom/language-c +[language-clojure]: https://github.com/atom/language-clojure +[language-coffee-script]: https://github.com/atom/language-coffee-script +[language-csharp]: https://github.com/atom/language-csharp +[language-css]: https://github.com/atom/language-css +[language-gfm]: https://github.com/atom/language-gfm +[language-git]: https://github.com/atom/language-git +[language-go]: https://github.com/atom/language-go +[language-html]: https://github.com/atom/language-html +[language-hyperlink]: https://github.com/atom/language-hyperlink +[language-java]: https://github.com/atom/language-java +[language-javascript]: https://github.com/atom/language-javascript +[language-json]: https://github.com/atom/language-json +[language-less]: https://github.com/atom/language-less +[language-make]: https://github.com/atom/language-make +[language-mustache]: https://github.com/atom/language-mustache +[language-objective-c]: https://github.com/atom/language-objective-c +[language-perl]: https://github.com/atom/language-perl +[language-php]: https://github.com/atom/language-php +[language-property-list]: https://github.com/atom/language-property-list +[language-python]: https://github.com/atom/language-python +[language-ruby]: https://github.com/atom/language-ruby +[language-ruby-on-rails]: https://github.com/atom/language-ruby-on-rails +[language-sass]: https://github.com/atom/language-sass +[language-shellscript]: https://github.com/atom/language-shellscript +[language-source]: https://github.com/atom/language-source +[language-sql]: https://github.com/atom/language-sql +[language-text]: https://github.com/atom/language-text +[language-todo]: https://github.com/atom/language-todo +[language-toml]: https://github.com/atom/language-toml +[language-typescript]: https://github.com/atom/language-typescript +[language-xml]: https://github.com/atom/language-xml +[language-yaml]: https://github.com/atom/language-yaml +[line-ending-selector]: https://github.com/atom/line-ending-selector +[link]: https://github.com/atom/link +[markdown-preview]: https://github.com/atom/markdown-preview +[metrics]: https://github.com/atom/metrics +[notifications]: https://github.com/atom/notifications +[one-dark-syntax]: https://github.com/atom/one-dark-syntax +[one-dark-ui]: https://github.com/atom/one-dark-ui +[one-light-syntax]: https://github.com/atom/one-light-syntax +[one-light-ui]: https://github.com/atom/one-light-ui +[open-on-github]: https://github.com/atom/open-on-github +[package-generator]: https://github.com/atom/package-generator +[settings-view]: https://github.com/atom/settings-view +[snippets]: https://github.com/atom/snippets +[solarized-dark-syntax]: https://github.com/atom/solarized-dark-syntax +[solarized-light-syntax]: https://github.com/atom/solarized-light-syntax +[spell-check]: https://github.com/atom/spell-check +[status-bar]: https://github.com/atom/status-bar +[styleguide]: https://github.com/atom/styleguide +[symbols-view]: https://github.com/atom/symbols-view +[tabs]: https://github.com/atom/tabs +[timecop]: https://github.com/atom/timecop +[tree-view]: https://github.com/atom/tree-view +[update-package-dependencies]: https://github.com/atom/update-package-dependencies +[welcome]: https://github.com/atom/welcome +[whitespace]: https://github.com/atom/whitespace +[wrap-guide]: https://github.com/atom/wrap-guide diff --git a/packages/about/.gitignore b/packages/about/.gitignore new file mode 100644 index 000000000..ade14b919 --- /dev/null +++ b/packages/about/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +npm-debug.log +node_modules diff --git a/packages/about/LICENSE.md b/packages/about/LICENSE.md new file mode 100644 index 000000000..cf3de7776 --- /dev/null +++ b/packages/about/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (c) 2015 Machisté N. Quintana + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/about/README.md b/packages/about/README.md new file mode 100644 index 000000000..83aeb8755 --- /dev/null +++ b/packages/about/README.md @@ -0,0 +1,21 @@ +# About package + +View useful information about your Atom installation. + +![About Atom](https://cloud.githubusercontent.com/assets/16760489/19395499/69bbb780-922d-11e6-9779-2b8327027ea5.png) + +This is a package for [Atom](https://atom.io), a hackable text editor for the 21st Century. + +## Usage + +This package provides a cross-platform "About Atom" view that displays information about your Atom installation, which currently includes the current version, the license, and the Terms of Use. + +## Contributing +Always feel free to help out! Whether it's filing bugs and feature requests +or working on some of the open issues, Atom's [contributing guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md) +will help get you started while the [guide for contributing to packages](https://github.com/atom/atom/blob/master/docs/contributing-to-packages.md) +has some extra information. + +## License + +[MIT License](https://opensource.org/licenses/MIT) - see the [LICENSE](https://github.com/atom/about/blob/master/LICENSE.md) for more details. diff --git a/packages/about/lib/about.js b/packages/about/lib/about.js new file mode 100644 index 000000000..1221bda6d --- /dev/null +++ b/packages/about/lib/about.js @@ -0,0 +1,93 @@ +const {CompositeDisposable, Emitter} = require('atom') +const AboutView = require('./components/about-view') + +// Deferred requires +let shell + +module.exports = class About { + constructor (initialState) { + this.subscriptions = new CompositeDisposable() + this.emitter = new Emitter() + + this.state = initialState + this.views = { + aboutView: null + } + + this.subscriptions.add(atom.workspace.addOpener((uriToOpen) => { + if (uriToOpen === this.state.uri) { + return this.deserialize() + } + })) + + this.subscriptions.add(atom.commands.add('atom-workspace', 'about:view-release-notes', () => { + shell = shell || require('electron').shell + shell.openExternal(this.state.updateManager.getReleaseNotesURLForCurrentVersion()) + })) + } + + destroy () { + if (this.views.aboutView) this.views.aboutView.destroy() + this.views.aboutView = null + + if (this.state.updateManager) this.state.updateManager.dispose() + this.setState({updateManager: null}) + + this.subscriptions.dispose() + } + + setState (newState) { + if (newState && typeof newState === 'object') { + let {state} = this + this.state = Object.assign({}, state, newState) + + this.didChange() + } + } + + didChange () { + this.emitter.emit('did-change') + } + + onDidChange (callback) { + this.emitter.on('did-change', callback) + } + + deserialize (state) { + if (!this.views.aboutView) { + this.setState(state) + + this.views.aboutView = new AboutView({ + uri: this.state.uri, + updateManager: this.state.updateManager, + currentAtomVersion: this.state.currentAtomVersion, + currentElectronVersion: this.state.currentElectronVersion, + currentChromeVersion: this.state.currentChromeVersion, + currentNodeVersion: this.state.currentNodeVersion, + availableVersion: this.state.updateManager.getAvailableVersion() + }) + this.handleStateChanges() + } + + return this.views.aboutView + } + + handleStateChanges () { + this.onDidChange(() => { + if (this.views.aboutView) { + this.views.aboutView.update({ + updateManager: this.state.updateManager, + currentAtomVersion: this.state.currentAtomVersion, + currentElectronVersion: this.state.currentElectronVersion, + currentChromeVersion: this.state.currentChromeVersion, + currentNodeVersion: this.state.currentNodeVersion, + availableVersion: this.state.updateManager.getAvailableVersion() + }) + } + }) + + this.state.updateManager.onDidChange(() => { + this.didChange() + }) + } +} diff --git a/packages/about/lib/components/about-status-bar.js b/packages/about/lib/components/about-status-bar.js new file mode 100644 index 000000000..d55800f5d --- /dev/null +++ b/packages/about/lib/components/about-status-bar.js @@ -0,0 +1,30 @@ +const {CompositeDisposable} = require('atom') +const etch = require('etch') +const EtchComponent = require('../etch-component') + +const $ = etch.dom + +module.exports = +class AboutStatusBar extends EtchComponent { + constructor () { + super() + this.subscriptions = new CompositeDisposable() + + this.subscriptions.add(atom.tooltips.add(this.element, {title: 'An update will be installed the next time Atom is relaunched.

Click the squirrel icon for more information.'})) + } + + handleClick () { + atom.workspace.open('atom://about') + } + + render () { + return $.div({className: 'about-release-notes inline-block', onclick: this.handleClick.bind(this)}, + $.span({type: 'button', className: 'icon icon-squirrel'}) + ) + } + + destroy () { + super.destroy() + this.subscriptions.dispose() + } +} diff --git a/packages/about/lib/components/about-view.js b/packages/about/lib/components/about-view.js new file mode 100644 index 000000000..3e370b171 --- /dev/null +++ b/packages/about/lib/components/about-view.js @@ -0,0 +1,159 @@ +const {Disposable} = require('atom') +const etch = require('etch') +const shell = require('shell') +const AtomLogo = require('./atom-logo') +const EtchComponent = require('../etch-component') +const UpdateView = require('./update-view') + +const $ = etch.dom + +module.exports = +class AboutView extends EtchComponent { + handleAtomVersionClick (e) { + e.preventDefault() + atom.clipboard.write(this.props.currentAtomVersion) + } + + handleElectronVersionClick (e) { + e.preventDefault() + atom.clipboard.write(this.props.currentElectronVersion) + } + + handleChromeVersionClick (e) { + e.preventDefault() + atom.clipboard.write(this.props.currentChromeVersion) + } + + handleNodeVersionClick (e) { + e.preventDefault() + atom.clipboard.write(this.props.currentNodeVersion) + } + + handleReleaseNotesClick (e) { + e.preventDefault() + shell.openExternal(this.props.updateManager.getReleaseNotesURLForAvailableVersion()) + } + + handleLicenseClick (e) { + e.preventDefault() + atom.commands.dispatch(atom.views.getView(atom.workspace), 'application:open-license') + } + + handleTermsOfUseClick (e) { + e.preventDefault() + shell.openExternal('https://atom.io/terms') + } + + handleHowToUpdateClick (e) { + e.preventDefault() + shell.openExternal('https://flight-manual.atom.io/getting-started/sections/installing-atom/') + } + + handleShowMoreClick (e) { + e.preventDefault() + var showMoreDiv = document.querySelector('.show-more') + var showMoreText = document.querySelector('.about-more-expand') + switch (showMoreText.textContent) { + case 'Show more': + showMoreDiv.classList.toggle('hidden') + showMoreText.textContent = 'Hide' + break + case 'Hide': + showMoreDiv.classList.toggle('hidden') + showMoreText.textContent = 'Show more' + break + } + } + + render () { + return $.div({className: 'pane-item native-key-bindings about'}, + $.div({className: 'about-container'}, + $.header({className: 'about-header'}, + $.a({className: 'about-atom-io', href: 'https://atom.io'}, + $(AtomLogo) + ), + $.div({className: 'about-header-info'}, + $.span({className: 'about-version-container inline-block atom', onclick: this.handleAtomVersionClick.bind(this)}, + $.span({className: 'about-version'}, `${this.props.currentAtomVersion} ${process.arch}`), + $.span({className: 'icon icon-clippy about-copy-version'}) + ), + $.a({className: 'about-header-release-notes', onclick: this.handleReleaseNotesClick.bind(this)}, 'Release Notes') + ), + $.span({className: 'about-version-container inline-block show-more-expand', onclick: this.handleShowMoreClick.bind(this)}, + $.span({className: 'about-more-expand'}, 'Show more') + ), + $.div({className: 'show-more hidden about-more-info'}, + $.div({className: 'about-more-info'}, + $.span({className: 'about-version-container inline-block electron', onclick: this.handleElectronVersionClick.bind(this)}, + $.span({className: 'about-more-version'}, `Electron: ${this.props.currentElectronVersion} `), + $.span({className: 'icon icon-clippy about-copy-version'}) + ) + ), + $.div({className: 'about-more-info'}, + $.span({className: 'about-version-container inline-block chrome', onclick: this.handleChromeVersionClick.bind(this)}, + $.span({className: 'about-more-version'}, `Chrome: ${this.props.currentChromeVersion} `), + $.span({className: 'icon icon-clippy about-copy-version'}) + ) + ), + $.div({className: 'about-more-info'}, + $.span({className: 'about-version-container inline-block node', onclick: this.handleNodeVersionClick.bind(this)}, + $.span({className: 'about-more-version'}, `Node: ${this.props.currentNodeVersion} `), + $.span({className: 'icon icon-clippy about-copy-version'}) + ) + ) + ) + ) + ), + + $(UpdateView, { + updateManager: this.props.updateManager, + availableVersion: this.props.availableVersion, + viewUpdateReleaseNotes: this.handleReleaseNotesClick.bind(this), + viewUpdateInstructions: this.handleHowToUpdateClick.bind(this) + }), + + $.div({className: 'about-actions group-item'}, + $.div({className: 'btn-group'}, + $.button({className: 'btn view-license', onclick: this.handleLicenseClick.bind(this)}, 'License'), + $.button({className: 'btn terms-of-use', onclick: this.handleTermsOfUseClick.bind(this)}, 'Terms of Use') + ) + ), + + $.div({className: 'about-love group-start'}, + $.span({className: 'icon icon-code'}), + $.span({className: 'inline'}, ' with '), + $.span({className: 'icon icon-heart'}), + $.span({className: 'inline'}, ' by '), + $.a({className: 'icon icon-logo-github', href: 'https://github.com'}) + ), + + $.div({className: 'about-credits group-item'}, + $.span({className: 'inline'}, 'And the awesome '), + $.a({href: 'https://github.com/atom/atom/contributors'}, 'Atom Community') + ) + ) + } + + serialize () { + return { + deserializer: this.constructor.name, + uri: this.props.uri + } + } + + onDidChangeTitle () { + return new Disposable() + } + + onDidChangeModified () { + return new Disposable() + } + + getTitle () { + return 'About' + } + + getIconName () { + return 'info' + } +} diff --git a/packages/about/lib/components/atom-logo.js b/packages/about/lib/components/atom-logo.js new file mode 100644 index 000000000..f8b620ce1 --- /dev/null +++ b/packages/about/lib/components/atom-logo.js @@ -0,0 +1,28 @@ +const etch = require('etch') +const EtchComponent = require('../etch-component') + +const $ = etch.dom + +module.exports = +class AtomLogo extends EtchComponent { + render () { + return $.svg({className: 'about-logo', width: '330px', height: '68px', viewBox: '0 0 330 68'}, + $.g({stroke: 'none', 'stroke-width': '1', fill: 'none', 'fill-rule': 'evenodd'}, + $.g({transform: 'translate(2.000000, 1.000000)'}, + $.g({transform: 'translate(96.000000, 8.000000)', fill: 'currentColor'}, + $.path({d: 'M185.498,3.399 C185.498,2.417 186.34,1.573 187.324,1.573 L187.674,1.573 C188.447,1.573 189.01,1.995 189.5,2.628 L208.676,30.862 L227.852,2.628 C228.272,1.995 228.905,1.573 229.676,1.573 L230.028,1.573 C231.01,1.573 231.854,2.417 231.854,3.399 L231.854,49.403 C231.854,50.387 231.01,51.231 230.028,51.231 C229.044,51.231 228.202,50.387 228.202,49.403 L228.202,8.246 L210.151,34.515 C209.729,35.148 209.237,35.428 208.606,35.428 C207.973,35.428 207.481,35.148 207.061,34.515 L189.01,8.246 L189.01,49.475 C189.01,50.457 188.237,51.231 187.254,51.231 C186.27,51.231 185.498,50.458 185.498,49.475 L185.498,3.399 L185.498,3.399 Z'}), + $.path({d: 'M113.086,26.507 L113.086,26.367 C113.086,12.952 122.99,0.941 137.881,0.941 C152.77,0.941 162.533,12.811 162.533,26.225 L162.533,26.367 C162.533,39.782 152.629,51.792 137.74,51.792 C122.85,51.792 113.086,39.923 113.086,26.507 M158.74,26.507 L158.74,26.367 C158.74,14.216 149.89,4.242 137.74,4.242 C125.588,4.242 116.879,14.075 116.879,26.225 L116.879,26.367 C116.879,38.518 125.729,48.491 137.881,48.491 C150.031,48.491 158.74,38.658 158.74,26.507'}), + $.path({d: 'M76.705,5.155 L60.972,5.155 C60.06,5.155 59.287,4.384 59.287,3.469 C59.287,2.556 60.059,1.783 60.972,1.783 L96.092,1.783 C97.004,1.783 97.778,2.555 97.778,3.469 C97.778,4.383 97.005,5.155 96.092,5.155 L80.358,5.155 L80.358,49.405 C80.358,50.387 79.516,51.231 78.532,51.231 C77.55,51.231 76.706,50.387 76.706,49.405 L76.706,5.155 L76.705,5.155 Z'}), + $.path({d: 'M0.291,48.562 L21.291,3.05 C21.783,1.995 22.485,1.292 23.75,1.292 L23.891,1.292 C25.155,1.292 25.858,1.995 26.348,3.05 L47.279,48.421 C47.49,48.843 47.56,49.194 47.56,49.546 C47.56,50.458 46.788,51.231 45.803,51.231 C44.961,51.231 44.329,50.599 43.978,49.826 L38.219,37.183 L9.21,37.183 L3.45,49.897 C3.099,50.739 2.538,51.231 1.694,51.231 C0.781,51.231 0.008,50.529 0.008,49.685 C0.009,49.404 0.08,48.983 0.291,48.562 L0.291,48.562 Z M36.673,33.882 L23.749,5.437 L10.755,33.882 L36.673,33.882 L36.673,33.882 Z'}) + ), + $.g({}, + $.path({d: 'M40.363,32.075 C40.874,34.44 39.371,36.77 37.006,37.282 C34.641,37.793 32.311,36.29 31.799,33.925 C31.289,31.56 32.791,29.23 35.156,28.718 C37.521,28.207 39.851,29.71 40.363,32.075', fill: 'currentColor'}), + $.path({d: 'M48.578,28.615 C56.851,45.587 58.558,61.581 52.288,64.778 C45.822,68.076 33.326,56.521 24.375,38.969 C15.424,21.418 13.409,4.518 19.874,1.221 C22.689,-0.216 26.648,1.166 30.959,4.629', stroke: 'currentColor', 'stroke-width': '3.08', 'stroke-linecap': 'round'}), + $.path({d: 'M7.64,39.45 C2.806,36.94 -0.009,33.915 0.154,30.79 C0.531,23.542 16.787,18.497 36.462,19.52 C56.137,20.544 71.781,27.249 71.404,34.497 C71.241,37.622 68.127,40.338 63.06,42.333', stroke: 'currentColor', 'stroke-width': '3.08', 'stroke-linecap': 'round'}), + $.path({d: 'M28.828,59.354 C23.545,63.168 18.843,64.561 15.902,62.653 C9.814,58.702 13.572,42.102 24.296,25.575 C35.02,9.048 48.649,-1.149 54.736,2.803 C57.566,4.639 58.269,9.208 57.133,15.232', stroke: 'currentColor', 'stroke-width': '3.08', 'stroke-linecap': 'round'}) + ) + ) + ) + ) + } +} diff --git a/packages/about/lib/components/update-view.js b/packages/about/lib/components/update-view.js new file mode 100644 index 000000000..a4e97e74d --- /dev/null +++ b/packages/about/lib/components/update-view.js @@ -0,0 +1,121 @@ +const etch = require('etch') +const EtchComponent = require('../etch-component') +const UpdateManager = require('../update-manager') + +const $ = etch.dom + +module.exports = +class UpdateView extends EtchComponent { + constructor (props) { + super(props) + + if (this.props.updateManager.getAutoUpdatesEnabled() && this.props.updateManager.getState() === UpdateManager.State.Idle) { + this.props.updateManager.checkForUpdate() + } + } + + handleAutoUpdateCheckbox (e) { + atom.config.set('core.automaticallyUpdate', e.target.checked) + } + + shouldUpdateActionButtonBeDisabled () { + let {state} = this.props.updateManager + return state === UpdateManager.State.CheckingForUpdate || state === UpdateManager.State.DownloadingUpdate + } + + executeUpdateAction () { + if (this.props.updateManager.state === UpdateManager.State.UpdateAvailableToInstall) { + this.props.updateManager.restartAndInstallUpdate() + } else { + this.props.updateManager.checkForUpdate() + } + } + + renderUpdateStatus () { + let updateStatus = '' + + switch (this.props.updateManager.state) { + case UpdateManager.State.Idle: + updateStatus = $.div({className: 'about-updates-item is-shown about-default-update-message'}, + this.props.updateManager.getAutoUpdatesEnabled() ? 'Atom will check for updates automatically' : 'Automatic updates are disabled please check manually' + ) + break + case UpdateManager.State.CheckingForUpdate: + updateStatus = $.div({className: 'about-updates-item app-checking-for-updates'}, + $.span({className: 'about-updates-label icon icon-search'}, 'Checking for updates...') + ) + break + case UpdateManager.State.DownloadingUpdate: + updateStatus = $.div({className: 'about-updates-item app-downloading-update'}, + $.span({className: 'loading loading-spinner-tiny inline-block'}), + $.span({className: 'about-updates-label'}, 'Downloading update') + ) + break + case UpdateManager.State.UpdateAvailableToInstall: + updateStatus = $.div({className: 'about-updates-item app-update-available-to-install'}, + $.span({className: 'about-updates-label icon icon-squirrel'}, 'New update'), + $.span({className: 'about-updates-version'}, this.props.availableVersion), + $.a({className: 'about-updates-release-notes', onclick: this.props.viewUpdateReleaseNotes}, 'Release Notes') + ) + break + case UpdateManager.State.UpToDate: + updateStatus = $.div({className: 'about-updates-item app-up-to-date'}, + $.span({className: 'icon icon-check'}), + $.span({className: 'about-updates-label is-strong'}, 'Atom is up to date!') + ) + break + case UpdateManager.State.Unsupported: + updateStatus = $.div({className: 'about-updates-item app-unsupported'}, + $.span({className: 'about-updates-label is-strong'}, 'Your system does not support automatic updates'), + $.a({className: 'about-updates-instructions', onclick: this.props.viewUpdateInstructions}, 'How to update') + ) + break + case UpdateManager.State.Error: + updateStatus = $.div({className: 'about-updates-item app-update-error'}, + $.span({className: 'icon icon-x'}), + $.span({className: 'about-updates-label app-error-message is-strong'}, this.props.updateManager.getErrorMessage()) + ) + break + } + + return updateStatus + } + + render () { + return $.div({className: 'about-updates group-start'}, + $.div({className: 'about-updates-box'}, + $.div({className: 'about-updates-status'}, this.renderUpdateStatus()), + $.button( + { + className: 'btn about-update-action-button', + disabled: this.shouldUpdateActionButtonBeDisabled(), + onclick: this.executeUpdateAction.bind(this), + style: { + display: this.props.updateManager.state === UpdateManager.State.Unsupported ? 'none' : 'block' + } + }, + this.props.updateManager.state === 'update-available' ? 'Restart and install' : 'Check now' + ) + ), + $.div( + { + className: 'about-auto-updates', + style: { + display: this.props.updateManager.state === UpdateManager.State.Unsupported ? 'none' : 'block' + } + }, + $.label({}, + $.input( + { + className: 'input-checkbox', + type: 'checkbox', + checked: this.props.updateManager.getAutoUpdatesEnabled(), + onchange: this.handleAutoUpdateCheckbox.bind(this) + } + ), + $.span({}, 'Automatically download updates') + ) + ) + ) + } +} diff --git a/packages/about/lib/etch-component.js b/packages/about/lib/etch-component.js new file mode 100644 index 000000000..f75edce94 --- /dev/null +++ b/packages/about/lib/etch-component.js @@ -0,0 +1,57 @@ +const etch = require('etch') + +/* + Public: Abstract class for handling the initialization + boilerplate of an Etch component. +*/ +module.exports = +class EtchComponent { + constructor (props) { + this.props = props + + etch.initialize(this) + EtchComponent.setScheduler(atom.views) + } + + /* + Public: Gets the scheduler Etch uses for coordinating DOM updates. + + Returns a {Scheduler} + */ + static getScheduler () { + return etch.getScheduler() + } + + /* + Public: Sets the scheduler Etch uses for coordinating DOM updates. + + * `scheduler` {Scheduler} + */ + static setScheduler (scheduler) { + etch.setScheduler(scheduler) + } + + /* + Public: Updates the component's properties and re-renders it. Only the + properties you specify in this object will update – any other properties + the component stores will be unaffected. + + * `props` an {Object} representing the properties you want to update + */ + update (props) { + let oldProps = this.props + this.props = Object.assign({}, oldProps, props) + return etch.update(this) + } + + /* + Public: Destroys the component, removing it from the DOM. + */ + destroy () { + etch.destroy(this) + } + + render () { + throw new Error('Etch components must implement a `render` method') + } +} diff --git a/packages/about/lib/main.js b/packages/about/lib/main.js new file mode 100644 index 000000000..f0b855649 --- /dev/null +++ b/packages/about/lib/main.js @@ -0,0 +1,96 @@ +const {CompositeDisposable} = require('atom') +const semver = require('semver') +const UpdateManager = require('./update-manager') +const About = require('./about') +const StatusBarView = require('./components/about-status-bar') +let updateManager + +// The local storage key for the available update version. +const AvailableUpdateVersion = 'about:version-available' +const AboutURI = 'atom://about' + +module.exports = { + activate () { + this.subscriptions = new CompositeDisposable() + + this.createModel() + + let availableVersion = window.localStorage.getItem(AvailableUpdateVersion) + if (atom.getReleaseChannel() === 'dev' || (availableVersion && semver.lte(availableVersion, atom.getVersion()))) { + this.clearUpdateState() + } + + this.subscriptions.add(updateManager.onDidChange(() => { + if (updateManager.getState() === UpdateManager.State.UpdateAvailableToInstall) { + window.localStorage.setItem(AvailableUpdateVersion, updateManager.getAvailableVersion()) + this.showStatusBarIfNeeded() + } + })) + + this.subscriptions.add(atom.commands.add('atom-workspace', 'about:clear-update-state', () => { + this.clearUpdateState() + })) + }, + + deactivate () { + this.model.destroy() + if (this.statusBarTile) this.statusBarTile.destroy() + + if (updateManager) { + updateManager.dispose() + updateManager = undefined + } + }, + + clearUpdateState () { + window.localStorage.removeItem(AvailableUpdateVersion) + }, + + consumeStatusBar (statusBar) { + this.statusBar = statusBar + this.showStatusBarIfNeeded() + }, + + deserializeAboutView (state) { + if (!this.model) { + this.createModel() + } + + return this.model.deserialize(state) + }, + + createModel () { + updateManager = updateManager || new UpdateManager() + + this.model = new About({ + uri: AboutURI, + currentAtomVersion: atom.getVersion(), + currentElectronVersion: process.versions.electron, + currentChromeVersion: process.versions.chrome, + currentNodeVersion: process.version, + updateManager: updateManager + }) + }, + + isUpdateAvailable () { + let availableVersion = window.localStorage.getItem(AvailableUpdateVersion) + return availableVersion && semver.gt(availableVersion, atom.getVersion()) + }, + + showStatusBarIfNeeded () { + if (this.isUpdateAvailable() && this.statusBar) { + let statusBarView = new StatusBarView() + + if (this.statusBarTile) { + this.statusBarTile.destroy() + } + + this.statusBarTile = this.statusBar.addRightTile({ + item: statusBarView, + priority: -100 + }) + + return this.statusBarTile + } + } +} diff --git a/packages/about/lib/update-manager.js b/packages/about/lib/update-manager.js new file mode 100644 index 000000000..0db55f08d --- /dev/null +++ b/packages/about/lib/update-manager.js @@ -0,0 +1,146 @@ +const {Emitter, CompositeDisposable} = require('atom') + +const Unsupported = 'unsupported' +const Idle = 'idle' +const CheckingForUpdate = 'checking' +const DownloadingUpdate = 'downloading' +const UpdateAvailableToInstall = 'update-available' +const UpToDate = 'no-update-available' +const ErrorState = 'error' + +let UpdateManager = class UpdateManager { + constructor () { + this.emitter = new Emitter() + this.currentVersion = atom.getVersion() + this.availableVersion = atom.getVersion() + this.resetState() + this.listenForAtomEvents() + } + + listenForAtomEvents () { + this.subscriptions = new CompositeDisposable() + + this.subscriptions.add( + atom.autoUpdater.onDidBeginCheckingForUpdate(() => { + this.setState(CheckingForUpdate) + }), + atom.autoUpdater.onDidBeginDownloadingUpdate(() => { + this.setState(DownloadingUpdate) + }), + atom.autoUpdater.onDidCompleteDownloadingUpdate(({releaseVersion}) => { + this.setAvailableVersion(releaseVersion) + }), + atom.autoUpdater.onUpdateNotAvailable(() => { + this.setState(UpToDate) + }), + atom.autoUpdater.onUpdateError(() => { + this.setState(ErrorState) + }), + atom.config.observe('core.automaticallyUpdate', (value) => { + this.autoUpdatesEnabled = value + this.emitDidChange() + }) + ) + + // TODO: When https://github.com/atom/electron/issues/4587 is closed we can add this support. + // atom.autoUpdater.onUpdateAvailable => + // @find('.about-updates-item').removeClass('is-shown') + // @updateAvailable.addClass('is-shown') + } + + dispose () { + this.subscriptions.dispose() + } + + onDidChange (callback) { + return this.emitter.on('did-change', callback) + } + + emitDidChange () { + this.emitter.emit('did-change') + } + + getAutoUpdatesEnabled () { + return this.autoUpdatesEnabled && this.state !== UpdateManager.State.Unsupported + } + + setAutoUpdatesEnabled (enabled) { + return atom.config.set('core.automaticallyUpdate', enabled) + } + + getErrorMessage () { + return atom.autoUpdater.getErrorMessage() + } + + getState () { + return this.state + } + + setState (state) { + this.state = state + this.emitDidChange() + } + + resetState () { + this.state = atom.autoUpdater.platformSupportsUpdates() ? atom.autoUpdater.getState() : Unsupported + this.emitDidChange() + } + + getAvailableVersion () { + return this.availableVersion + } + + setAvailableVersion (version) { + this.availableVersion = version + + if (this.availableVersion !== this.currentVersion) { + this.state = UpdateAvailableToInstall + } else { + this.state = UpToDate + } + + this.emitDidChange() + } + + checkForUpdate () { + atom.autoUpdater.checkForUpdate() + } + + restartAndInstallUpdate () { + atom.autoUpdater.restartAndInstallUpdate() + } + + getReleaseNotesURLForCurrentVersion () { + return this.getReleaseNotesURLForVersion(this.currentVersion) + } + + getReleaseNotesURLForAvailableVersion () { + return this.getReleaseNotesURLForVersion(this.availableVersion) + } + + getReleaseNotesURLForVersion (appVersion) { + // Dev versions will not have a releases page + if (appVersion.indexOf('dev') > -1) { + return 'https://atom.io/releases' + } + + if (!appVersion.startsWith('v')) { + appVersion = `v${appVersion}` + } + + const releaseRepo = appVersion.indexOf('nightly') > -1 ? 'atom-nightly-releases' : 'atom' + return `https://github.com/atom/${releaseRepo}/releases/tag/${appVersion}` + } +} + +UpdateManager.State = { + Unsupported: Unsupported, + Idle: Idle, + CheckingForUpdate: CheckingForUpdate, + DownloadingUpdate: DownloadingUpdate, + UpdateAvailableToInstall: UpdateAvailableToInstall, + UpToDate: UpToDate, + Error: ErrorState +} + +module.exports = UpdateManager diff --git a/packages/about/package-lock.json b/packages/about/package-lock.json new file mode 100644 index 000000000..ab0d5c51b --- /dev/null +++ b/packages/about/package-lock.json @@ -0,0 +1,1806 @@ +{ + "name": "about", + "version": "1.9.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "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-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, + "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 + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "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" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "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" + } + }, + "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" + } + } + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "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" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "dev": true, + "requires": { + "color-name": "1.1.1" + } + }, + "color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", + "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=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", + "dev": true + }, + "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 + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "deglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", + "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", + "dev": true, + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "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" + } + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "^1.1.1", + "is-date-object": "^1.0.1", + "is-symbol": "^1.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": "4.18.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz", + "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==", + "dev": true, + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.2", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + } + }, + "eslint-config-standard": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz", + "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==", + "dev": true + }, + "eslint-config-standard-jsx": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-5.0.0.tgz", + "integrity": "sha512-rLToPAEqLMPBfWnYTu6xRhm2OWziS2n40QFqJ8jAM8NSVzeVKTa3nclhsU4DpPJQRY60F34Oo1wi/71PN/eITg==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "eslint-module-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz", + "integrity": "sha1-JgAu+/ylmJtyiKwEdQi9JPIXsWk=", + "dev": true, + "requires": { + "builtin-modules": "^1.1.1", + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.1.1", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-plugin-node": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz", + "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==", + "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "^5.4.1" + } + }, + "eslint-plugin-promise": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz", + "integrity": "sha512-2WO+ZFh7vxUKRfR0cOIMrWgYKdR6S1AlOezw6pC52B6oYpd5WFghN+QHxvrRdZMtbo8h3dfUZ2o1rWb0UPbKtg==", + "dev": true + }, + "eslint-plugin-react": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz", + "integrity": "sha512-KC7Snr4YsWZD5flu6A5c0AcIZidzW3Exbqp7OT67OaD2AppJtlBr/GuPrW/vaQM/yfZotEvKAdrxrO+v8vwYJA==", + "dev": true, + "requires": { + "doctrine": "^2.0.2", + "has": "^1.0.1", + "jsx-ast-utils": "^2.0.1", + "prop-types": "^15.6.0" + } + }, + "eslint-plugin-standard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.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.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/etch/-/etch-0.9.0.tgz", + "integrity": "sha1-CSJpiPLO4GkL3yCMyyXkFNXfrV8=" + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "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 + }, + "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" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "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 + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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" + } + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "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 + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "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 + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "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-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "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 + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "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 + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "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.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "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 + }, + "jsx-ast-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", + "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", + "dev": true, + "requires": { + "array-includes": "^3.0.3" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "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 + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "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=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "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 + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "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 + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "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" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~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=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "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=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "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": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "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" + } + }, + "pkg-conf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", + "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.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" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pkg-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", + "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", + "dev": true, + "requires": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "^1.0.0" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "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 + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "prop-types": { + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", + "dev": true, + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "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" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "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 + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "*" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + }, + "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 + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "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 + }, + "standard": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/standard/-/standard-11.0.1.tgz", + "integrity": "sha512-nu0jAcHiSc8H+gJCXeiziMVZNDYi8MuqrYJKxTgjP4xKXZMKm311boqQIzDrYI/ktosltxt2CbDjYQs9ANC8IA==", + "dev": true, + "requires": { + "eslint": "~4.18.0", + "eslint-config-standard": "11.0.0", + "eslint-config-standard-jsx": "5.0.0", + "eslint-plugin-import": "~2.9.0", + "eslint-plugin-node": "~6.0.0", + "eslint-plugin-promise": "~3.7.0", + "eslint-plugin-react": "~7.7.0", + "eslint-plugin-standard": "~3.0.1", + "standard-engine": "~8.0.0" + } + }, + "standard-engine": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-8.0.1.tgz", + "integrity": "sha512-LA531C3+nljom/XRvdW/hGPXwmilRkaRkENhO3FAGF1Vtq/WtCXzgmnc5S6vUHHsgv534MRy02C1ikMwZXC+tw==", + "dev": true, + "requires": { + "deglob": "^2.1.0", + "get-stdin": "^6.0.0", + "minimist": "^1.1.0", + "pkg-conf": "^2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.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" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "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 + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "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" + } + }, + "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" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "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" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } +} diff --git a/packages/about/package.json b/packages/about/package.json new file mode 100644 index 000000000..a96955185 --- /dev/null +++ b/packages/about/package.json @@ -0,0 +1,44 @@ +{ + "name": "about", + "author": "Machisté N. Quintana ", + "main": "./lib/main", + "version": "1.9.1", + "description": "View useful information about your Atom installation.", + "keywords": [], + "repository": "https://github.com/atom/about", + "license": "MIT", + "scripts": { + "lint": "standard" + }, + "engines": { + "atom": ">=1.7 <2.0.0" + }, + "dependencies": { + "etch": "0.9.0", + "semver": "^5.5.0" + }, + "devDependencies": { + "standard": "^11.0.0" + }, + "consumedServices": { + "status-bar": { + "versions": { + "^1.0.0": "consumeStatusBar" + } + } + }, + "deserializers": { + "AboutView": "deserializeAboutView" + }, + "standard": { + "env": [ + "browser", + "node", + "atomtest", + "jasmine" + ], + "globals": [ + "atom" + ] + } +} diff --git a/packages/about/spec/about-spec.js b/packages/about/spec/about-spec.js new file mode 100644 index 000000000..60c4136d8 --- /dev/null +++ b/packages/about/spec/about-spec.js @@ -0,0 +1,101 @@ +const {it, fit, ffit, fffit, beforeEach, afterEach} = require('./helpers/async-spec-helpers') // eslint-disable-line no-unused-vars + +describe('About', () => { + let workspaceElement + + beforeEach(async () => { + let storage = {} + + spyOn(window.localStorage, 'setItem').andCallFake((key, value) => { + storage[key] = value + }) + spyOn(window.localStorage, 'getItem').andCallFake((key) => { + return storage[key] + }) + + workspaceElement = atom.views.getView(atom.workspace) + await atom.packages.activatePackage('about') + }) + + it('deserializes correctly', () => { + let deserializedAboutView = atom.deserializers.deserialize({ + deserializer: 'AboutView', + uri: 'atom://about' + }) + + expect(deserializedAboutView).toBeTruthy() + }) + + describe('when the about:about-atom command is triggered', () => { + it('shows the About Atom view', async () => { + // Attaching the workspaceElement to the DOM is required to allow the + // `toBeVisible()` matchers to work. Anything testing visibility or focus + // requires that the workspaceElement is on the DOM. Tests that attach the + // workspaceElement to the DOM are generally slower than those off DOM. + jasmine.attachToDOM(workspaceElement) + + expect(workspaceElement.querySelector('.about')).not.toExist() + await atom.workspace.open('atom://about') + + let aboutElement = workspaceElement.querySelector('.about') + expect(aboutElement).toBeVisible() + }) + }) + + describe('when the Atom version number is clicked', () => { + it('copies the version number to the clipboard', async () => { + await atom.workspace.open('atom://about') + + let aboutElement = workspaceElement.querySelector('.about') + let versionContainer = aboutElement.querySelector('.atom') + versionContainer.click() + expect(atom.clipboard.read()).toBe(atom.getVersion()) + }) + }) + + describe('when the show more link is clicked', () => { + it('expands to show additional version numbers', async () => { + await atom.workspace.open('atom://about') + jasmine.attachToDOM(workspaceElement) + + let aboutElement = workspaceElement.querySelector('.about') + let showMoreElement = aboutElement.querySelector('.show-more-expand') + let moreInfoElement = workspaceElement.querySelector('.show-more') + showMoreElement.click() + expect(moreInfoElement).toBeVisible() + }) + }) + + describe('when the Electron version number is clicked', () => { + it('copies the version number to the clipboard', async () => { + await atom.workspace.open('atom://about') + + let aboutElement = workspaceElement.querySelector('.about') + let versionContainer = aboutElement.querySelector('.electron') + versionContainer.click() + expect(atom.clipboard.read()).toBe(process.versions.electron) + }) + }) + + describe('when the Chrome version number is clicked', () => { + it('copies the version number to the clipboard', async () => { + await atom.workspace.open('atom://about') + + let aboutElement = workspaceElement.querySelector('.about') + let versionContainer = aboutElement.querySelector('.chrome') + versionContainer.click() + expect(atom.clipboard.read()).toBe(process.versions.chrome) + }) + }) + + describe('when the Node version number is clicked', () => { + it('copies the version number to the clipboard', async () => { + await atom.workspace.open('atom://about') + + let aboutElement = workspaceElement.querySelector('.about') + let versionContainer = aboutElement.querySelector('.node') + versionContainer.click() + expect(atom.clipboard.read()).toBe(process.version) + }) + }) +}) diff --git a/packages/about/spec/about-status-bar-spec.js b/packages/about/spec/about-status-bar-spec.js new file mode 100644 index 000000000..a611af67a --- /dev/null +++ b/packages/about/spec/about-status-bar-spec.js @@ -0,0 +1,179 @@ +const {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} = require('./helpers/async-spec-helpers') // eslint-disable-line no-unused-vars +const MockUpdater = require('./mocks/updater') + +describe('the status bar', () => { + let atomVersion + let workspaceElement + + beforeEach(async () => { + let storage = {} + + spyOn(window.localStorage, 'setItem').andCallFake((key, value) => { + storage[key] = value + }) + spyOn(window.localStorage, 'getItem').andCallFake((key) => { + return storage[key] + }) + spyOn(atom, 'getVersion').andCallFake(() => { + return atomVersion + }) + + workspaceElement = atom.views.getView(atom.workspace) + + await atom.packages.activatePackage('status-bar') + await atom.workspace.open('sample.js') + }) + + afterEach(async () => { + await atom.packages.deactivatePackage('about') + await atom.packages.deactivatePackage('status-bar') + }) + + describe('on a stable version', function () { + beforeEach(async () => { + atomVersion = '1.2.3' + + await atom.packages.activatePackage('about') + }) + + describe('with no update', () => { + it('does not show the view', () => { + expect(workspaceElement).not.toContain('.about-release-notes') + }) + }) + + describe('with an update', () => { + it('shows the view when the update finishes downloading', () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + expect(workspaceElement).toContain('.about-release-notes') + }) + + describe('clicking on the status', () => { + it('opens the about page', async () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + workspaceElement.querySelector('.about-release-notes').click() + await conditionPromise(() => workspaceElement.querySelector('.about')) + expect(workspaceElement.querySelector('.about')).toExist() + }) + }) + + it('continues to show the squirrel until Atom is updated to the new version', async () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + expect(workspaceElement).toContain('.about-release-notes') + + await atom.packages.deactivatePackage('about') + expect(workspaceElement).not.toContain('.about-release-notes') + + await atom.packages.activatePackage('about') + await Promise.resolve() // Service consumption hooks are deferred until the next tick + expect(workspaceElement).toContain('.about-release-notes') + + await atom.packages.deactivatePackage('about') + expect(workspaceElement).not.toContain('.about-release-notes') + + atomVersion = '42.0.0' + await atom.packages.activatePackage('about') + + await Promise.resolve() // Service consumption hooks are deferred until the next tick + expect(workspaceElement).not.toContain('.about-release-notes') + }) + + it('does not show the view if Atom is updated to a newer version than notified', async () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + + await atom.packages.deactivatePackage('about') + + atomVersion = '43.0.0' + await atom.packages.activatePackage('about') + + await Promise.resolve() // Service consumption hooks are deferred until the next tick + expect(workspaceElement).not.toContain('.about-release-notes') + }) + }) + }) + + describe('on a beta version', function () { + beforeEach(async () => { + atomVersion = '1.2.3-beta4' + + await atom.packages.activatePackage('about') + }) + + describe('with no update', () => { + it('does not show the view', () => { + expect(workspaceElement).not.toContain('.about-release-notes') + }) + }) + + describe('with an update', () => { + it('shows the view when the update finishes downloading', () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + expect(workspaceElement).toContain('.about-release-notes') + }) + + describe('clicking on the status', () => { + it('opens the about page', async () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + workspaceElement.querySelector('.about-release-notes').click() + await conditionPromise(() => workspaceElement.querySelector('.about')) + expect(workspaceElement.querySelector('.about')).toExist() + }) + }) + + it('continues to show the squirrel until Atom is updated to the new version', async () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + expect(workspaceElement).toContain('.about-release-notes') + + await atom.packages.deactivatePackage('about') + expect(workspaceElement).not.toContain('.about-release-notes') + + await atom.packages.activatePackage('about') + await Promise.resolve() // Service consumption hooks are deferred until the next tick + expect(workspaceElement).toContain('.about-release-notes') + + await atom.packages.deactivatePackage('about') + expect(workspaceElement).not.toContain('.about-release-notes') + + atomVersion = '42.0.0' + await atom.packages.activatePackage('about') + + await Promise.resolve() // Service consumption hooks are deferred until the next tick + expect(workspaceElement).not.toContain('.about-release-notes') + }) + + it('does not show the view if Atom is updated to a newer version than notified', async () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + + await atom.packages.deactivatePackage('about') + + atomVersion = '43.0.0' + await atom.packages.activatePackage('about') + + await Promise.resolve() // Service consumption hooks are deferred until the next tick + expect(workspaceElement).not.toContain('.about-release-notes') + }) + }) + }) + + describe('on a development version', function () { + beforeEach(async () => { + atomVersion = '1.2.3-dev-0123abcd' + + await atom.packages.activatePackage('about') + }) + + describe('with no update', () => { + it('does not show the view', () => { + expect(workspaceElement).not.toContain('.about-release-notes') + }) + }) + + describe('with a previously downloaded update', () => { + it('does not show the view', () => { + window.localStorage.setItem('about:version-available', '42.0.0') + + expect(workspaceElement).not.toContain('.about-release-notes') + }) + }) + }) +}) diff --git a/packages/about/spec/helpers/async-spec-helpers.js b/packages/about/spec/helpers/async-spec-helpers.js new file mode 100644 index 000000000..377024691 --- /dev/null +++ b/packages/about/spec/helpers/async-spec-helpers.js @@ -0,0 +1,65 @@ +/** @babel */ + +const {now} = Date +const {setTimeout} = global + +export function beforeEach (fn) { + global.beforeEach(function () { + const result = fn() + if (result instanceof Promise) { + waitsForPromise(() => result) + } + }) +} + +export function afterEach (fn) { + global.afterEach(function () { + const result = fn() + if (result instanceof Promise) { + waitsForPromise(() => result) + } + }) +} + +['it', 'fit', 'ffit', 'fffit'].forEach(function (name) { + module.exports[name] = function (description, fn) { + global[name](description, function () { + const result = fn() + if (result instanceof Promise) { + waitsForPromise(() => result) + } + }) + } +}) + +export async function conditionPromise (condition) { + const startTime = now() + + while (true) { + await timeoutPromise(100) + + if (await condition()) { + return + } + + if (now() - startTime > 5000) { + throw new Error('Timed out waiting on condition') + } + } +} + +export function timeoutPromise (timeout) { + return new Promise(function (resolve) { + setTimeout(resolve, timeout) + }) +} + +function waitsForPromise (fn) { + const promise = fn() + global.waitsFor('spec promise to resolve', function (done) { + promise.then(done, function (error) { + jasmine.getEnv().currentSpec.fail(error) + done() + }) + }) +} diff --git a/packages/about/spec/mocks/updater.js b/packages/about/spec/mocks/updater.js new file mode 100644 index 000000000..c96ea4ec1 --- /dev/null +++ b/packages/about/spec/mocks/updater.js @@ -0,0 +1,21 @@ +module.exports = { + updateError () { + atom.autoUpdater.emitter.emit('update-error') + }, + + checkForUpdate () { + atom.autoUpdater.emitter.emit('did-begin-checking-for-update') + }, + + updateNotAvailable () { + atom.autoUpdater.emitter.emit('update-not-available') + }, + + downloadUpdate () { + atom.autoUpdater.emitter.emit('did-begin-downloading-update') + }, + + finishDownloadingUpdate (releaseVersion) { + atom.autoUpdater.emitter.emit('did-complete-downloading-update', {releaseVersion}) + } +} diff --git a/packages/about/spec/update-manager-spec.js b/packages/about/spec/update-manager-spec.js new file mode 100644 index 000000000..294e33b8b --- /dev/null +++ b/packages/about/spec/update-manager-spec.js @@ -0,0 +1,22 @@ +const UpdateManager = require('../lib/update-manager') + +describe('UpdateManager', () => { + let updateManager + + beforeEach(() => { + updateManager = new UpdateManager() + }) + + describe('::getReleaseNotesURLForVersion', () => { + it('returns atom.io releases when dev version', () => { + expect(updateManager.getReleaseNotesURLForVersion('1.7.0-dev-e44b57d')).toContain('atom.io/releases') + }) + + it('returns the page for the release when not a dev version', () => { + expect(updateManager.getReleaseNotesURLForVersion('1.7.0')).toContain('atom/atom/releases/tag/v1.7.0') + expect(updateManager.getReleaseNotesURLForVersion('v1.7.0')).toContain('atom/atom/releases/tag/v1.7.0') + expect(updateManager.getReleaseNotesURLForVersion('1.7.0-beta10')).toContain('atom/atom/releases/tag/v1.7.0-beta10') + expect(updateManager.getReleaseNotesURLForVersion('1.7.0-nightly10')).toContain('atom/atom-nightly-releases/releases/tag/v1.7.0-nightly10') + }) + }) +}) diff --git a/packages/about/spec/update-view-spec.js b/packages/about/spec/update-view-spec.js new file mode 100644 index 000000000..83ddf5ac1 --- /dev/null +++ b/packages/about/spec/update-view-spec.js @@ -0,0 +1,280 @@ +const {shell} = require('electron') +const {it, fit, ffit, fffit, beforeEach, afterEach} = require('./helpers/async-spec-helpers') // eslint-disable-line no-unused-vars +const main = require('../lib/main') +const AboutView = require('../lib/components/about-view') +const UpdateView = require('../lib/components/update-view') +const MockUpdater = require('./mocks/updater') + +describe('UpdateView', () => { + let aboutElement + let updateManager + let workspaceElement + let scheduler + + beforeEach(async () => { + let storage = {} + + spyOn(window.localStorage, 'setItem').andCallFake((key, value) => { + storage[key] = value + }) + spyOn(window.localStorage, 'getItem').andCallFake((key) => { + return storage[key] + }) + + workspaceElement = atom.views.getView(atom.workspace) + await atom.packages.activatePackage('about') + spyOn(atom.autoUpdater, 'getState').andReturn('idle') + spyOn(atom.autoUpdater, 'checkForUpdate') + spyOn(atom.autoUpdater, 'platformSupportsUpdates').andReturn(true) + }) + + describe('when the About page is open', () => { + beforeEach(async () => { + jasmine.attachToDOM(workspaceElement) + await atom.workspace.open('atom://about') + aboutElement = workspaceElement.querySelector('.about') + updateManager = main.model.state.updateManager + scheduler = AboutView.getScheduler() + }) + + describe('when the updates are not supported by the platform', () => { + beforeEach(async () => { + atom.autoUpdater.platformSupportsUpdates.andReturn(false) + updateManager.resetState() + await scheduler.getNextUpdatePromise() + }) + + it('hides the auto update UI and shows the update instructions link', async () => { + expect(aboutElement.querySelector('.about-update-action-button')).not.toBeVisible() + expect(aboutElement.querySelector('.about-auto-updates')).not.toBeVisible() + }) + + it('opens the update instructions page when the instructions link is clicked', async () => { + spyOn(shell, 'openExternal') + let link = aboutElement.querySelector('.app-unsupported .about-updates-instructions') + link.click() + + let args = shell.openExternal.mostRecentCall.args + expect(shell.openExternal).toHaveBeenCalled() + expect(args[0]).toContain('installing-atom') + }) + }) + + describe('when updates are supported by the platform', () => { + beforeEach(async () => { + atom.autoUpdater.platformSupportsUpdates.andReturn(true) + updateManager.resetState() + await scheduler.getNextUpdatePromise() + }) + + it('shows the auto update UI', () => { + expect(aboutElement.querySelector('.about-updates')).toBeVisible() + }) + + it('shows the correct panels when the app checks for updates and there is no update available', async () => { + expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible() + + MockUpdater.checkForUpdate() + await scheduler.getNextUpdatePromise() + expect(aboutElement.querySelector('.app-up-to-date')).not.toBeVisible() + expect(aboutElement.querySelector('.app-checking-for-updates')).toBeVisible() + + MockUpdater.updateNotAvailable() + await scheduler.getNextUpdatePromise() + expect(aboutElement.querySelector('.app-up-to-date')).toBeVisible() + expect(aboutElement.querySelector('.app-checking-for-updates')).not.toBeVisible() + }) + + it('shows the correct panels when the app checks for updates and encounters an error', async () => { + expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible() + + MockUpdater.checkForUpdate() + await scheduler.getNextUpdatePromise() + expect(aboutElement.querySelector('.app-up-to-date')).not.toBeVisible() + expect(aboutElement.querySelector('.app-checking-for-updates')).toBeVisible() + + spyOn(atom.autoUpdater, 'getErrorMessage').andReturn('an error message') + MockUpdater.updateError() + await scheduler.getNextUpdatePromise() + expect(aboutElement.querySelector('.app-update-error')).toBeVisible() + expect(aboutElement.querySelector('.app-error-message').textContent).toBe('an error message') + expect(aboutElement.querySelector('.app-checking-for-updates')).not.toBeVisible() + expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(false) + expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now') + }) + + it('shows the correct panels and button states when the app checks for updates and an update is downloaded', async () => { + expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible() + expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(false) + expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now') + + MockUpdater.checkForUpdate() + await scheduler.getNextUpdatePromise() + + expect(aboutElement.querySelector('.app-up-to-date')).not.toBeVisible() + expect(aboutElement.querySelector('.app-checking-for-updates')).toBeVisible() + expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(true) + expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now') + + MockUpdater.downloadUpdate() + await scheduler.getNextUpdatePromise() + expect(aboutElement.querySelector('.app-checking-for-updates')).not.toBeVisible() + expect(aboutElement.querySelector('.app-downloading-update')).toBeVisible() + // TODO: at some point it would be nice to be able to cancel an update download, and then this would be a cancel button + expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(true) + expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now') + + MockUpdater.finishDownloadingUpdate('42.0.0') + await scheduler.getNextUpdatePromise() + expect(aboutElement.querySelector('.app-downloading-update')).not.toBeVisible() + expect(aboutElement.querySelector('.app-update-available-to-install')).toBeVisible() + + expect(aboutElement.querySelector('.app-update-available-to-install .about-updates-version').textContent).toBe('42.0.0') + expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(false) + expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Restart and install') + }) + + it('opens the release notes for the downloaded release when the release notes link are clicked', async () => { + MockUpdater.finishDownloadingUpdate('1.2.3') + await scheduler.getNextUpdatePromise() + + spyOn(shell, 'openExternal') + let link = aboutElement.querySelector('.app-update-available-to-install .about-updates-release-notes') + link.click() + + let args = shell.openExternal.mostRecentCall.args + expect(shell.openExternal).toHaveBeenCalled() + expect(args[0]).toContain('/v1.2.3') + }) + + it('executes checkForUpdate() when the check for update button is clicked', () => { + let button = aboutElement.querySelector('.about-update-action-button') + button.click() + expect(atom.autoUpdater.checkForUpdate).toHaveBeenCalled() + }) + + it('executes restartAndInstallUpdate() when the restart and install button is clicked', async () => { + spyOn(atom.autoUpdater, 'restartAndInstallUpdate') + MockUpdater.finishDownloadingUpdate('42.0.0') + await scheduler.getNextUpdatePromise() + + let button = aboutElement.querySelector('.about-update-action-button') + button.click() + expect(atom.autoUpdater.restartAndInstallUpdate).toHaveBeenCalled() + }) + + it("starts in the same state as atom's AutoUpdateManager", async () => { + atom.autoUpdater.getState.andReturn('downloading') + updateManager.resetState() + + await scheduler.getNextUpdatePromise() + expect(aboutElement.querySelector('.app-checking-for-updates')).not.toBeVisible() + expect(aboutElement.querySelector('.app-downloading-update')).toBeVisible() + expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(true) + expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Check now') + }) + + describe('when core.automaticallyUpdate is toggled', () => { + beforeEach(async () => { + expect(atom.config.get('core.automaticallyUpdate')).toBe(true) + atom.autoUpdater.checkForUpdate.reset() + }) + + it('shows the auto update UI', async () => { + expect(aboutElement.querySelector('.about-auto-updates input').checked).toBe(true) + expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible() + expect(aboutElement.querySelector('.about-default-update-message').textContent).toBe('Atom will check for updates automatically') + + atom.config.set('core.automaticallyUpdate', false) + await scheduler.getNextUpdatePromise() + + expect(aboutElement.querySelector('.about-auto-updates input').checked).toBe(false) + expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible() + expect(aboutElement.querySelector('.about-default-update-message').textContent).toBe('Automatic updates are disabled please check manually') + }) + + it('updates config and the UI when the checkbox is used to toggle', async () => { + expect(aboutElement.querySelector('.about-auto-updates input').checked).toBe(true) + + aboutElement.querySelector('.about-auto-updates input').click() + await scheduler.getNextUpdatePromise() + + expect(atom.config.get('core.automaticallyUpdate')).toBe(false) + expect(aboutElement.querySelector('.about-auto-updates input').checked).toBe(false) + expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible() + expect(aboutElement.querySelector('.about-default-update-message').textContent).toBe('Automatic updates are disabled please check manually') + + aboutElement.querySelector('.about-auto-updates input').click() + await scheduler.getNextUpdatePromise() + + expect(atom.config.get('core.automaticallyUpdate')).toBe(true) + expect(aboutElement.querySelector('.about-auto-updates input').checked).toBe(true) + expect(aboutElement.querySelector('.about-default-update-message')).toBeVisible() + expect(aboutElement.querySelector('.about-default-update-message').textContent).toBe('Atom will check for updates automatically') + }) + + describe('checking for updates', function () { + afterEach(() => { + this.updateView = null + }) + + it('checks for update when the about page is shown', () => { + expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled() + + this.updateView = new UpdateView({ + updateManager: updateManager, + availableVersion: '9999.0.0', + viewUpdateReleaseNotes: () => {} + }) + + expect(atom.autoUpdater.checkForUpdate).toHaveBeenCalled() + }) + + it('does not check for update when the about page is shown and the update manager is not in the idle state', () => { + atom.autoUpdater.getState.andReturn('downloading') + updateManager.resetState() + expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled() + + this.updateView = new UpdateView({ + updateManager: updateManager, + availableVersion: '9999.0.0', + viewUpdateReleaseNotes: () => {} + }) + + expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled() + }) + + it('does not check for update when the about page is shown and auto updates are turned off', () => { + atom.config.set('core.automaticallyUpdate', false) + expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled() + + this.updateView = new UpdateView({ + updateManager: updateManager, + availableVersion: '9999.0.0', + viewUpdateReleaseNotes: () => {} + }) + + expect(atom.autoUpdater.checkForUpdate).not.toHaveBeenCalled() + }) + }) + }) + }) + }) + + describe('when the About page is not open and an update is downloaded', () => { + it('should display the new version when it is opened', async () => { + MockUpdater.finishDownloadingUpdate('42.0.0') + + jasmine.attachToDOM(workspaceElement) + await atom.workspace.open('atom://about') + aboutElement = workspaceElement.querySelector('.about') + updateManager = main.model.state.updateManager + scheduler = AboutView.getScheduler() + + expect(aboutElement.querySelector('.app-update-available-to-install')).toBeVisible() + expect(aboutElement.querySelector('.app-update-available-to-install .about-updates-version').textContent).toBe('42.0.0') + expect(aboutElement.querySelector('.about-update-action-button').disabled).toBe(false) + expect(aboutElement.querySelector('.about-update-action-button').textContent).toBe('Restart and install') + }) + }) +}) diff --git a/packages/about/styles/about.less b/packages/about/styles/about.less new file mode 100644 index 000000000..1877f47cf --- /dev/null +++ b/packages/about/styles/about.less @@ -0,0 +1,175 @@ +@import "ui-variables"; +@import "variables"; + +.about { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + -webkit-user-select: none; + cursor: default; + overflow: auto; + text-align: center; + font-size: 1.25em; + line-height: 1.4; + padding: 4em; + color: @text-color; + background-color: @base-background-color; + + button { + cursor: default; + } + + a:focus { + // Don't use Bootstrap default here + color: inherit; + } + + img, a { + -webkit-user-drag: none; + } + + .input-checkbox { + margin-top: -.2em; + } + + // used to group different elements + .group-start { + margin-top: 4em; + } + .group-item { + margin-top: 1.5em; + } +} + +.about-container { + width: 100%; + max-width: 500px; +} + +// Header -------------------------------- + +.about-atom-io:hover { + .about-logo { + color: @atom-green; + } +} + +.about-logo { + display: block; + width: 100%; + max-width: 280px; + margin: 0 auto 1em auto; + color: @text-color-highlight; + transition: color 0.2s; +} + +.about-version-container { + &:hover { + color: lighten(@text-color, 15%); + } + &:active { + color: lighten(@text-color, 30%); + } +} + +.about-version { + margin-right: .5em; + font-size: 1.25em; + vertical-align: middle; +} + +.about-more-version { + color: @text-color-subtle; + font-size: .9em; +} + +.about-header-release-notes { + vertical-align: middle; + margin-left: 1em; +} + + +// Updates -------------------------------- + +.about-updates { + width: 100%; + max-width: 500px; +} + +.about-updates-box { + display: flex; + align-items: center; + padding: @component-padding; + border: 1px solid @base-border-color; + border-radius: @component-border-radius * 2; + background-color: @background-color-highlight; +} + +.about-updates-status { + flex: 1; + margin-left: .5em; + text-align: left; +} + +.about-updates-item, +.about-default-update-message .about-updates-label { + display: block; +} + +.about-updates-label { + color: @text-color-subtle; + &.is-strong { + color: @text-color; + } +} + +.about-updates-version { + margin: 0 .4em; +} + +.about-updates-release-notes, +.about-updates-instructions { + margin: 0 1em 0 1.5em; +} + +.about-auto-updates { + margin-top: 1em; + input { + margin-right: .5em; + } +} + + +// Love -------------------------------- + +.about-love { + .icon::before { + // Make these octicons look good inlined with text + position: relative; + width: auto; + height: auto; + margin-right: 0; + font-size: 1.5em; + vertical-align: text-top; + } + + .icon-logo-github::before { + font-size: 3.6em; + height: .36em; + } +} + +.about-credits { + color: @text-color-subtle; +} + + +// the blue squirrel -------------------------------- + +.about-release-notes { + color: @background-color-info; + &:hover { + color: lighten(@background-color-info, 15%); + } +} diff --git a/packages/about/styles/variables.less b/packages/about/styles/variables.less new file mode 100644 index 000000000..fcb4ba3c8 --- /dev/null +++ b/packages/about/styles/variables.less @@ -0,0 +1 @@ +@atom-green: #40a977; diff --git a/packages/one-light-ui/.coffeelintignore b/packages/one-light-ui/.coffeelintignore new file mode 100644 index 000000000..1db51fed7 --- /dev/null +++ b/packages/one-light-ui/.coffeelintignore @@ -0,0 +1 @@ +spec/fixtures diff --git a/packages/one-light-ui/.gitignore b/packages/one-light-ui/.gitignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/packages/one-light-ui/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/one-light-ui/LICENSE.md b/packages/one-light-ui/LICENSE.md new file mode 100644 index 000000000..4d231b456 --- /dev/null +++ b/packages/one-light-ui/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (c) 2014 GitHub Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/one-light-ui/README.md b/packages/one-light-ui/README.md new file mode 100644 index 000000000..0c8bb0229 --- /dev/null +++ b/packages/one-light-ui/README.md @@ -0,0 +1,42 @@ +## One Light UI theme + +A light UI theme that adapts to most syntax themes. + +![One light UI](https://cloud.githubusercontent.com/assets/378023/26246819/0826f04e-3cd6-11e7-98eb-cd94bc48b090.png) + +> The font used in the screenshot is [Fira Mono](https://github.com/mozilla/Fira). + + +### Install + +This theme comes bundled with Atom and can be activated by going to the __Settings > Themes__ section and selecting "One Light" from the __UI Themes__ drop-down menu. + + +### Settings + +In the theme settings you can: + +- Change the __Font Size__ to scale the whole UI up or down. +- Choose between 3 __Tab Sizing__ modes. +- Hide the __dock buttons__. + +To make changes, go to `Settings > Themes > One Light UI > Settings` or the cog icon next to the theme picker. + + +### Customize + +It's also possible to resize only certain areas by adding the following to your `styles.less` (Use DevTools to find the right selectors): + +```css +.theme-one-light-ui { + .tab-bar { font-size: 18px; } + .tree-view { font-size: 14px; } + .status-bar { font-size: 12px; } +} +``` + + +### FAQ + +__Why do the colors change when I switch Syntax themes.__ +This UI theme uses the same background color as the chosen syntax theme. If that syntax theme has a dark background color, it only uses its hue, but otherwise stays light. This lets you use light-dark combos. diff --git a/packages/one-light-ui/coffeelint.json b/packages/one-light-ui/coffeelint.json new file mode 100644 index 000000000..a5dd715e3 --- /dev/null +++ b/packages/one-light-ui/coffeelint.json @@ -0,0 +1,37 @@ +{ + "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/packages/one-light-ui/index.less b/packages/one-light-ui/index.less new file mode 100644 index 000000000..09b35c279 --- /dev/null +++ b/packages/one-light-ui/index.less @@ -0,0 +1,35 @@ + +// Atom UI Theme: One + +@import "styles/ui-variables.less"; +@import "styles/ui-mixins.less"; +@import "octicon-mixins.less"; // https://github.com/atom/atom/blob/master/static/variables/octicon-mixins.less + +@import "styles/atom.less"; +@import "styles/badges.less"; +@import "styles/buttons.less"; +@import "styles/docks.less"; +@import "styles/editor.less"; +@import "styles/git.less"; +@import "styles/inputs.less"; +@import "styles/lists.less"; +@import "styles/messages.less"; +@import "styles/nav.less"; +@import "styles/notifications.less"; +@import "styles/modal.less"; +@import "styles/panels.less"; +@import "styles/panes.less"; +@import "styles/progress.less"; +@import "styles/tabs.less"; +@import "styles/text.less"; +@import "styles/title-bar.less"; +@import "styles/tooltips.less"; +@import "styles/tree-view.less"; +@import "styles/status-bar.less"; +@import "styles/key-binding.less"; +@import "styles/sites.less"; + +@import "styles/settings.less"; +@import "styles/packages.less"; +@import "styles/core.less"; +@import "styles/config.less"; diff --git a/packages/one-light-ui/lib/main.coffee b/packages/one-light-ui/lib/main.coffee new file mode 100644 index 000000000..815691a56 --- /dev/null +++ b/packages/one-light-ui/lib/main.coffee @@ -0,0 +1,86 @@ +root = document.documentElement +themeName = 'one-light-ui' + + +module.exports = + activate: (state) -> + atom.config.observe "#{themeName}.fontSize", (value) -> + setFontSize(value) + + atom.config.observe "#{themeName}.tabSizing", (value) -> + setTabSizing(value) + + atom.config.observe "#{themeName}.tabCloseButton", (value) -> + setTabCloseButton(value) + + atom.config.observe "#{themeName}.hideDockButtons", (value) -> + setHideDockButtons(value) + + atom.config.observe "#{themeName}.stickyHeaders", (value) -> + setStickyHeaders(value) + + # DEPRECATED: This can be removed at some point (added in Atom 1.17/1.18ish) + # It removes `layoutMode` + if atom.config.get("#{themeName}.layoutMode") + atom.config.unset("#{themeName}.layoutMode") + + deactivate: -> + unsetFontSize() + unsetTabSizing() + unsetTabCloseButton() + unsetHideDockButtons() + unsetStickyHeaders() + + +# Font Size ----------------------- + +setFontSize = (currentFontSize) -> + root.style.fontSize = "#{currentFontSize}px" + +unsetFontSize = -> + root.style.fontSize = '' + + +# Tab Sizing ----------------------- + +setTabSizing = (tabSizing) -> + root.setAttribute("theme-#{themeName}-tabsizing", tabSizing.toLowerCase()) + +unsetTabSizing = -> + root.removeAttribute("theme-#{themeName}-tabsizing") + + +# Tab Close Button ----------------------- + +setTabCloseButton = (tabCloseButton) -> + if tabCloseButton is 'Left' + root.setAttribute("theme-#{themeName}-tab-close-button", 'left') + else + unsetTabCloseButton() + +unsetTabCloseButton = -> + root.removeAttribute("theme-#{themeName}-tab-close-button") + + +# Dock Buttons ----------------------- + +setHideDockButtons = (hideDockButtons) -> + if hideDockButtons + root.setAttribute("theme-#{themeName}-dock-buttons", 'hidden') + else + unsetHideDockButtons() + +unsetHideDockButtons = -> + root.removeAttribute("theme-#{themeName}-dock-buttons") + + +# Sticky Headers ----------------------- + +setStickyHeaders = (stickyHeaders) -> + if stickyHeaders + root.setAttribute("theme-#{themeName}-sticky-headers", 'sticky') + else + unsetStickyHeaders() + +unsetStickyHeaders = -> + root.removeAttribute("theme-#{themeName}-sticky-headers") diff --git a/packages/one-light-ui/package.json b/packages/one-light-ui/package.json new file mode 100644 index 000000000..9d4c47be7 --- /dev/null +++ b/packages/one-light-ui/package.json @@ -0,0 +1,78 @@ +{ + "name": "one-light-ui", + "theme": "ui", + "version": "1.12.5", + "description": "Atom One light UI theme", + "keywords": [ + "light", + "adaptive", + "ui" + ], + "license": "MIT", + "repository": "https://github.com/atom/one-light-ui", + "main": "lib/main", + "engines": { + "atom": ">0.40.0" + }, + "devDependencies": { + "coffeelint": "^1.9.7" + }, + "configSchema": { + "fontSize": { + "title": "Font Size", + "description": "Change the font size for the UI.", + "type": "integer", + "default": 12, + "enum": [ + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20 + ], + "order": 1 + }, + "tabSizing": { + "title": "Tab Sizing", + "description": "In Even mode all tabs will be the same size. Great for quickly closing many tabs. In Maximum mode the tabs will expand to take up the full width. In Minimum mode the tabs will only take as little space as needed and also show longer file names.", + "type": "string", + "default": "Even", + "enum": [ + "Even", + "Maximum", + "Minimum" + ], + "order": 2 + }, + "tabCloseButton": { + "title": "Tab Close Button", + "description": "Choose the position of the close button shown in tabs.", + "type": "string", + "default": "Right", + "enum": [ + "Left", + "Right" + ], + "order": 3 + }, + "hideDockButtons": { + "title": "Hide dock toggle buttons", + "description": "Note: When hiding the toggle buttons, opening a dock needs to be done by using the keyboard or other alternatives.", + "type": "boolean", + "default": "false", + "order": 4 + }, + "stickyHeaders": { + "title": "Make tree-view project headers sticky", + "type": "boolean", + "default": "false", + "order": 5 + } + } +} diff --git a/packages/one-light-ui/spec/theme-spec.coffee b/packages/one-light-ui/spec/theme-spec.coffee new file mode 100644 index 000000000..909939f69 --- /dev/null +++ b/packages/one-light-ui/spec/theme-spec.coffee @@ -0,0 +1,36 @@ +themeName = 'one-light-ui' + +describe "#{themeName} theme", -> + beforeEach -> + waitsForPromise -> + atom.packages.activatePackage(themeName) + + it "allows the font size to be set via config", -> + expect(document.documentElement.style.fontSize).toBe '12px' + + atom.config.set("#{themeName}.fontSize", '10') + expect(document.documentElement.style.fontSize).toBe '10px' + + it "allows the tab sizing to be set via config", -> + atom.config.set("#{themeName}.tabSizing", 'Maximum') + expect(document.documentElement.getAttribute("theme-#{themeName}-tabsizing")).toBe 'maximum' + + it "allows the tab sizing to be set via config", -> + atom.config.set("#{themeName}.tabSizing", 'Minimum') + expect(document.documentElement.getAttribute("theme-#{themeName}-tabsizing")).toBe 'minimum' + + it "allows the tab close button to be shown on the left via config", -> + atom.config.set("#{themeName}.tabCloseButton", 'Left') + expect(document.documentElement.getAttribute("theme-#{themeName}-tab-close-button")).toBe 'left' + + it "allows the dock toggle buttons to be hidden via config", -> + atom.config.set("#{themeName}.hideDockButtons", true) + expect(document.documentElement.getAttribute("theme-#{themeName}-dock-buttons")).toBe 'hidden' + + it "allows the tree-view headers to be sticky via config", -> + atom.config.set("#{themeName}.stickyHeaders", true) + expect(document.documentElement.getAttribute("theme-#{themeName}-sticky-headers")).toBe 'sticky' + + it "allows the tree-view headers to not be sticky via config", -> + atom.config.set("#{themeName}.stickyHeaders", false) + expect(document.documentElement.getAttribute("theme-#{themeName}-sticky-headers")).toBe null diff --git a/packages/one-light-ui/styles/atom.less b/packages/one-light-ui/styles/atom.less new file mode 100644 index 000000000..911a7ac5a --- /dev/null +++ b/packages/one-light-ui/styles/atom.less @@ -0,0 +1,67 @@ +* { + box-sizing: border-box; +} + +html { + font-size: @font-size; +} + +atom-workspace { + background-color: @app-background-color; +} + + +// Scrollbars ------------------------------------ + +.scrollbars-visible-always { + ::-webkit-scrollbar { + width: 10px; + height: 10px; + } + + ::-webkit-scrollbar-track { + background: @scrollbar-background-color; + } + + ::-webkit-scrollbar-thumb { + border-radius: 5px; + border: 3px solid @scrollbar-background-color; + background: @scrollbar-color; + background-clip: content-box; + } + + ::-webkit-scrollbar-corner { + background: @scrollbar-background-color; + } + + ::-webkit-scrollbar-thumb:vertical:active { + border-radius: 0; + border-left-width: 0; + border-right-width: 0; + } + + ::-webkit-scrollbar-thumb:horizontal:active { + border-radius: 0; + border-top-width: 0; + border-bottom-width: 0; + } + + atom-text-editor { + ::-webkit-scrollbar-track { + background: @scrollbar-background-color-editor; + } + ::-webkit-scrollbar-corner { + background: @scrollbar-background-color-editor; + } + ::-webkit-scrollbar-thumb { + border-color: @scrollbar-background-color-editor; + background: @scrollbar-color-editor; + } + } +} + +// TODO: Move to a better place, not sure where it gets used +.caret { + border-top: 5px solid #fff; + margin-top: -1px; +} diff --git a/packages/one-light-ui/styles/badges.less b/packages/one-light-ui/styles/badges.less new file mode 100644 index 000000000..a1020805d --- /dev/null +++ b/packages/one-light-ui/styles/badges.less @@ -0,0 +1,14 @@ +.badge { + padding: @ui-padding/4 @ui-padding/2.5; + min-width: @ui-padding*1.25; + .text(highlight); + border-radius: @ui-size*2; + background-color: @badge-background-color; + + // Icon ---------------------- + &.icon { + font-size: @ui-size; + padding: @ui-padding-icon @ui-padding-icon*1.5; + } + +} diff --git a/packages/one-light-ui/styles/buttons.less b/packages/one-light-ui/styles/buttons.less new file mode 100644 index 000000000..8a1b3989a --- /dev/null +++ b/packages/one-light-ui/styles/buttons.less @@ -0,0 +1,186 @@ + +@btn-border: 1px solid @button-border-color; +@btn-padding: 0 @ui-size/1.25; + +// Mixins ----------------------- + +.btn-default (@color, @hover-color, @selected-color, @text-color) { + color: @text-color; + text-shadow: none; + border: @btn-border; + background-color: @color; + background-image: linear-gradient(lighten(@color, 2%), @color); + + &:hover { + color: @text-color-highlight; + background-image: linear-gradient(lighten(@hover-color, 2%), @hover-color); + } + &:active { + background: darken(@color, 4%); + box-shadow: none; + } + &.selected { + background: @selected-color; + } + &.selected:focus, + &.selected:hover { + background: lighten(@selected-color, 2%); + } + &:focus { + .focus(); // unfortunately :focus styles stay even after releasing mouse. + } +} + +.btn-variant (@color) { + @_text-color: contrast(@color, white, hsl(0,0%,20%), 33% ); + .btn-default( + @color, + lighten(@color, 3%), + saturate(darken(@color, 12%), 20%), + @text-color-highlight + ); + color: @_text-color; + + & when (@ui-lightness > 50%) { + border-color: transparent; // hide border on light backgrounds + } + + &:hover, + &:focus { + color: @_text-color; + } + &:focus { + border-color: transparent; + background-clip: padding-box; + box-shadow: inset 0 0 0 1px fade(@base-border-color, 50%), 0 0 0 1px @color; + } + + &.icon:before { + color: @_text-color; + } +} + + +// Buttons ----------------------- + +.btn { + height: initial; + padding: @btn-padding; + font-size: @ui-size; + line-height: @ui-line-height; +} + +.btn, +.btn.btn-default { + .btn-default(@button-background-color, @button-background-color-hover, @button-background-color-selected, @text-color); +} + +.btn.btn-primary { + .btn-variant(@accent-bg-color); +} +.btn.btn-info { + .btn-variant(@background-color-info); +} +.btn.btn-success { + .btn-variant(@background-color-success); +} +.btn.btn-warning { + .btn-variant(@background-color-warning); +} +.btn.btn-error { + .btn-variant(@background-color-error); +} + + +// Button Sizes ----------------------- + +.btn.btn-xs, +.btn-group-xs > .btn { + font-size: @ui-size*.8; + line-height: @ui-line-height; + padding: @btn-padding; +} +.btn.btn-sm, +.btn-group-sm > .btn { + font-size: @ui-size*.9; + line-height: @ui-line-height; + padding: @btn-padding; +} +.btn.btn-lg, +.btn-group-lg > .btn { + font-size: @ui-size * 1.5; + line-height: @ui-line-height; + padding: @btn-padding; +} + + +// Button Group ----------------------- + +.btn-group > .btn { + z-index: 0; + &:hover { + z-index: 0; + } + &.btn:focus { + z-index: 1; + .focus(); + } + + &:first-child { + border-left: @btn-border; + } + &:last-child, + &.selected:last-child { + border-right: @btn-border; + } + + // hide border on light backgrounds + & when (@ui-lightness > 50%) { + &.btn-primary:first-child, + &.btn-info:first-child, + &.btn-success:first-child, + &.btn-warning:first-child, + &.btn-error:first-child { + border-left-color: transparent; + } + + &.btn-primary:last-child, + &.btn-info:last-child, + &.btn-success:last-child, + &.btn-warning:last-child, + &.btn-error:last-child { + border-right-color: transparent; + } + } + + &.selected, + &.selected:first-child, + &.selected:last-child { + color: @button-text-color-selected; + border-color: @button-border-color-selected; + } + + & when (@ui-lightness > 50%) { + &.selected + .btn { + border-left-color: @button-border-color-selected; + } + &.selected + .selected { + border-left-color: mix(@button-border-color, @button-border-color-selected); + } + } + + &.selected:focus { + border-color: @button-background-color-selected; + box-shadow: inset 0 0 0 1px fade(@base-border-color, 50%), 0 0 0 1px @button-background-color-selected; + } +} + + +// Button Icons ----------------------- + +.btn.icon:before { + width: auto; + height: auto; + font-size: 1.333333em; + vertical-align: -.1em; +} diff --git a/packages/one-light-ui/styles/config.less b/packages/one-light-ui/styles/config.less new file mode 100644 index 000000000..a0970cc8c --- /dev/null +++ b/packages/one-light-ui/styles/config.less @@ -0,0 +1,156 @@ + +// Theme config +// This gets changed from the theme settings + +@theme-tabsizing: ~'theme-@{ui-theme-name}-tabsizing'; +@theme-dockButtons: ~'theme-@{ui-theme-name}-dock-buttons'; +@theme-stickyHeaders: ~'theme-@{ui-theme-name}-sticky-headers'; +@theme-closeButton: ~'theme-@{ui-theme-name}-tab-close-button'; + + +// Tabs ---------------------------------------------- + +@tab-min-width: 7em; // ~ icon + 6 characters + +// Even (default) + +.tab-bar { + .tab, + .tab.active { + flex: 1 1 0; + max-width: 22em; + min-width: @tab-min-width; + } + atom-dock & { + .tab, + .tab.active { + max-width: none; + } + } + + // TODO: Turn this into a config + // Truncates the beginning instead + // .title.title.title { + // direction: rtl; // change direction + // } +} + + +// Maximum (full width) + +[@{theme-tabsizing}="maximum"] .tab-bar { + .tab, + .tab.active { + max-width: none; + } +} + + +// Minimum (show long paths) + +[@{theme-tabsizing}="minimum"] .tab-bar { + .tab, + .tab.active { + flex: 0 0 auto; + min-width: 2.75em; + max-width: @tab-min-width * 3.3; + } + atom-dock { + .tab, + .tab.active { + max-width: @tab-min-width * 2; + } + } +} + + +// Tabs: close button position ------------------------------ + +[@{theme-closeButton}="left"] { + + .tab-bar .tab { + .close-icon { + right: auto; + left: @icon-padding-right; + } + } + +} + + +// Hide docks toggle buttons ------------------------------ + +[@{theme-dockButtons}="hidden"] { + + // Hide docks when not open + .atom-dock-inner:not(.atom-dock-open) { + display: none; + } + + // Hide toggle buttons + .atom-dock-toggle-button { + display: none; + } + +} + + +// Sticky Projects ------------------------------ + +[@{theme-stickyHeaders}="sticky"] { + + .tree-view { + .project-root-header { + position: sticky; + top: 0; + z-index: 3; + padding-left: 5px; + padding-right: 10px; + border-bottom: 1px solid @base-border-color; + background-color: @tree-view-background-color; + } + .project-root.project-root { + margin-left: -5px; + margin-right: -10px; + + // Disable selection + &::before { + display: none; + } + + // Add selection back + &.selected .project-root-header { + background-color: @background-color-selected; + } + } + &:focus .selected .project-root-header.project-root-header { + background: @button-background-color-selected; + } + + // Fix sticky header from covering auto-revealed files + .entry.file.selected { + padding-top: @ui-tab-height; + margin-top: -@ui-tab-height; + } + + // Fix sticky header from covering auto-revealed directories when using up/down keys + // for directories, scroll test moves to .header, see https://github.com/atom/tree-view/blob/d2857ad4d7eeb7dad5cf94b33257a8740211480e/lib/tree-view.coffee#L839 + .entry.directory.selected:not(.project-root) { + & > .header { + padding-top: @ui-tab-height; + margin-top: -@ui-tab-height; + } + &::before { + margin-top: @ui-tab-height; + } + } + + // Fix above directory is not being clickable + .entry.directory:not(.project-root) > .header { + z-index: 2; + } + .entry.directory.selected:not(.project-root) > .header { + z-index: 1; + } + } +} diff --git a/packages/one-light-ui/styles/core.less b/packages/one-light-ui/styles/core.less new file mode 100644 index 000000000..0f30626c0 --- /dev/null +++ b/packages/one-light-ui/styles/core.less @@ -0,0 +1,25 @@ +// Misc + +.preview-pane .results-view .path-match-number { + // show number also on selected item + color: inherit; + opacity: .6; +} + +.tool-panel.incompatible-packages { + // incompatible-packages isn't really a tool-panel and more a whole pane + .text(normal); + background-color: @level-2-color; +} + +// Styleguide ---------------------------------------------- + +.styleguide { + // Modal + atom-panel.modal:after { + position: absolute; // prevent overlay backdrop from leaking outside + left: -@ui-padding; + right: -@ui-padding; + bottom: -@ui-padding; + } +} diff --git a/packages/one-light-ui/styles/docks.less b/packages/one-light-ui/styles/docks.less new file mode 100644 index 000000000..c91681e21 --- /dev/null +++ b/packages/one-light-ui/styles/docks.less @@ -0,0 +1,43 @@ + +// Docks ------------------------------ + +// Make handles not take up any space when dock is open +.atom-dock-resize-handle { + position: absolute; + z-index: 11; // same as toggle buttons + + &.left { + top: 0; + right: 0; + bottom: 0; + } + &.right { + top: 0; + left: 0; + bottom: 0; + } + &.bottom { + top: 0; + left: 0; + right: 0; + } +} + +// Add borders +.atom-dock-inner.atom-dock-open.left { + border-right: 1px solid @base-border-color; +} +.atom-dock-inner.atom-dock-open.right { + border-left: 1px solid @base-border-color; +} + +// Make toggle buttons cover ^ border +.atom-dock-toggle-button.left { + margin-left: -2px; +} +.atom-dock-toggle-button.right { + margin-right: -2px; +} +.atom-dock-inner:not(.atom-dock-open) .atom-dock-toggle-button.bottom { + margin-bottom: -1px; +} diff --git a/packages/one-light-ui/styles/dropdowns.less b/packages/one-light-ui/styles/dropdowns.less new file mode 100644 index 000000000..d793523bb --- /dev/null +++ b/packages/one-light-ui/styles/dropdowns.less @@ -0,0 +1,15 @@ +.dropdown-menu { + background-color: @overlay-background-color; + border-radius: @component-border-radius; + border: 1px solid @base-border-color; + padding: 0; + + > li > a { + .text(normal); + } + + > li > a:hover { + .text(highlight); + background-color: @background-color-highlight; + } +} diff --git a/packages/one-light-ui/styles/editor.less b/packages/one-light-ui/styles/editor.less new file mode 100644 index 000000000..1a73d4dcc --- /dev/null +++ b/packages/one-light-ui/styles/editor.less @@ -0,0 +1,44 @@ + +// Editor in a panel + +// TODO: Find a better selector, maybe a new class like atom-text-editor[medium] +atom-panel-container atom-text-editor.is-focused { + .focus(); +} + + +// Mini +// Usually just single line inputs + +atom-text-editor[mini] { + overflow: auto; + font-size: @ui-input-size; + line-height: @ui-line-height; + max-height: @ui-line-height * 5; // rows + padding-left: @ui-padding/3; + border-radius: @component-border-radius; + color: @text-color-highlight; + border: 1px solid @input-border-color; + background-color: @input-background-color; + + .placeholder-text { + color: @text-color-subtle; + } + + .selection .region { + background-color: @input-selection-color; + } + + .cursor { + border-color: @accent-color; + border-width: 2px; + } + + &.is-focused { + .focus(); + background-color: @input-background-color-focus; + .selection .region { + background-color: @input-selection-color-focus; + } + } +} diff --git a/packages/one-light-ui/styles/git.less b/packages/one-light-ui/styles/git.less new file mode 100644 index 000000000..2b6f2f8a4 --- /dev/null +++ b/packages/one-light-ui/styles/git.less @@ -0,0 +1,6 @@ +.status { .text(normal); } +.status-added { .text(success); } // green +.status-ignored { .text(subtle); } // faded +.status-modified { .text(warning); } // orange +.status-removed { .text(error); } // red +.status-renamed { .text(info); } // blue diff --git a/packages/one-light-ui/styles/inputs.less b/packages/one-light-ui/styles/inputs.less new file mode 100644 index 000000000..fe7e5e294 --- /dev/null +++ b/packages/one-light-ui/styles/inputs.less @@ -0,0 +1,87 @@ + +// +// Checkbox +// ------------------------- + +.input-checkbox { + &:active { + background-color: @accent-color; + } + &:before, + &:after { + background-color: @accent-text-color; + } + &:checked { + background-color: @accent-color; + } + + &:indeterminate { + background-color: @accent-color; + } +} + + +// +// Radio +// ------------------------- + +.input-radio { + &:before { + background-color: @accent-text-color; + } + &:active { + background-color: @accent-color; + } + &:checked { + background-color: @accent-color; + } +} + + +// +// Range (Slider) +// ------------------------- + +.input-range { + &::-webkit-slider-thumb { + background-color: @accent-color; + } +} + + +// +// Toggle +// ------------------------- + +.input-toggle { + &:checked { + background-color: @accent-color; + } + &:before { + background-color: @accent-text-color; + } +} + + + +// States ------------------------- + +.input-text, +.input-search, +.input-number, +.input-textarea, +.input-select, +.input-color { + &:focus { + .focus(); + } +} + +.input-text, +.input-search, +.input-number, +.input-textarea { + &:invalid { + .invalid(); + } +} diff --git a/packages/one-light-ui/styles/key-binding.less b/packages/one-light-ui/styles/key-binding.less new file mode 100644 index 000000000..c4dff4133 --- /dev/null +++ b/packages/one-light-ui/styles/key-binding.less @@ -0,0 +1,12 @@ +.key-binding { + display: inline-block; + margin-left: @ui-padding-icon; + padding: 0 @ui-padding/4; + line-height: 2; + font-family: inherit; + font-size: max(1em, @ui-size*.85); + letter-spacing: @ui-size/10; + border-radius: @component-border-radius; + color: @accent-bg-text-color; + background-color: @accent-bg-color; +} diff --git a/packages/one-light-ui/styles/lists.less b/packages/one-light-ui/styles/lists.less new file mode 100644 index 000000000..ddae9f44a --- /dev/null +++ b/packages/one-light-ui/styles/lists.less @@ -0,0 +1,150 @@ +.list-group, +.list-tree { + li:not(.list-nested-item), + li.list-nested-item > .list-item { + .text(normal); + } + + .generate-list-item-text-color(@class) { + li:not(.list-nested-item).text-@{class}, + li.list-nested-item.text-@{class} > .list-item { + .text(@class); + } + } + .generate-list-item-text-color(subtle); + .generate-list-item-text-color(info); + .generate-list-item-text-color(success); + .generate-list-item-text-color(warning); + .generate-list-item-text-color(error); + .generate-list-item-text-color(selected); + + .generate-list-item-status-color(@color, @status) { + li:not(.list-nested-item).status-@{status}, + li.list-nested-item.status-@{status} > .list-item { + color: @color; + } + + li:not(.list-nested-item).selected.status-@{status}, + li.list-nested-item.selected.status-@{status} > .list-item { + color: @color; + } + + } + + .generate-list-item-status-color(@text-color-added, added); + .generate-list-item-status-color(@text-color-ignored, ignored); + .generate-list-item-status-color(@text-color-modified, modified); + .generate-list-item-status-color(@text-color-removed, removed); + .generate-list-item-status-color(@text-color-renamed, renamed); + + li:not(.list-nested-item).selected, + li.list-nested-item.selected > .list-item { + .text(selected); + } + + .no-icon { + padding-left: calc(@ui-padding-icon ~"+" @component-icon-size); + } +} + +.list-tree.has-collapsable-children .list-nested-item > .list-item::before { + text-align: center; +} + +.select-list ol.list-group, +&.select-list ol.list-group { + li.two-lines { + .secondary-line { + color: @text-color-subtle; + } + &.selected .secondary-line { + color: fade(@text-color-highlight, 50%); + text-shadow: none; + } + } + + // Reset icon to allow nesting + .icon { + display: initial; + height: initial; + } + + // We want to highlight the background of the list items because we dont + // know their size. + li.selected { + background-color: @background-color-selected; + &:before{ display: none; } + } + + &.mark-active { + @active-icon-size: 14px; + + // pad in front of the text where the icon would be We'll pad the non- + // active items with a 'fake' icon so other classes can pad the item + // without worrying about the icon padding. + li:before { + content: ''; + background-color: transparent; + position: static; + display: inline-block; + left: auto; right: auto; + height: @active-icon-size; + width: @active-icon-size; + font-size: @active-icon-size; + } + > li:not(.active):before { + margin-right: @ui-padding-icon; + } + li.active { + .octicon(check, @active-icon-size); + &:before { + margin-right: @ui-padding-icon; + color: @text-color-success; + } + } + } +} + +.select-list.popover-list { + @popover-list-padding: @ui-padding/4; + background-color: @overlay-background-color; + box-shadow: 0 2px 8px 1px rgba(0, 0, 0, 0.3); + padding: @popover-list-padding; + border-radius: @component-border-radius; + + atom-text-editor[mini] { + margin-bottom: @popover-list-padding; + } + + ol.list-group { + margin-top: @popover-list-padding; + } + + .list-group li { + padding-left: @popover-list-padding; + } +} + +.ui-sortable { + li { + line-height: 2.5; + } + + // For sortable lists in the settings view + li.ui-sortable-placeholder { + visibility: visible !important; + background-color: darken(@pane-item-background-color, 10%); + } +} + +li.ui-draggable-dragging, +li.ui-sortable-helper { + line-height: @ui-line-height; + height: @ui-line-height; + border: 0; + border-radius: 0; + list-style: none; + padding: 0 @ui-padding; + background: @background-color-highlight; + box-shadow: 0 0 1px @base-border-color; +} diff --git a/packages/one-light-ui/styles/messages.less b/packages/one-light-ui/styles/messages.less new file mode 100644 index 000000000..dda181c60 --- /dev/null +++ b/packages/one-light-ui/styles/messages.less @@ -0,0 +1,16 @@ +background-tips ul.background-message { + font-weight: 500; + font-size: 2em; + color: @text-color-faded; + + .message { + padding: 0 @component-padding * 10; + + .keystroke { + white-space: nowrap; + vertical-align: middle; + line-height: 1; + padding: .1em .4em; + } + } +} diff --git a/packages/one-light-ui/styles/modal.less b/packages/one-light-ui/styles/modal.less new file mode 100644 index 000000000..7bc0a42d1 --- /dev/null +++ b/packages/one-light-ui/styles/modal.less @@ -0,0 +1,125 @@ + +@modal-padding: @ui-padding/2 @ui-padding/1.5; +@modal-width: @ui-size * 50; + +atom-panel-container.modal { + position: absolute; + top: 0; left: 0; right: 0; +} + +atom-panel.modal { + position: relative; + width: 100%; + max-width: @modal-width; + margin: 0 auto; + left: initial; + color: @text-color; + background-color: transparent; + padding: @ui-padding/2; + + &.from-top { + top: @component-padding * 5; + } + + atom-text-editor[mini] { + margin-bottom: @ui-padding/2; + } + + .select-list ol.list-group, + &.select-list ol.list-group { + border: 1px solid @overlay-border-color; + background-color: lighten(@overlay-background-color, 2%); + + &:empty { + border: none; + margin-top: 0; + } + + li { + padding: @modal-padding; + line-height: @ui-line-height; + border-bottom: 1px solid @overlay-border-color; + + &:last-of-type { + border-bottom: none; + } + + .icon::before { + margin-left: 1px; + } + + .icon.status { + float: right; + margin-left: @ui-padding-icon; + &:before { + margin-left: 0; + margin-right: 0; + } + } + + &.selected { + .status.icon { + color: @text-color-selected; + } + } + } + + } + + .select-list .key-binding { + margin-top: -1px; + margin-left: @ui-padding/2; + margin-right: calc( -@ui-padding/3 ~"+" 1px); + } + + .select-list .primary-line { + display: block; + } + + & > * { + position: relative; // fixes stacking order + } + + .command-palette { + padding: 1px; // prevents the box-shadow of the input from being cut off + background-color: @overlay-background-color; + } + + + // Container + &:before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 0; + background-color: @overlay-background-color; + border-radius: @component-border-radius*2; + box-shadow: 0 6px 12px -2px hsla(0,0%,0%,.4); + } + + // Backdrop + // TODO: Add extra wrapper to translate individually or easier positioning + + &:after { + content: ""; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: -1; + background: @overlay-backdrop-color; + opacity: @overlay-backdrop-opacity; + backface-visibility: hidden; // fixes scrollbar on retina screens + -webkit-animation: overlay-fade .24s cubic-bezier(0.215, 0.61, 0.355, 1); + } + + @-webkit-keyframes overlay-fade { + 0% { opacity: 0; } + 100% { opacity: @overlay-backdrop-opacity; } + } + +} diff --git a/packages/one-light-ui/styles/nav.less b/packages/one-light-ui/styles/nav.less new file mode 100644 index 000000000..2d35bfdd9 --- /dev/null +++ b/packages/one-light-ui/styles/nav.less @@ -0,0 +1,25 @@ +.nav-tabs { + border-bottom: 1px solid @base-border-color; + li { + a, + &.active a { + border: none; + margin-right: 0px; + margin-bottom: 1px; + } + + a:hover, + &.active a, + &.active a:hover { + background-color: @background-color-highlight; + border: none; + color: @text-color-selected; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + } + + &.active a { + background-color: @tab-background-color-active; + } + } +} diff --git a/packages/one-light-ui/styles/notifications.less b/packages/one-light-ui/styles/notifications.less new file mode 100644 index 000000000..3f7ec520d --- /dev/null +++ b/packages/one-light-ui/styles/notifications.less @@ -0,0 +1,45 @@ + +atom-notifications { + font-size: @ui-size * 1.2; + + atom-notification { + width: 32em; + &.has-detail { + width: 32em; + } + + &:first-child.has-close .message { + padding-right: 9em; + } + &:only-child.has-close .message, + &.has-close .message { + padding-right: 2.5em; + } + .item { + padding: @ui-padding/2; + } + + .detail, + .description { + font-size: .85em; + } + + &.icon:before { + padding-top: .85em; + } + .close { + width: 2.5em; + height: 3em; + line-height: 3em; + font-size: inherit; + } + .close-all.btn { + top: .5em; + right: 2.5em; + } + .btn-copy-report { + line-height: 2em; + margin-left: .5em; + } + } +} diff --git a/packages/one-light-ui/styles/packages.less b/packages/one-light-ui/styles/packages.less new file mode 100644 index 000000000..73dd79c28 --- /dev/null +++ b/packages/one-light-ui/styles/packages.less @@ -0,0 +1,231 @@ +// Overrides packages + +// find-and-replace + project-find --------------------------- + +.find-and-replace, +.project-find { + padding: @ui-padding/4; + .input-block-item { + padding: @ui-padding/4; + } +} + +// find-and-replace +.find-and-replace { + .header, + .input-block { + min-width: @ui-size*22; + } + + .input-block-item { + flex: 1 1 @ui-size*22; + } + .input-block-item--flex { + flex: 100 1 @ui-size*22; + } + + .btn, + .btn-group-options .btn { + font-size: @ui-size*1.1; + padding: 0; + } + + .btn-group-options .btn, + .btn-group-options .btn.option-selection, + .btn-group-options .btn.option-whole-word { + padding: 0; + font-size: @ui-input-size; // keep same as text input + } + + .find-container atom-text-editor { + padding-right: @ui-size*5; // leave some room for the results count + } + .find-meta-container { + top: 0; + font-size: @ui-size; + line-height: @ui-size*2.5; + } +} + +// project-find +.project-find { + .header, + .input-block { + min-width: @ui-size*15; + } + + .input-block-item { + flex: 1 1 @ui-size*14; + } + .input-block-item--flex { + flex: 100 1 @ui-size*20; + } + + .btn { + font-size: @ui-size*1.1; + padding: 0; + } + .btn-group-options .btn { + padding: 0; + font-size: @ui-input-size; // keep same as text input + } +} + +// Colorize find-and-replace based on results +& when (@ui-hue >= 190) and (@ui-hue <= 340) { + .find-and-replace { + &.has-no-results .find-container atom-text-editor[mini].is-focused { + .invalid(); + .selection .region { + background-color: mix(@text-color-error, @input-background-color, 50%); + } + .cursor { + border-color: @text-color-error; + } + } + + &.has-results .find-container atom-text-editor[mini].is-focused { + .valid(); + .selection .region { + background-color: mix(@text-color-success, @input-background-color, 50%); + } + .cursor { + border-color: @text-color-success; + } + } + + &.has-results .find-container .result-counter { color: @text-color-success; } + &.has-no-results .find-container .result-counter { color: @text-color-error; } + } +} + + + + +// Timecop --------------------------- + +.timecop { + .timecop-panel { + padding: @component-padding/2; + background-color: @level-2-color; + } + + .tool-panel { + padding: @component-padding/2; + background-color: @level-2-color; + } + + .inset-panel { + border: 1px solid @base-border-color; + } + + .panel-heading { + .text(highlight); + border-color: @base-border-color; + background-color: @level-1-color; + } + + .list-item .inline-block { + line-height: 1.5; + } +} + + +// Command Palette + Fuzzy Finder --------------------------- + +.command-palette .list-group .character-match, +.fuzzy-finder .list-group .character-match { + color: @accent-only-text-color; +} + + +// Deprecation Cop --------------------------- + +.deprecation-cop { + .deprecation-overview { + background-color: @level-2-color; + border-bottom: 1px solid @base-border-color; + } +} + + +// Tool Bar --------------------------- + +.tool-bar { + // Make it look the same as other panels + background-color: @level-3-color; + border: none; + + // just a single border + more spacing + &.tool-bar-horizontal .tool-bar-spacer { + border-left: 0 none; + margin-left: .5em; + margin-right: .5em; + } + &.tool-bar-vertical .tool-bar-spacer { + border-bottom: 0 none; + margin-top: .5em; + margin-bottom: .5em; + } + + // only show button styles on hover + button.tool-bar-btn { + background-color: @level-3-color; + background-image: none; + border-color: @level-3-color; + } +} + + + +// GitHub package --------------------------------------------------- + +.github { + + // Fix focus styles + // Since it's not possible to add a padding to + // a pseudo element is used to add the border when focused. + &-CommitView-editor atom-text-editor.is-focused { + box-shadow: none; + &:before { + content: ""; + position: absolute; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + border: 2px solid; + border-color: inherit; + border-radius: @component-border-radius; + } + } + + // Add focus styles since :focus doesn't work + &-CommitView-coAuthorEditor { + &.is-focused { + .focus(); + } + &.is-open { + border-top-left-radius: 0; + border-top-right-radius: 0; + } + + + .Select-option { + &.is-focused { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + color: @accent-text-color; + background-color: @accent-color; + } + } + .Select-menu-outer { + left: -2px; + right: -2px; + bottom: 100%; + border: 2px solid @accent-color; + background-color: @overlay-background-color; + } + } + +} diff --git a/packages/one-light-ui/styles/panels.less b/packages/one-light-ui/styles/panels.less new file mode 100644 index 000000000..0d8b10850 --- /dev/null +++ b/packages/one-light-ui/styles/panels.less @@ -0,0 +1,64 @@ + +// Panels + +atom-panel { + .text(normal); + position: relative; + border-bottom: 1px solid @base-border-color; + + &.top { + border-right: 1px solid @base-border-color; + } + &.left { + border-right: 1px solid @base-border-color; + } + &.right { + border-left: 1px solid @base-border-color; + } + &.bottom { + border-right: 1px solid @base-border-color; + } + &.footer:last-child { + border-bottom: none; + } + &.tool-panel:empty { + border: none; + } +} + +.panel { + &.bordered { + border: 1px solid @base-border-color; + border-radius: @component-border-radius; + } +} + +.inset-panel { + position: relative; + background-color: @inset-panel-background-color; + border-radius: @component-border-radius; + &.bordered { + border: 1px solid @base-border-color; + border-radius: @component-border-radius; + } + & .panel-heading { + border-color: @inset-panel-border-color; + } +} + +.panel-heading { + .text(normal); + border-bottom: 1px solid @panel-heading-border-color; + background-color: @panel-heading-background-color; + + .btn { + padding-left: 8px; + padding-right: 8px; + .btn-default( + lighten(@button-background-color, 10%), + lighten(@button-background-color-hover, 10%), + lighten(@button-background-color-selected, 10%), + lighten(@text-color, 10%) + ); + } +} diff --git a/packages/one-light-ui/styles/panes.less b/packages/one-light-ui/styles/panes.less new file mode 100644 index 000000000..1842937ee --- /dev/null +++ b/packages/one-light-ui/styles/panes.less @@ -0,0 +1,22 @@ + +atom-pane-container { + + atom-pane { + position: relative; + border-right: 1px solid @base-border-color; + border-bottom: 1px solid @base-border-color; + + .item-views { + // prevent atom-text-editor from leaking ouside might improve performance + overflow: hidden; + } + } + +} + +// Hide right-most border +atom-pane:only-child, +atom-pane-axis.pane-row > atom-pane:last-child, +atom-pane-axis.pane-column:last-child > atom-pane { + border-right: none; +} diff --git a/packages/one-light-ui/styles/progress.less b/packages/one-light-ui/styles/progress.less new file mode 100644 index 000000000..0c070df60 --- /dev/null +++ b/packages/one-light-ui/styles/progress.less @@ -0,0 +1,94 @@ + +// Spinner ---------------------- + +@spinner-duration: 1.2s; + +.loading-spinner(@size) { + position: relative; + display: block; + width: 1em; + height: 1em; + font-size: @size; + background: radial-gradient(@accent-color .1em, transparent .11em); + + &::before, + &::after { + content: ""; + position: absolute; + z-index: 10; // prevent sibling elements from getting their own layers + top: 0; + left: 0; + border-radius: 1em; + width: inherit; + height: inherit; + border-radius: 1em; + border: 2px solid; + -webkit-animation: spinner-animation @spinner-duration infinite; + -webkit-animation-fill-mode: backwards; + } + &::before { + border-color: @accent-color transparent transparent transparent; + } + &::after { + border-color: transparent lighten(@accent-color, 15%) transparent transparent; + -webkit-animation-delay: @spinner-duration/2; + } + + &.inline-block { + display: inline-block; + } +} + +@-webkit-keyframes spinner-animation { + 0% { transform: rotateZ( 0deg); -webkit-animation-timing-function: cubic-bezier(0, 0, .8, .2); } + 50% { transform: rotateZ(180deg); -webkit-animation-timing-function: cubic-bezier(.2, .8, 1, 1); } + 100% { transform: rotateZ(360deg); } +} + +// Spinner sizes +.loading-spinner-tiny { .loading-spinner(16px); &::before, &::after { border-width: 1px; } } +.loading-spinner-small { .loading-spinner(32px); } +.loading-spinner-medium { .loading-spinner(48px); } +.loading-spinner-large { .loading-spinner(64px); } + + + + +// Progress Bar ---------------------- + +@progress-height: 8px; +@progress-buffer-color: fade(@progress-background-color, 20%); + +progress { + -webkit-appearance: none; + height: @progress-height; + border-radius: @component-border-radius; + background-color: @input-background-color; + box-shadow: inset 0 0 0 1px @input-border-color; + + &::-webkit-progress-bar { + background-color: transparent; + } + + &::-webkit-progress-value { + border-radius: @component-border-radius; + background-color: @progress-background-color; + } + + // Is buffering (when no value is set) + &:indeterminate { + background-image: + linear-gradient(-45deg, transparent 33%, @progress-buffer-color 33%, + @progress-buffer-color 66%, transparent 66%); + background-size: 25px @progress-height, 100% 100%, 100% 100%; + + // Plays animation for 1min (12runs) at normal speed, + // then slows down frame-rate for 9mins (108runs) to limit CPU usage + -webkit-animation: progress-buffering 5s linear 12, + progress-buffering 5s 60s steps(10) 108; + } +} + +@-webkit-keyframes progress-buffering { + 100% { background-position: -100px 0px; } +} diff --git a/packages/one-light-ui/styles/settings.less b/packages/one-light-ui/styles/settings.less new file mode 100644 index 000000000..a3a2642ef --- /dev/null +++ b/packages/one-light-ui/styles/settings.less @@ -0,0 +1,140 @@ + +// Settings + +// Modular Scale (1.125): http://www.modularscale.com/?1&em&1.125&web&table +@ms-6: @ui-size * 2.027; +@ms-5: @ui-size * 1.802; +@ms-4: @ui-size * 1.602; +@ms-3: @ui-size * 1.424; +@ms-2: @ui-size * 1.266; +@ms-1: @ui-size * 1.125; +@ms-0: @ui-size * 1; +@ms_1: @ui-size * 0.889; +@ms_2: @ui-size * 0.790; + + + +.settings-view { + + // Menu ------------------------------ + + .config-menu { + position: relative; + min-width: @ui-size * 15; + max-width: @ui-size * 20; + border-width: 0 1px 0 0; + border-image: linear-gradient(@level-2-color 10px, @base-border-color 200px) 0 1 0 0 stretch; + background: @level-2-color; + + .btn { + white-space: initial; + font-size: @ms_1; + line-height: 1; + padding: @ui-padding/3 @ui-padding/2; + &::before { + vertical-align: middle; + } + } + + + } + .nav { + & > li > a { + padding: @ui-padding/2 @ui-padding; + line-height: @ui-line-height; + } + } + + + // Sections ------------------------------ + + & > .panels { + background-color: @level-2-color; + } + + .section-container { + max-width: @ui-size*60; + } + .sub-section { + margin: @ui-padding*3 0; + } + + .section, + .section:first-child, + .section:last-child { + padding: @ui-padding*3; + } + + .themes-panel .control-group { + margin-top: @ui-padding*2; + } + + + // Titles ------------------------------ + + .section .section-heading { + margin-bottom: @ui-padding/1.5; + } + + .sub-section-heading.icon:before, + .section-heading.icon:before { + margin-right: @ui-padding-icon; + } + + + + // Cards ------------------------------ + + .package-card { + padding: @ui-padding; + .meta-controls .status-indicator { + width: @ui-padding/4; + &:before { + content: "\00a0"; // fixes 0 height + } + } + } + + + // Components ------------------------------ + + .icon::before { + color: @text-color-subtle; + } + + .editor-container { + margin: @ui-padding 0; + } + + .form-control { + font-size: @ui-size*1.25; + height: @ui-line-height; + padding-top: 0; + padding-bottom: 0; + } + + .update-all-button { + font-size: .75em; + } + + .install-button { + .btn-variant(@accent-bg-color); + } + + input[type="checkbox"] { + background-color: @background-color-selected; + &:active, + &:checked { + background-color: @accent-color; + } + &:before, + &:after { + background-color: @accent-text-color; + } + } + + .search-container .btn { + font-size: @ui-input-size; + } + +} diff --git a/packages/one-light-ui/styles/sites.less b/packages/one-light-ui/styles/sites.less new file mode 100644 index 000000000..4a02affed --- /dev/null +++ b/packages/one-light-ui/styles/sites.less @@ -0,0 +1,13 @@ +// Site Colors + +.ui-site(@num, @color) { + .ui-site-@{num} { + background-color: @color; + } +} + +.ui-site(1, @ui-site-color-1); +.ui-site(2, @ui-site-color-2); +.ui-site(3, @ui-site-color-3); +.ui-site(4, @ui-site-color-4); +.ui-site(5, @ui-site-color-5); diff --git a/packages/one-light-ui/styles/status-bar.less b/packages/one-light-ui/styles/status-bar.less new file mode 100644 index 000000000..1a171f501 --- /dev/null +++ b/packages/one-light-ui/styles/status-bar.less @@ -0,0 +1,97 @@ + +@status-bar-height: @ui-tab-height; // same as tabs +@status-bar-padding: @ui-padding; + +.status-bar { + font-size: @ui-size; + height: @status-bar-height; + line-height: @status-bar-height; + background-color: @level-3-color; + + .flexbox-repaint-hack { + padding: 0; // override default + } + + // underlines should only be used for external links + a:hover, + a:focus { + text-decoration: none; + cursor: default; + } + + .inline-block { + margin: 0; // override default + padding: 0 @status-bar-padding/2; + vertical-align: top; + + &:hover { + text-decoration: none; + background-color: @level-3-color-hover; + } + &:active { + background-color: @level-3-color-active; + } + + // reset on child inline-block + .inline-block { + margin: 0; + padding: 0; + } + } + + .status-bar-right { + .inline-block { + margin-left: 0; // override default + } + } + .icon { + vertical-align: middle; + } + .icon::before { + font-size: 1.33333em; // should be 16px with a default of 12px + width: auto; // use natural width + line-height: 1; + height: 1em; // same as line-height + margin-right: .25em; + top: auto; + } +} + + +// Package overrides ------------------------------- + +.status-bar.status-bar { + + // Read-only -> Remove hover effect + .is-read-only, // <- use this class in packages + status-bar-launch-mode, + busy-signal { + &:hover, + &:active, + .inline-block:hover, + .inline-block:active { + background-color: transparent; + } + } + + // Remove underline + .package-updates-status-view, + .github-ChangedFilesCount { + &:hover, + &:focus { + text-decoration: none; + cursor: default; + } + } + + // Remove margin for icon without text + status-bar-launch-mode::before, // Launch mode + .about-release-notes::before, // New release squirrel + .PortalStatusBarIndicator .icon::before, // Teletype + .icon.is-icon-only::before { + margin-right: 0; + } + .github-PushPull-label.is-push:empty { // GitHub package when nothing to push + margin-right: -.25em; + } +} diff --git a/packages/one-light-ui/styles/tabs.less b/packages/one-light-ui/styles/tabs.less new file mode 100644 index 000000000..be3c0990e --- /dev/null +++ b/packages/one-light-ui/styles/tabs.less @@ -0,0 +1,250 @@ + +// Tabs + +@tab-border: 1px solid @tab-border-color; +@title-padding: .66em; +@icon-padding-top: .5em; // 2.5 (total) - 1.5 (text) / 2 +@icon-padding-right: .5em; + +.tab-bar { + position: relative; + height: @ui-tab-height; + box-shadow: inset 0 -1px 0 @tab-border-color; + background: @tab-bar-background-color; + overflow-x: auto; + overflow-y: hidden; + border-radius: 0; + + &::-webkit-scrollbar { + display: none; + } + + &:empty { + display: none; + } + + + // Tab ---------------------- + + .tab { + position: relative; + top: 0; + padding: 0; + margin: 0; + height: inherit; + font-size: inherit; + line-height: @ui-tab-height; + color: @tab-text-color; + background-color: @tab-background-color; + box-shadow: inherit; + border-left: @tab-border; + &.active { + color: @tab-text-color-active; + background-color: @tab-background-color-active; + box-shadow: none; + } + &:first-of-type { + border-left-color: transparent; + } + &:last-of-type { + // use box-shadow to not take up any space + box-shadow: inset 0 -1px 0 @tab-border-color, 1px 0 0 @base-border-color; + } + &.active:last-of-type { + box-shadow: 1px 0 0 @base-border-color; + } + + + // Title ---------------------- + + .title { + text-align: center; + margin: 0 @title-padding; + } + + // VCS coloring ---------------------- + &:not(.active) .status-added { color: @tab-inactive-status-added; } + &:not(.active) .status-modified { color: @tab-inactive-status-modified; } + + + // Icons ---------------------- + + .title.title:before { + margin-right: .3em; + width: auto; + height: auto; + line-height: 1; + font-size: 1.125em; + vertical-align: -.0625em; // Adjust center for the 0.1em font-size increase + } + + // Close icon ---------------------- + + .close-icon { + top: @icon-padding-top; + right: @icon-padding-right; + z-index: 2; + font-size: 1em; + width: 1.5em; + height: 1.5em; + line-height: 1.5; + text-align: center; + border-radius: @component-border-radius; + background-color: inherit; + overflow: hidden; + transform: scale(0); + transition: transform .08s; + &:hover { + color: @accent-text-color; + background-color: @accent-color; + } + &:active { + background-color: fade(@accent-color, 50%); + } + &::before { + z-index: 1; + font-size: 1.1em; + vertical-align: -.05em; // Adjust center for the 0.1em font-size increase + width: auto; + height: auto; + pointer-events: none; + } + } + &:hover .close-icon { + transform: scale(1); + transition-duration: .16s; + } + } + + // Modified icon ---------------------- + + .tab.modified { + &:hover .close-icon { + color: @accent-color; + &:hover { + color: @accent-bg-text-color; + } + } + &:not(:hover) .close-icon { + top: @icon-padding-top; + right: @icon-padding-right; + width: 1.5em; + height: 1.5em; + line-height: 1.5; + color: @accent-color; + border-radius: @component-border-radius; + border: none; + transform: scale(1); + &::before { + content: "\f052"; + display: inline-block; + } + } + } + + + // Tabs in the docks ---------------------- + + atom-dock & { + .tab.active { + background-color: @tool-panel-background-color; + } + } + + + // Dragging ---------------------- + + .tab.is-dragging { + opacity: .5; + + .close-icon, + &:before { + visibility: hidden; + } + } + + .placeholder { + position: relative; + pointer-events: none; + + // bar + &:before { + z-index: 1; + margin: 0; + width: 2px; + height: @ui-tab-height; + background-color: @accent-color; + } + + // arrow + &:after { + z-index: 0; + top: @ui-tab-height/2; + margin: -4px 0 0 -3px; + border-radius: 0; + border: 4px solid @accent-color; + transform: rotate(45deg); + background: transparent; + } + + &:last-child { + &:before { + margin-left: -2px; + } + &:after { + transform: none; + margin-left: -10px; + border-color: transparent @accent-color transparent transparent; + } + } + } + + + // Overrides ---------------------- + + // keep tabs same size when active + .tab, + .tab.active { + padding-right: 0; + .title { + padding: 0; + } + } +} + + +// Active pane marker -------------- + +atom-pane-axis > atom-pane.active, +atom-pane-container > atom-pane.pane { + .tab.active:before { + content: ""; + position: absolute; + pointer-events: none; + z-index: 2; + top: 0; + left: -1px; // cover left border + bottom: 0; + width: 2px; + background: @accent-color; + } +} + +// hide marker in docks +atom-dock .tab-bar .tab::before { + display: none; +} + + +// Custom tabs -------------- + +.tab-bar .tab.active { + &[data-type$="Editor"], + &[data-type$="AboutView"], + &[data-type$="TimecopView"], + &[data-type$="StyleguideView"], + &[data-type="MarkdownPreviewView"] { + color: @tab-text-color-editor; + background-color: @tab-background-color-editor; // Match syntax background color + } +} diff --git a/packages/one-light-ui/styles/text.less b/packages/one-light-ui/styles/text.less new file mode 100644 index 000000000..399ff06d1 --- /dev/null +++ b/packages/one-light-ui/styles/text.less @@ -0,0 +1,84 @@ +h1, +h2, +h3 { + line-height: 1em; + margin-bottom: 15px +} +h1 { font-size: 2em; } +h2 { font-size: 1.5em; } +h3 { font-size: 1.2em; } + +p { + line-height: 1.6; + margin-bottom: 15px; +} + +label { + font-weight: normal; +} + +pre { + box-shadow: none; + color: @text-color; + background: @inset-panel-background-color; + border-radius: @component-border-radius; + border: none; + margin: 0; +} + +code { + .text(highlight); + background: @background-color-highlight; + border-radius: @component-border-radius; +} + +.selected { .text(highlight); } + +.text-smaller { font-size: 0.9em; } + +.text-subtle { .text(subtle); } +.text-highlight { .text(highlight); } + +.text-error { .text(error); } +.text-info { + .text(info); + &:hover { color: @text-color-info; } +} +.text-warning { + .text(warning); + &:hover { color: @text-color-warning; } +} +.text-success { + .text(success); + &:hover { color: @text-color-success; } +} + +.highlight-mixin { + padding: 1px 4px; + border-radius: 2px; +} + +.highlight { + .highlight-mixin(); + font-weight: 700; + color: @text-color-highlight; + background-color: @background-color-highlight; +} + +.highlight-color(@name, @background-color) { + .highlight-@{name} { + .highlight-mixin(); + font-weight: 500; + color: white; + text-shadow: 0 1px 0px hsla(0,0%,0%,.2); + background-color: @background-color; + } +} +.highlight-color( info, @background-color-info); +.highlight-color(warning, @background-color-warning); +.highlight-color( error, @background-color-error); +.highlight-color(success, @background-color-success); + +.results-view .path-details.list-item { + color: darken(@text-color-highlight, 18%); +} diff --git a/packages/one-light-ui/styles/title-bar.less b/packages/one-light-ui/styles/title-bar.less new file mode 100644 index 000000000..7e1b945a4 --- /dev/null +++ b/packages/one-light-ui/styles/title-bar.less @@ -0,0 +1,4 @@ +.title-bar { + height: 22px; // remove 1px since there is no border + border-bottom: none; +} diff --git a/packages/one-light-ui/styles/tooltips.less b/packages/one-light-ui/styles/tooltips.less new file mode 100644 index 000000000..f034f0e9b --- /dev/null +++ b/packages/one-light-ui/styles/tooltips.less @@ -0,0 +1,53 @@ +.tooltip { + white-space: nowrap; + font-size: @ui-size*1.15; + + &.in { + opacity: 1; + transition: opacity .12s ease-out; + } + + .tooltip-inner { + line-height: 1; + padding: @ui-padding*.5 @ui-padding*.65; + border-radius: @component-border-radius; + background-color: @tooltip-background-color; + color: @tooltip-text-color; + white-space: nowrap; + max-width: none; + } + + .keystroke { + font-size: max(1em, @ui-size*.85); + padding: .1em .4em; + margin: 0 @ui-padding*-.35 0 @ui-padding*.25; + border-radius: max(2px, @component-border-radius / 2); + color: @tooltip-text-key-color; + background: @tooltip-background-key-color; + } + + &.top .tooltip-arrow { + border-top-color: @tooltip-background-color; + } + &.top-left .tooltip-arrow { + border-top-color: @tooltip-background-color; + } + &.top-right .tooltip-arrow { + border-top-color: @tooltip-background-color; + } + &.right .tooltip-arrow { + border-right-color: @tooltip-background-color; + } + &.left .tooltip-arrow { + border-left-color: @tooltip-background-color; + } + &.bottom .tooltip-arrow { + border-bottom-color: @tooltip-background-color; + } + &.bottom-left .tooltip-arrow { + border-bottom-color: @tooltip-background-color; + } + &.bottom-right .tooltip-arrow { + border-bottom-color: @tooltip-background-color; + } +} diff --git a/packages/one-light-ui/styles/tree-view.less b/packages/one-light-ui/styles/tree-view.less new file mode 100644 index 000000000..9063d7dd9 --- /dev/null +++ b/packages/one-light-ui/styles/tree-view.less @@ -0,0 +1,85 @@ +@tree-view-height: @ui-line-height; + +.tree-view { + font-size: @ui-size; + background: @tree-view-background-color; + + .project-root.project-root { + &:before { + height: @ui-tab-height; + background-clip: padding-box; + } + & > .header .name { + line-height: @ui-tab-height; + } + } + + // Selected state + .selected:before { + background: @background-color-selected; + } + + // Focus + selected state + &:focus { + .selected.list-item > .name, // files + .selected.list-nested-item > .list-item > .name, // folders + .selected.list-nested-item > .header:before { // arrow icon + color: contrast(@button-background-color-selected); + } + .selected:before { + background: @button-background-color-selected; + } + } +} + +.theme-one-dark-ui .tree-view .project-root.project-root::before { + border-top: 1px solid transparent; + background-clip: padding-box; +} + +.tree-view-resizer { + .tree-view-resize-handle { + width: 8px; + } +} + +// Variable height, based on ems +.list-group li:not(.list-nested-item), +.list-tree li:not(.list-nested-item), +.list-group li.list-nested-item > .list-item, +.list-tree li.list-nested-item > .list-item { + line-height: @tree-view-height; +} + +.list-group .selected::before, +.list-tree .selected::before { + height: @tree-view-height; +} + +// icon +.list-group .icon, +.list-tree .icon { + display: inline-block; + height: inherit; + &::before { + top: initial; + line-height: inherit; + height: inherit; + vertical-align: top; + } +} + +// Arrow icon +.list-group, +.list-tree { + .header.header.header.header::before { + top: initial; + line-height: inherit; + height: inherit; + vertical-align: top; + font-size: inherit; + } +} +.tree-view .project-root-header.project-root-header.project-root-header.project-root-header::before { + line-height: @ui-tab-height; +} diff --git a/packages/one-light-ui/styles/ui-mixins.less b/packages/one-light-ui/styles/ui-mixins.less new file mode 100644 index 000000000..e50a63aff --- /dev/null +++ b/packages/one-light-ui/styles/ui-mixins.less @@ -0,0 +1,49 @@ +// Pattern matching; ish is cray. +// http://lesscss.org/#-pattern-matching-and-guard-expressions + +.text(normal) { + font-weight: normal; + color: @text-color; +} +.text(subtle) { + font-weight: normal; + color: @text-color-subtle; +} +.text(highlight) { + font-weight: normal; + color: @text-color-highlight; +} +.text(selected) { + .text(highlight) +} + +.text(info) { + color: @text-color-info; +} +.text(success) { + color: @text-color-success; +} +.text(warning) { + color: @text-color-warning; +} +.text(error) { + color: @text-color-error; +} + +.focus() { + outline: none; + border-color: @accent-color; + box-shadow: 0 0 0 1px @accent-color; +} + +.valid() { + border-color: @text-color-success; + box-shadow: 0 0 0 1px @text-color-success; + background-color: mix(@text-color-success, @input-background-color, 10%); +} + +.invalid() { + border-color: @text-color-error; + box-shadow: 0 0 0 1px @text-color-error; + background-color: mix(@text-color-error, @input-background-color, 10%); +} diff --git a/packages/one-light-ui/styles/ui-variables-custom.less b/packages/one-light-ui/styles/ui-variables-custom.less new file mode 100644 index 000000000..c43f5aabd --- /dev/null +++ b/packages/one-light-ui/styles/ui-variables-custom.less @@ -0,0 +1,132 @@ + +// ONE light UI variables +// ---------------------------------------------- + +@import "syntax-variables"; + +.ui-syntax-color() { @syntax-background-color: hsl(220,1%,98%); } .ui-syntax-color(); // fallback color +@ui-syntax-color: @syntax-background-color; + +// Color guards ----------------- +@ui-s-h: hue(@ui-syntax-color); +.ui-hue() when (@ui-s-h = 0) { @ui-hue: 220; } // Use blue hue when no saturation +.ui-hue() when (@ui-s-h > 0) { @ui-hue: @ui-s-h; } +.ui-hue(); + +@ui-saturation: min( saturation(@ui-syntax-color), 24%); // max saturation +@ui-lightness: max( lightness(@ui-syntax-color), 92%); // min lightness + +// Main colors ----------------- +@ui-fg: hsl(@ui-hue, @ui-saturation, @ui-lightness - 72%); +@ui-bg: hsl(@ui-hue, @ui-saturation, @ui-lightness); // normalized @syntax-background-color +@ui-border: darken(@level-3-color, 6%); + + + + +// Custom variables +// These variables are only used in this theme +// ---------------------------------------------- + +@ui-theme-name: one-light-ui; + +// Text (Custom) ----------------- +@text-color-faded: fade(@text-color, 30%); + +@text-color-added: @text-color-success; // green +@text-color-ignored: @text-color-subtle; // faded +@text-color-modified: @text-color-warning; // orange +@text-color-removed: @text-color-error; // red +@text-color-renamed: @text-color-info; // blue + + +// Background (Custom) ----------------- +@level-1-color: lighten(@base-background-color, 4%); +@level-2-color: @base-background-color; +@level-3-color: darken(@base-background-color, 6%); + +@level-3-color-hover: darken(@level-3-color, 6%); +@level-3-color-active: darken(@level-3-color, 3%); + + +// Accent (Custom) ----------------- +@accent-luma: luma( hsl(@ui-hue, 50%, 50%) ); // get lightness of current hue + +// used for marker, inputs (smaller things) +@accent-color: mix( hsv( @ui-hue, 60%, 60%), hsl( @ui-hue, 100%, 68%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors) +@accent-text-color: contrast(@accent-color, hsl(@ui-hue,100%,16%), #fff, 40% ); + +// used for button, tooltip (larger things) +@accent-bg-color: mix( hsv( @ui-hue, 40%, 72%), hsl( @ui-hue, 100%, 66%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors) +@accent-bg-text-color: contrast(@accent-bg-color, hsl(@ui-hue,100%,10%), #fff, 40% ); + +// used for text only +@accent-only-text-color: mix( hsv( @ui-hue, 70%, 50%), hsl( @ui-hue, 100%, 60%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors) + + +// Components (Custom) ----------------- +@badge-background-color: @background-color-selected; + +@button-text-color-selected: @accent-bg-text-color; +@button-border-color-selected: @accent-color; + +@checkbox-background-color: fade(@accent-bg-color, 33%); + +@input-background-color-focus: hsl(@ui-hue, 100%, 96%); +@input-selection-color: mix( hsv( @ui-hue, 33%, 95%), hsl( @ui-hue, 100%, 98%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors) +@input-selection-color-focus: mix( hsv( @ui-hue, 44%, 90%), hsl( @ui-hue, 100%, 94%), @accent-luma * 2 ); // mix hsv + hsl (favor hsl for dark, hsv for light colors) + +@overlay-backdrop-color: hsl(@ui-hue, @ui-saturation*0.4, @ui-lightness*0.8); +@overlay-backdrop-opacity: .66; + +@progress-background-color: @accent-color; + +@scrollbar-color: darken(@level-3-color, 14%); +@scrollbar-background-color: @level-3-color; // replaced `transparent` with a solid color to test https://github.com/atom/one-light-ui/issues/4 +@scrollbar-color-editor: contrast(@ui-syntax-color, darken(@ui-syntax-color, 14%), lighten(@ui-syntax-color, 9%) ); +@scrollbar-background-color-editor: @ui-syntax-color; + +@tab-text-color: @text-color-subtle; +@tab-text-color-active: @text-color-highlight; +@tab-text-color-editor: contrast(@ui-syntax-color, lighten(@ui-syntax-color, 70%), @text-color-highlight ); +@tab-background-color-editor: @ui-syntax-color; +@tab-inactive-status-added: fade(@text-color-success, 77%); +@tab-inactive-status-modified: fade(@text-color-warning, 77%); + +@tooltip-background-color: @accent-bg-color; +@tooltip-text-color: @accent-bg-text-color; +@tooltip-text-key-color: @tooltip-background-color; +@tooltip-background-key-color: @tooltip-text-color; + + +// Sizes (Custom) ----------------- + +@ui-size: 1em; +@ui-input-size: @ui-size*1.15; +@ui-padding: @ui-size*1.5; +@ui-padding-pane: @ui-size*.5; +@ui-padding-icon: @ui-padding/3.3; +@ui-line-height: @ui-size*2; +@ui-tab-height: @ui-size*2.5; + + + + + +// Packages variables +// These variables are used to override packages +// ---------------------------------------------- + +@settings-list-background-color: darken(@level-2-color, 3%); +@theme-config-box-shadow: inset 0 1px 2px hsla(0, 0%, 0%, .2), 0 1px 0 hsla(0, 0%, 100%, .3); +@theme-config-box-shadow-selected: inset 0 1px 3px hsla(0, 0%, 0%, .2); +@theme-config-border-selected: hsla(0, 0%, 0%, .5); + + +// Debug +// Output variables to the top of the UI +// ------------------------------------- + +// html:before { +// content: "@{variable}"; +// } diff --git a/packages/one-light-ui/styles/ui-variables.less b/packages/one-light-ui/styles/ui-variables.less new file mode 100644 index 000000000..5749b6393 --- /dev/null +++ b/packages/one-light-ui/styles/ui-variables.less @@ -0,0 +1,97 @@ + +@import "ui-variables-custom.less"; // import colors and custom variables + +// ONE light UI variables +// ---------------------------------------------- + +// Official variables +// These variables must be defined in every theme +// Source: https://github.com/atom/atom/blob/master/static/variables/ui-variables.less +// ---------------------------------------------- + + +// Text ----------------- +@text-color: @ui-fg; +@text-color-subtle: lighten(@text-color, 30%); +@text-color-highlight: darken(@text-color, 12%); +@text-color-selected: darken(@text-color-highlight, 12%); + +@text-color-info: hsl(208, 100%, 54%); +@text-color-success: hsl(132, 60%, 44%); +@text-color-warning: hsl( 37, 90%, 44%); +@text-color-error: hsl( 0, 90%, 56%); + + +// Background ----------------- +@background-color-info: hsl(208, 100%, 56%); +@background-color-success: hsl(132, 52%, 48%); +@background-color-warning: hsl( 40, 60%, 48%); +@background-color-error: hsl( 5, 72%, 56%); + +@background-color-highlight: darken(@level-3-color, 2%); +@background-color-selected: darken(@level-3-color, 6%); + +@app-background-color: @level-3-color; + + +// Base ----------------- +@base-background-color: @ui-bg; +@base-border-color: @ui-border; + + +// Components ----------------- +@pane-item-background-color: @base-background-color; +@pane-item-border-color: @base-border-color; + +@input-background-color: @level-1-color; +@input-border-color: @base-border-color; + +@tool-panel-background-color: @level-3-color; +@tool-panel-border-color: @base-border-color; + +@inset-panel-background-color: lighten(@level-2-color, 4%); +@inset-panel-border-color: fadeout(@base-border-color, 15%); + +@panel-heading-background-color: @level-2-color; +@panel-heading-border-color: @base-border-color; + +@overlay-background-color: mix(@level-2-color, @level-3-color); +@overlay-border-color: @base-border-color; + +@button-background-color: @level-1-color; +@button-background-color-hover: darken(@button-background-color, 4%); +@button-background-color-selected: @accent-bg-color; +@button-border-color: @base-border-color; + +@tab-bar-background-color: @level-3-color; +@tab-bar-border-color: @base-border-color; +@tab-background-color: @level-3-color; +@tab-background-color-active: @level-2-color; +@tab-border-color: @base-border-color; + +@tree-view-background-color: @level-3-color; +@tree-view-border-color: @base-border-color; + +@ui-site-color-1: hsl(208, 100%, 56%); // blue +@ui-site-color-2: hsl(132, 48%, 48%); // green +@ui-site-color-3: hsl( 40, 60%, 52%); // orange +@ui-site-color-4: #D831B0; // pink +@ui-site-color-5: #EBDD5B; // yellow + + +// Sizes ----------------- +@font-size: 12px; +@input-font-size: 14px; +@disclosure-arrow-size: 12px; + +@component-padding: 10px; +@component-icon-padding: 5px; +@component-icon-size: 16px; // needs to stay 16px to look sharpest +@component-line-height: 25px; +@component-border-radius: 3px; + +@tab-height: 30px; + + +// Font ----------------- +@font-family: system-ui; diff --git a/resources/app-icons/nightly/atom.icns b/resources/app-icons/nightly/atom.icns new file mode 100644 index 000000000..e49166fe2 Binary files /dev/null and b/resources/app-icons/nightly/atom.icns differ diff --git a/resources/app-icons/nightly/atom.ico b/resources/app-icons/nightly/atom.ico new file mode 100644 index 000000000..158a02f0f Binary files /dev/null and b/resources/app-icons/nightly/atom.ico differ diff --git a/resources/app-icons/nightly/png/1024.png b/resources/app-icons/nightly/png/1024.png new file mode 100644 index 000000000..b81ab2a2e Binary files /dev/null and b/resources/app-icons/nightly/png/1024.png differ diff --git a/resources/app-icons/nightly/png/128.png b/resources/app-icons/nightly/png/128.png new file mode 100644 index 000000000..374043550 Binary files /dev/null and b/resources/app-icons/nightly/png/128.png differ diff --git a/resources/app-icons/nightly/png/16.png b/resources/app-icons/nightly/png/16.png new file mode 100644 index 000000000..582356487 Binary files /dev/null and b/resources/app-icons/nightly/png/16.png differ diff --git a/resources/app-icons/nightly/png/24.png b/resources/app-icons/nightly/png/24.png new file mode 100644 index 000000000..32f6999cf Binary files /dev/null and b/resources/app-icons/nightly/png/24.png differ diff --git a/resources/app-icons/nightly/png/256.png b/resources/app-icons/nightly/png/256.png new file mode 100644 index 000000000..89618fec4 Binary files /dev/null and b/resources/app-icons/nightly/png/256.png differ diff --git a/resources/app-icons/nightly/png/32.png b/resources/app-icons/nightly/png/32.png new file mode 100644 index 000000000..a83e9a4de Binary files /dev/null and b/resources/app-icons/nightly/png/32.png differ diff --git a/resources/app-icons/nightly/png/48.png b/resources/app-icons/nightly/png/48.png new file mode 100644 index 000000000..3637315e4 Binary files /dev/null and b/resources/app-icons/nightly/png/48.png differ diff --git a/resources/app-icons/nightly/png/512.png b/resources/app-icons/nightly/png/512.png new file mode 100644 index 000000000..7afe3fbe3 Binary files /dev/null and b/resources/app-icons/nightly/png/512.png differ diff --git a/resources/app-icons/nightly/png/64.png b/resources/app-icons/nightly/png/64.png new file mode 100644 index 000000000..2403b7b01 Binary files /dev/null and b/resources/app-icons/nightly/png/64.png differ diff --git a/resources/linux/debian/control.in b/resources/linux/debian/control.in index 39a49c178..c376be354 100644 --- a/resources/linux/debian/control.in +++ b/resources/linux/debian/control.in @@ -1,6 +1,6 @@ Package: <%= appFileName %> Version: <%= version %> -Depends: git, gconf2, gconf-service, libgtk2.0-0, libudev0 | libudev1, libgcrypt11 | libgcrypt20, libnotify4, libxtst6, libnss3 (>= 2:3.22), python, gvfs-bin, xdg-utils, libcap2, libx11-xcb1, libxss1, libasound2 (>= 1.0.16), libxkbfile1 +Depends: git, gconf2, gconf-service, libgtk-3-0 (>= 3.9.10), libudev0 | libudev1, libgcrypt11 | libgcrypt20, libnotify4, libxtst6, libnss3 (>= 2:3.22), python, gvfs-bin, xdg-utils, libcap2, libx11-xcb1, libxss1, libasound2 (>= 1.0.16), libxkbfile1 Recommends: lsb-release Suggests: libsecret-1-0, gir1.2-gnomekeyring-1.0 Section: devel diff --git a/resources/win/atom.sh b/resources/win/atom.sh old mode 100644 new mode 100755 index 324b2956a..42840a938 --- a/resources/win/atom.sh +++ b/resources/win/atom.sh @@ -7,6 +7,10 @@ else pushd "$(dirname "$0")" > /dev/null if [[ $(uname -r) == *-Microsoft ]]; then # We are in Windows Subsystem for Linux, map /mnt/drive + root="/mnt/" + # If different root mount point defined in /etc/wsl.conf, use that instead + eval $(grep "^root" /etc/wsl.conf | sed -e "s/ //g") + root="$(echo $root | sed 's|/|\\/|g')" ATOMCMD="$(echo $PWD | sed 's/\/mnt\/\([a-z]*\)\(.*\)/\1:\2/')/atom.cmd" ATOMCMD="${ATOMCMD////\\}" else diff --git a/script/bootstrap b/script/bootstrap index 430d7959a..156ddf286 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -2,8 +2,9 @@ 'use strict' -const childProcess = require('child_process') +const path = require('path') const CONFIG = require('./config') +const childProcess = require('child_process') const cleanDependencies = require('./lib/clean-dependencies') const deleteMsbuildFromPath = require('./lib/delete-msbuild-from-path') const dependenciesFingerprint = require('./lib/dependencies-fingerprint') @@ -17,6 +18,14 @@ process.on('unhandledRejection', function (e) { process.exit(1) }) +// We can't use yargs until installScriptDependencies() is executed, so... +let ci = process.argv.indexOf('--ci') !== -1 + +if (!ci && process.env.CI === 'true' && process.argv.indexOf('--no-ci') === -1) { + console.log('Automatically enabling --ci because CI is set in the environment') + ci = true +} + verifyMachineRequirements() if (dependenciesFingerprint.isOutdated()) { @@ -25,13 +34,13 @@ if (dependenciesFingerprint.isOutdated()) { if (process.platform === 'win32') deleteMsbuildFromPath() -installScriptDependencies() -installApm() +installScriptDependencies(ci) +installApm(ci) childProcess.execFileSync( CONFIG.getApmBinPath(), ['--version'], {stdio: 'inherit'} ) -runApmInstall(CONFIG.repositoryRootPath) +runApmInstall(CONFIG.repositoryRootPath, ci) dependenciesFingerprint.write() diff --git a/script/build b/script/build index 55cebe96d..7b84a4eff 100755 --- a/script/build +++ b/script/build @@ -21,14 +21,15 @@ const argv = yargs .describe('create-debian-package', 'Create .deb package (Linux only)') .describe('create-rpm-package', 'Create .rpm package (Linux only)') .describe('compress-artifacts', 'Compress Atom binaries (and symbols on macOS)') + .describe('generate-api-docs', 'Only build the API documentation') .describe('install', 'Install Atom') .string('install') + .describe('ci', 'Install dependencies quickly (package-lock.json files must be up to date)') .wrap(yargs.terminalWidth()) .argv const checkChromedriverVersion = require('./lib/check-chromedriver-version') const cleanOutputDirectory = require('./lib/clean-output-directory') -const cleanPackageLock = require('./lib/clean-package-lock') const codeSignOnMac = require('./lib/code-sign-on-mac') const codeSignOnWindows = require('./lib/code-sign-on-windows') const compressArtifacts = require('./lib/compress-artifacts') @@ -59,7 +60,6 @@ const CONFIG = require('./config') let binariesPromise = Promise.resolve() if (!argv.existingBinaries) { - cleanPackageLock() checkChromedriverVersion() cleanOutputDirectory() copyAssets() @@ -72,65 +72,74 @@ if (!argv.existingBinaries) { prebuildLessCache() generateMetadata() generateAPIDocs() - binariesPromise = dumpSymbols() + if (!argv.generateApiDocs) { + binariesPromise = dumpSymbols() + } } -binariesPromise - .then(packageApplication) - .then(packagedAppPath => generateStartupSnapshot(packagedAppPath).then(() => packagedAppPath)) - .then(packagedAppPath => { - switch (process.platform) { - case 'darwin': { - if (argv.codeSign) { - codeSignOnMac(packagedAppPath) - } else { - console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray) - } - } - case 'win32': { - if (argv.codeSign) { - const executablesToSign = [ path.join(packagedAppPath, 'Atom.exe') ] - if (argv.createWindowsInstaller) { - executablesToSign.push(path.join(__dirname, 'node_modules', 'electron-winstaller', 'vendor', 'Update.exe')) +if (!argv.generateApiDocs) { + binariesPromise + .then(packageApplication) + .then(packagedAppPath => generateStartupSnapshot(packagedAppPath).then(() => packagedAppPath)) + .then(packagedAppPath => { + switch (process.platform) { + case 'darwin': { + if (argv.codeSign) { + codeSignOnMac(packagedAppPath) + } else { + console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray) } - codeSignOnWindows(executablesToSign) - } else { - console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray) + break } - if (argv.createWindowsInstaller) { - return createWindowsInstaller(packagedAppPath) - .then(() => argv.codeSign && codeSignOnWindows([ path.join(CONFIG.buildOutputPath, 'AtomSetup.exe') ])) - .then(() => packagedAppPath) - } else { - console.log('Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer.'.gray) + case 'win32': { + if (argv.codeSign) { + const executablesToSign = [ path.join(packagedAppPath, 'Atom.exe') ] + if (argv.createWindowsInstaller) { + executablesToSign.push(path.join(__dirname, 'node_modules', 'electron-winstaller', 'vendor', 'Update.exe')) + } + codeSignOnWindows(executablesToSign) + } else { + console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray) + } + if (argv.createWindowsInstaller) { + return createWindowsInstaller(packagedAppPath) + .then((installerPath) => { + argv.codeSign && codeSignOnWindows([installerPath]) + return packagedAppPath + }) + } else { + console.log('Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer.'.gray) + } + break + } + case 'linux': { + if (argv.createDebianPackage) { + createDebianPackage(packagedAppPath) + } else { + console.log('Skipping creating debian package. Specify the --create-debian-package option to create it.'.gray) + } + + if (argv.createRpmPackage) { + createRpmPackage(packagedAppPath) + } else { + console.log('Skipping creating rpm package. Specify the --create-rpm-package option to create it.'.gray) + } + break } } - case 'linux': { - if (argv.createDebianPackage) { - createDebianPackage(packagedAppPath) - } else { - console.log('Skipping creating debian package. Specify the --create-debian-package option to create it.'.gray) - } - if (argv.createRpmPackage) { - createRpmPackage(packagedAppPath) - } else { - console.log('Skipping creating rpm package. Specify the --create-rpm-package option to create it.'.gray) - } + return Promise.resolve(packagedAppPath) + }).then(packagedAppPath => { + if (argv.compressArtifacts) { + compressArtifacts(packagedAppPath) + } else { + console.log('Skipping artifacts compression. Specify the --compress-artifacts option to compress Atom binaries (and symbols on macOS)'.gray) } - } - return Promise.resolve(packagedAppPath) - }).then(packagedAppPath => { - if (argv.compressArtifacts) { - compressArtifacts(packagedAppPath) - } else { - console.log('Skipping artifacts compression. Specify the --compress-artifacts option to compress Atom binaries (and symbols on macOS)'.gray) - } - - if (argv.install != null) { - installApplication(packagedAppPath, argv.install) - } else { - console.log('Skipping installation. Specify the --install option to install Atom'.gray) - } - }) + if (argv.install != null) { + installApplication(packagedAppPath, argv.install) + } else { + console.log('Skipping installation. Specify the --install option to install Atom'.gray) + } + }) +} diff --git a/script/config.js b/script/config.js index 1dd670702..16b7cadb5 100644 --- a/script/config.js +++ b/script/config.js @@ -5,6 +5,7 @@ const fs = require('fs') const path = require('path') +const spawnSync = require('./lib/spawn-sync') const repositoryRootPath = path.resolve(__dirname, '..') const apmRootPath = path.join(repositoryRootPath, 'apm') @@ -19,12 +20,16 @@ const atomHomeDirPath = process.env.ATOM_HOME || path.join(homeDirPath, '.atom') const appMetadata = require(path.join(repositoryRootPath, 'package.json')) const apmMetadata = require(path.join(apmRootPath, 'package.json')) -const channel = getChannel() +const computedAppVersion = computeAppVersion(process.env.ATOM_RELEASE_VERSION || appMetadata.version) +const channel = getChannel(computedAppVersion) +const appName = getAppName(channel) module.exports = { appMetadata, apmMetadata, channel, + appName, + computedAppVersion, repositoryRootPath, apmRootPath, scriptRootPath, @@ -40,14 +45,30 @@ module.exports = { snapshotAuxiliaryData: {} } -function getChannel () { - if (appMetadata.version.match(/dev/)) { - return 'dev' - } else if (appMetadata.version.match(/beta/)) { - return 'beta' - } else { - return 'stable' +function getChannel (version) { + const match = version.match(/\d+\.\d+\.\d+(-([a-z]+)(\d+|-\w{4,})?)?$/) + if (!match) { + throw new Error(`Found incorrectly formatted Atom version ${version}`) + } else if (match[2]) { + return match[2] } + + return 'stable' +} + +function getAppName (channel) { + return channel === 'stable' + ? 'Atom' + : `Atom ${process.env.ATOM_CHANNEL_DISPLAY_NAME || channel.charAt(0).toUpperCase() + channel.slice(1)}` +} + +function computeAppVersion (version) { + if (version.match(/-dev$/)) { + const result = spawnSync('git', ['rev-parse', '--short', 'HEAD'], {cwd: repositoryRootPath}) + const commitHash = result.stdout.toString().trim() + version += '-' + commitHash + } + return version } function getApmBinPath () { @@ -55,8 +76,8 @@ function getApmBinPath () { return path.join(apmRootPath, 'node_modules', 'atom-package-manager', 'bin', apmBinName) } -function getNpmBinPath () { +function getNpmBinPath (external = false) { const npmBinName = process.platform === 'win32' ? 'npm.cmd' : 'npm' const localNpmBinPath = path.resolve(repositoryRootPath, 'script', 'node_modules', '.bin', npmBinName) - return fs.existsSync(localNpmBinPath) ? localNpmBinPath : npmBinName + return !external && fs.existsSync(localNpmBinPath) ? localNpmBinPath : npmBinName } diff --git a/script/lib/clean-caches.js b/script/lib/clean-caches.js index 1df3aa9c2..3861908bb 100644 --- a/script/lib/clean-caches.js +++ b/script/lib/clean-caches.js @@ -14,6 +14,7 @@ module.exports = function () { path.join(CONFIG.atomHomeDirPath, '.apm'), path.join(CONFIG.atomHomeDirPath, '.npm'), path.join(CONFIG.atomHomeDirPath, 'compile-cache'), + path.join(CONFIG.atomHomeDirPath, 'snapshot-cache'), path.join(CONFIG.atomHomeDirPath, 'atom-shell'), path.join(CONFIG.atomHomeDirPath, 'electron'), path.join(os.tmpdir(), 'atom-build'), diff --git a/script/lib/clean-package-lock.js b/script/lib/clean-package-lock.js deleted file mode 100644 index 01376c9c5..000000000 --- a/script/lib/clean-package-lock.js +++ /dev/null @@ -1,18 +0,0 @@ -// This module exports a function that deletes all `package-lock.json` files that do -// not exist under a `node_modules` directory. - -'use strict' - -const CONFIG = require('../config') -const fs = require('fs-extra') -const glob = require('glob') -const path = require('path') - -module.exports = function () { - console.log('Deleting problematic package-lock.json files') - let paths = glob.sync(path.join(CONFIG.repositoryRootPath, '**', 'package-lock.json'), {ignore: path.join('**', 'node_modules', '**')}) - - for (let path of paths) { - fs.unlinkSync(path) - } -} diff --git a/script/lib/code-sign-on-mac.js b/script/lib/code-sign-on-mac.js index a97438835..1d8243808 100644 --- a/script/lib/code-sign-on-mac.js +++ b/script/lib/code-sign-on-mac.js @@ -16,6 +16,36 @@ module.exports = function (packagedAppPath) { downloadFileFromGithub(process.env.ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL, certPath) } try { + console.log(`Ensuring keychain ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN} exists`) + try { + spawnSync('security', [ + 'show-keychain-info', + process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN + ], {stdio: 'inherit'}) + } catch (err) { + console.log(`Creating keychain ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN}`) + // The keychain doesn't exist, try to create it + spawnSync('security', [ + 'create-keychain', + '-p', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD, + process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN + ], {stdio: 'inherit'}) + + // List the keychain to "activate" it. Somehow this seems + // to be needed otherwise the signing operation fails + spawnSync('security', [ + 'list-keychains', + '-s', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN + ], {stdio: 'inherit'}) + + // Make sure it doesn't time out before we use it + spawnSync('security', [ + 'set-keychain-settings', + '-t', '3600', + '-u', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN + ], {stdio: 'inherit'}) + } + console.log(`Unlocking keychain ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN}`) const unlockArgs = ['unlock-keychain'] // For signing on local workstations, password could be entered interactively diff --git a/script/lib/compress-artifacts.js b/script/lib/compress-artifacts.js index 7d9125925..74f31313f 100644 --- a/script/lib/compress-artifacts.js +++ b/script/lib/compress-artifacts.js @@ -3,6 +3,7 @@ const fs = require('fs-extra') const path = require('path') const spawnSync = require('./spawn-sync') +const { path7za } = require('7zip-bin') const CONFIG = require('../config') @@ -19,7 +20,7 @@ module.exports = function (packagedAppPath) { function getArchiveName () { switch (process.platform) { case 'darwin': return 'atom-mac.zip' - case 'win32': return 'atom-windows.zip' + case 'win32': return `atom-${process.arch === 'x64' ? 'x64-' : ''}windows.zip` default: return `atom-${getLinuxArchiveArch()}.tar.gz` } } @@ -44,7 +45,7 @@ function compress (inputDirPath, outputArchivePath) { compressCommand = 'zip' compressArguments = ['-r', '--symlinks'] } else if (process.platform === 'win32') { - compressCommand = '7z.exe' + compressCommand = path7za compressArguments = ['a', '-r'] } else { compressCommand = 'tar' diff --git a/script/lib/copy-assets.js b/script/lib/copy-assets.js index d53515f4a..27b5f086c 100644 --- a/script/lib/copy-assets.js +++ b/script/lib/copy-assets.js @@ -23,7 +23,7 @@ module.exports = function () { ] srcPaths = srcPaths.concat(glob.sync(path.join(CONFIG.repositoryRootPath, 'spec', '*.*'), {ignore: path.join('**', '*-spec.*')})) for (let srcPath of srcPaths) { - fs.copySync(srcPath, computeDestinationPath(srcPath), {filter: includePathInPackagedApp}) + fs.copySync(srcPath, computeDestinationPath(srcPath), {filter: includePathInPackagedApp, dereference: true}) } fs.copySync( diff --git a/script/lib/create-debian-package.js b/script/lib/create-debian-package.js index 120463f7b..1aa179b70 100644 --- a/script/lib/create-debian-package.js +++ b/script/lib/create-debian-package.js @@ -10,9 +10,8 @@ const CONFIG = require('../config') module.exports = function (packagedAppPath) { console.log(`Creating Debian package for "${packagedAppPath}"`) - const atomExecutableName = CONFIG.channel === 'beta' ? 'atom-beta' : 'atom' - const apmExecutableName = CONFIG.channel === 'beta' ? 'apm-beta' : 'apm' - const appName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom' + const atomExecutableName = CONFIG.channel === 'stable' ? 'atom' : `atom-${CONFIG.channel}` + const apmExecutableName = CONFIG.channel === 'stable' ? 'apm' : `apm-${CONFIG.channel}` const appDescription = CONFIG.appMetadata.description const appVersion = CONFIG.appMetadata.version let arch @@ -88,7 +87,7 @@ module.exports = function (packagedAppPath) { console.log(`Writing desktop entry file into "${debianPackageApplicationsDirPath}"`) const desktopEntryTemplate = fs.readFileSync(path.join(CONFIG.repositoryRootPath, 'resources', 'linux', 'atom.desktop.in')) const desktopEntryContents = template(desktopEntryTemplate)({ - appName: appName, + appName: CONFIG.appName, appFileName: atomExecutableName, description: appDescription, installDir: '/usr', diff --git a/script/lib/create-rpm-package.js b/script/lib/create-rpm-package.js index f76385aab..cdef23300 100644 --- a/script/lib/create-rpm-package.js +++ b/script/lib/create-rpm-package.js @@ -10,9 +10,9 @@ const CONFIG = require('../config') module.exports = function (packagedAppPath) { console.log(`Creating rpm package for "${packagedAppPath}"`) - const atomExecutableName = CONFIG.channel === 'beta' ? 'atom-beta' : 'atom' - const apmExecutableName = CONFIG.channel === 'beta' ? 'apm-beta' : 'apm' - const appName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom' + const atomExecutableName = CONFIG.channel === 'stable' ? 'atom' : `atom-${CONFIG.channel}` + const apmExecutableName = CONFIG.channel === 'stable' ? 'apm' : `apm-${CONFIG.channel}` + const appName = CONFIG.appName const appDescription = CONFIG.appMetadata.description // RPM versions can't have dashes or tildes in them. // (Ref.: https://twiki.cern.ch/twiki/bin/view/Main/RPMAndDebVersioning) diff --git a/script/lib/create-windows-installer.js b/script/lib/create-windows-installer.js index ddc46d484..f5e387e7f 100644 --- a/script/lib/create-windows-installer.js +++ b/script/lib/create-windows-installer.js @@ -1,7 +1,7 @@ 'use strict' const electronInstaller = require('electron-winstaller') -const fs = require('fs-extra') +const fs = require('fs') const glob = require('glob') const path = require('path') @@ -16,17 +16,32 @@ module.exports = (packagedAppPath) => { loadingGif: path.join(CONFIG.repositoryRootPath, 'resources', 'win', 'loading.gif'), outputDirectory: CONFIG.buildOutputPath, noMsi: true, - remoteReleases: `https://atom.io/api/updates${archSuffix}?version=${CONFIG.appMetadata.version}`, + noDelta: CONFIG.channel === 'nightly', // Delta packages are broken for nightly versions past nightly9 due to Squirrel/NuGet limitations + remoteReleases: `https://atom.io/api/updates${archSuffix}?version=${CONFIG.computedAppVersion}`, + setupExe: `AtomSetup${process.arch === 'x64' ? '-x64' : ''}.exe`, setupIcon: path.join(CONFIG.repositoryRootPath, 'resources', 'app-icons', CONFIG.channel, 'atom.ico') } const cleanUp = () => { - for (let nupkgPath of glob.sync(`${CONFIG.buildOutputPath}/*.nupkg`)) { - if (!nupkgPath.includes(CONFIG.appMetadata.version)) { + const releasesPath = `${CONFIG.buildOutputPath}/RELEASES` + if (process.arch === 'x64' && fs.existsSync(releasesPath)) { + fs.renameSync(releasesPath, `${releasesPath}-x64`) + } + + for (let nupkgPath of glob.sync(`${CONFIG.buildOutputPath}/atom-*.nupkg`)) { + if (!nupkgPath.includes(CONFIG.computedAppVersion)) { console.log(`Deleting downloaded nupkg for previous version at ${nupkgPath} to prevent it from being stored as an artifact`) - fs.removeSync(nupkgPath) + fs.unlinkSync(nupkgPath) + } else { + if (process.arch === 'x64') { + // Use the original .nupkg filename to generate the `atom-x64` name by inserting `-x64` after `atom` + const newNupkgPath = nupkgPath.replace('atom-', 'atom-x64-') + fs.renameSync(nupkgPath, newNupkgPath) + } } } + + return `${CONFIG.buildOutputPath}/${options.setupExe}` } console.log(`Creating Windows Installer for ${packagedAppPath}`) diff --git a/script/lib/generate-metadata.js b/script/lib/generate-metadata.js index 6bcd18618..ae61b6633 100644 --- a/script/lib/generate-metadata.js +++ b/script/lib/generate-metadata.js @@ -6,7 +6,6 @@ const fs = require('fs-plus') const normalizePackageData = require('normalize-package-data') const path = require('path') const semver = require('semver') -const spawnSync = require('./spawn-sync') const CONFIG = require('../config') @@ -16,7 +15,7 @@ module.exports = function () { CONFIG.appMetadata._atomMenu = buildPlatformMenuMetadata() CONFIG.appMetadata._atomKeymaps = buildPlatformKeymapsMetadata() CONFIG.appMetadata._deprecatedPackages = deprecatedPackagesMetadata - CONFIG.appMetadata.version = computeAppVersion() + CONFIG.appMetadata.version = CONFIG.computedAppVersion checkDeprecatedPackagesMetadata() fs.writeFileSync(path.join(CONFIG.intermediateAppPath, 'package.json'), JSON.stringify(CONFIG.appMetadata)) } @@ -162,13 +161,3 @@ function checkDeprecatedPackagesMetadata () { } } } - -function computeAppVersion () { - let version = CONFIG.appMetadata.version - if (CONFIG.channel === 'dev') { - const result = spawnSync('git', ['rev-parse', '--short', 'HEAD'], {cwd: CONFIG.repositoryRootPath}) - const commitHash = result.stdout.toString().trim() - version += '-' + commitHash - } - return version -} diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 8c33e5494..4e4945e19 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -2,6 +2,7 @@ const childProcess = require('child_process') const fs = require('fs') const path = require('path') const electronLink = require('electron-link') +const terser = require('terser') const CONFIG = require('../config') module.exports = function (packagedAppPath) { @@ -15,64 +16,75 @@ module.exports = function (packagedAppPath) { mainPath: path.resolve(baseDirPath, '..', 'src', 'initialize-application-window.js'), cachePath: path.join(CONFIG.atomHomeDirPath, 'snapshot-cache'), auxiliaryData: CONFIG.snapshotAuxiliaryData, - shouldExcludeModule: (modulePath) => { + shouldExcludeModule: ({requiringModulePath, requiredModulePath}) => { if (processedFiles > 0) { process.stdout.write('\r') } process.stdout.write(`Generating snapshot script at "${snapshotScriptPath}" (${++processedFiles})`) - const relativePath = path.relative(baseDirPath, modulePath) + const requiringModuleRelativePath = path.relative(baseDirPath, requiringModulePath) + const requiredModuleRelativePath = path.relative(baseDirPath, requiredModulePath) return ( - modulePath.endsWith('.node') || - coreModules.has(modulePath) || - (relativePath.startsWith(path.join('..', 'src')) && relativePath.endsWith('-element.js')) || - relativePath.startsWith(path.join('..', 'node_modules', 'dugite')) || - relativePath.endsWith(path.join('node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js')) || - relativePath.endsWith(path.join('node_modules', 'fs-extra', 'lib', 'index.js')) || - relativePath.endsWith(path.join('node_modules', 'graceful-fs', 'graceful-fs.js')) || - relativePath.endsWith(path.join('node_modules', 'htmlparser2', 'lib', 'index.js')) || - relativePath.endsWith(path.join('node_modules', 'minimatch', 'minimatch.js')) || - relativePath.endsWith(path.join('node_modules', 'request', 'index.js')) || - relativePath.endsWith(path.join('node_modules', 'request', 'request.js')) || - relativePath === path.join('..', 'exports', 'atom.js') || - relativePath === path.join('..', 'src', 'electron-shims.js') || - relativePath === path.join('..', 'src', 'safe-clipboard.js') || - relativePath === path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') || - relativePath === path.join('..', 'node_modules', 'babel-core', 'index.js') || - relativePath === path.join('..', 'node_modules', 'cached-run-in-this-context', 'lib', 'main.js') || - relativePath === path.join('..', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || - relativePath === path.join('..', 'node_modules', 'debug', 'node.js') || - relativePath === path.join('..', 'node_modules', 'git-utils', 'src', 'git.js') || - relativePath === path.join('..', 'node_modules', 'glob', 'glob.js') || - relativePath === path.join('..', 'node_modules', 'iconv-lite', 'lib', 'index.js') || - relativePath === path.join('..', 'node_modules', 'less', 'index.js') || - relativePath === path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || - relativePath === path.join('..', 'node_modules', 'less', 'lib', 'less-node', 'index.js') || - relativePath === path.join('..', 'node_modules', 'lodash.isequal', 'index.js') || - relativePath === path.join('..', 'node_modules', 'node-fetch', 'lib', 'fetch-error.js') || - relativePath === path.join('..', 'node_modules', 'superstring', 'index.js') || - relativePath === path.join('..', 'node_modules', 'oniguruma', 'src', 'oniguruma.js') || - relativePath === path.join('..', 'node_modules', 'resolve', 'index.js') || - relativePath === path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') || - relativePath === path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') || - relativePath === path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') || - relativePath === path.join('..', 'node_modules', 'spelling-manager', 'node_modules', 'natural', 'lib', 'natural', 'index.js') || - relativePath === path.join('..', 'node_modules', 'tar', 'tar.js') || - relativePath === path.join('..', 'node_modules', 'temp', 'lib', 'temp.js') || - relativePath === path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js') || - relativePath === path.join('..', 'node_modules', 'tree-sitter', 'index.js') || - relativePath === path.join('..', 'node_modules', 'winreg', 'lib', 'registry.js') + requiredModulePath.endsWith('.node') || + coreModules.has(requiredModulePath) || + requiringModuleRelativePath.endsWith(path.join('node_modules/xregexp/xregexp-all.js')) || + (requiredModuleRelativePath.startsWith(path.join('..', 'src')) && requiredModuleRelativePath.endsWith('-element.js')) || + requiredModuleRelativePath.startsWith(path.join('..', 'node_modules', 'dugite')) || + requiredModuleRelativePath.endsWith(path.join('node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js')) || + requiredModuleRelativePath.endsWith(path.join('node_modules', 'fs-extra', 'lib', 'index.js')) || + requiredModuleRelativePath.endsWith(path.join('node_modules', 'graceful-fs', 'graceful-fs.js')) || + requiredModuleRelativePath.endsWith(path.join('node_modules', 'htmlparser2', 'lib', 'index.js')) || + requiredModuleRelativePath.endsWith(path.join('node_modules', 'minimatch', 'minimatch.js')) || + requiredModuleRelativePath.endsWith(path.join('node_modules', 'request', 'index.js')) || + requiredModuleRelativePath.endsWith(path.join('node_modules', 'request', 'request.js')) || + requiredModuleRelativePath === path.join('..', 'exports', 'atom.js') || + requiredModuleRelativePath === path.join('..', 'src', 'electron-shims.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'babel-core', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'cached-run-in-this-context', 'lib', 'main.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'debug', 'node.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'git-utils', 'src', 'git.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'glob', 'glob.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'iconv-lite', 'lib', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'less', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'less', 'lib', 'less-node', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'lodash.isequal', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'node-fetch', 'lib', 'fetch-error.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'superstring', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'oniguruma', 'src', 'oniguruma.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'resolve', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'spelling-manager', 'node_modules', 'natural', 'lib', 'natural', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'tar', 'tar.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'ls-archive', 'node_modules', 'tar', 'tar.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'temp', 'lib', 'temp.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'tree-sitter', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'yauzl', 'index.js') || + requiredModuleRelativePath === path.join('..', 'node_modules', 'winreg', 'lib', 'registry.js') ) } - }).then((snapshotScript) => { - fs.writeFileSync(snapshotScriptPath, snapshotScript) + }).then(({snapshotScript}) => { process.stdout.write('\n') + process.stdout.write('Minifying startup script') + const minification = terser.minify(snapshotScript, { + keep_fnames: true, + keep_classnames: true, + compress: {keep_fargs: true, keep_infinity: true} + }) + if (minification.error) throw minification.error + process.stdout.write('\n') + fs.writeFileSync(snapshotScriptPath, minification.code) + console.log('Verifying if snapshot can be executed via `mksnapshot`') const verifySnapshotScriptPath = path.join(CONFIG.repositoryRootPath, 'script', 'verify-snapshot-script') let nodeBundledInElectronPath if (process.platform === 'darwin') { - const executableName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom' + const executableName = CONFIG.appName nodeBundledInElectronPath = path.join(packagedAppPath, 'Contents', 'MacOS', executableName) } else if (process.platform === 'win32') { nodeBundledInElectronPath = path.join(packagedAppPath, 'atom.exe') diff --git a/script/lib/include-path-in-packaged-app.js b/script/lib/include-path-in-packaged-app.js index 603f14da0..842cfab2f 100644 --- a/script/lib/include-path-in-packaged-app.js +++ b/script/lib/include-path-in-packaged-app.js @@ -14,7 +14,6 @@ const EXCLUDE_REGEXPS_SOURCES = [ escapeRegExp('.pairs'), escapeRegExp('.travis.yml'), escapeRegExp('appveyor.yml'), - escapeRegExp('circle.yml'), escapeRegExp('.idea'), escapeRegExp('.editorconfig'), escapeRegExp('.lint'), @@ -69,7 +68,6 @@ const EXCLUDE_REGEXPS_SOURCES = [ // Ignore node_module files we won't need at runtime 'node_modules' + escapeRegExp(path.sep) + '.*' + escapeRegExp(path.sep) + '_*te?sts?_*' + escapeRegExp(path.sep), 'node_modules' + escapeRegExp(path.sep) + '.*' + escapeRegExp(path.sep) + 'examples?' + escapeRegExp(path.sep), - 'node_modules' + escapeRegExp(path.sep) + '.*' + '\\.md$', 'node_modules' + escapeRegExp(path.sep) + '.*' + '\\.d\\.ts$', 'node_modules' + escapeRegExp(path.sep) + '.*' + '\\.js\\.map$', '.*' + escapeRegExp(path.sep) + 'test.*\\.html$' diff --git a/script/lib/install-apm.js b/script/lib/install-apm.js index ce68b79a6..81c9e849d 100644 --- a/script/lib/install-apm.js +++ b/script/lib/install-apm.js @@ -4,8 +4,9 @@ const childProcess = require('child_process') const CONFIG = require('../config') -module.exports = function () { +module.exports = function (ci) { console.log('Installing apm') + // npm ci leaves apm with a bunch of unmet dependencies childProcess.execFileSync( CONFIG.getNpmBinPath(), ['--global-style', '--loglevel=error', 'install'], diff --git a/script/lib/install-script-dependencies.js b/script/lib/install-script-dependencies.js index 5a36e69a6..76f6e94c6 100644 --- a/script/lib/install-script-dependencies.js +++ b/script/lib/install-script-dependencies.js @@ -4,11 +4,11 @@ const childProcess = require('child_process') const CONFIG = require('../config') -module.exports = function () { +module.exports = function (ci) { console.log('Installing script dependencies') childProcess.execFileSync( - CONFIG.getNpmBinPath(), - ['--loglevel=error', 'install'], + CONFIG.getNpmBinPath(ci), + ['--loglevel=error', ci ? 'ci' : 'install'], {env: process.env, cwd: CONFIG.scriptRootPath} ) } diff --git a/script/lib/package-application.js b/script/lib/package-application.js index 842883e51..1b3c19b28 100644 --- a/script/lib/package-application.js +++ b/script/lib/package-application.js @@ -114,7 +114,7 @@ function buildAsarUnpackGlobExpression () { function getAppName () { if (process.platform === 'darwin') { - return CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom' + return CONFIG.appName } else { return 'atom' } @@ -156,7 +156,7 @@ function renamePackagedAppDir (packageOutputDirPath) { if (fs.existsSync(packagedAppPath)) fs.removeSync(packagedAppPath) fs.renameSync(path.join(packageOutputDirPath, appBundleName), packagedAppPath) } else if (process.platform === 'linux') { - const appName = CONFIG.channel === 'beta' ? 'atom-beta' : 'atom' + const appName = CONFIG.channel !== 'stable' ? `atom-${CONFIG.channel}` : 'atom' let architecture if (process.arch === 'ia32') { architecture = 'i386' @@ -169,8 +169,7 @@ function renamePackagedAppDir (packageOutputDirPath) { if (fs.existsSync(packagedAppPath)) fs.removeSync(packagedAppPath) fs.renameSync(packageOutputDirPath, packagedAppPath) } else { - const appName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom' - packagedAppPath = path.join(CONFIG.buildOutputPath, appName) + packagedAppPath = path.join(CONFIG.buildOutputPath, CONFIG.appName) if (process.platform === 'win32' && process.arch !== 'ia32') { packagedAppPath += ` ${process.arch}` } diff --git a/script/lib/run-apm-install.js b/script/lib/run-apm-install.js index 3f56e8dd4..982ed7165 100644 --- a/script/lib/run-apm-install.js +++ b/script/lib/run-apm-install.js @@ -4,7 +4,7 @@ const childProcess = require('child_process') const CONFIG = require('../config') -module.exports = function (packagePath) { +module.exports = function (packagePath, ci, stdioOptions) { const installEnv = Object.assign({}, process.env) // Set resource path so that apm can load metadata related to Atom. installEnv.ATOM_RESOURCE_PATH = CONFIG.repositoryRootPath @@ -13,7 +13,7 @@ module.exports = function (packagePath) { installEnv.npm_config_target = CONFIG.appMetadata.electronVersion childProcess.execFileSync( CONFIG.getApmBinPath(), - ['--loglevel=error', 'install'], - {env: installEnv, cwd: packagePath, stdio: 'inherit'} + ['--loglevel=error', ci ? 'ci' : 'install'], + {env: installEnv, cwd: packagePath, stdio: stdioOptions || 'inherit'} ) } diff --git a/script/lib/upload-to-s3.js b/script/lib/upload-to-s3.js new file mode 100644 index 000000000..91c50b384 --- /dev/null +++ b/script/lib/upload-to-s3.js @@ -0,0 +1,57 @@ +'use strict' + +const fs = require('fs') +const path = require('path') +const aws = require('aws-sdk') + +module.exports = function (s3Key, s3Secret, s3Bucket, directory, assets) { + const s3 = new aws.S3({ + accessKeyId: s3Key, + secretAccessKey: s3Secret, + params: { Bucket: s3Bucket } + }) + + function listExistingAssetsForDirectory (directory) { + return s3.listObjectsV2({ Prefix: directory }).promise().then((res) => { + return res.Contents.map((obj) => { return { Key: obj.Key } }) + }) + } + + function deleteExistingAssets (existingAssets) { + if (existingAssets.length > 0) { + return s3.deleteObjects({ Delete: { Objects: existingAssets } }).promise() + } else { + return Promise.resolve(true) + } + } + + function uploadAssets (assets, directory) { + return assets.reduce( + function (promise, asset) { + return promise.then(() => uploadAsset(directory, asset)) + }, Promise.resolve()) + } + + function uploadAsset (directory, assetPath) { + return new Promise((resolve, reject) => { + console.info(`Uploading ${assetPath}`) + const params = { + Key: `${directory}${path.basename(assetPath)}`, + ACL: 'public-read', + Body: fs.createReadStream(assetPath) + } + + s3.upload(params, error => { + if (error) { + reject(error) + } else { + resolve() + } + }) + }) + } + + return listExistingAssetsForDirectory(directory) + .then(deleteExistingAssets) + .then(() => uploadAssets(assets, directory)) +} diff --git a/script/package-lock.json b/script/package-lock.json new file mode 100644 index 000000000..ce6897f61 --- /dev/null +++ b/script/package-lock.json @@ -0,0 +1,10773 @@ +{ + "name": "atom-build-scripts", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "7zip-bin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-4.0.2.tgz", + "integrity": "sha512-XtGk+IF57pr852UK1AhQJXqmm1WmSgS5uISL+LPs0z/iAxXouMvdlLJrHPeukP6gd7yR2rDTMSMkHNODgwIq7A==" + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", + "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "abstract-leveldown": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz", + "integrity": "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==", + "requires": { + "xtend": "~4.0.0" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "alter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz", + "integrity": "sha1-x1iICGF1cgNKrmJICvJrHU0cs80=", + "requires": { + "stable": "~0.1.3" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "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": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "archiver": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-0.6.1.tgz", + "integrity": "sha1-1AKZJXH9F5rtZy2Xl/iI5Wjh3Vw=", + "requires": { + "file-utils": "~0.1.5", + "lazystream": "~0.1.0", + "lodash": "~2.4.1", + "readable-stream": "~1.0.24", + "zip-stream": "~0.2.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + } + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "array-iterate": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-1.1.2.tgz", + "integrity": "sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ==" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "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=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asar": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-0.11.0.tgz", + "integrity": "sha1-uSbnksMV+MBIxDNx4yWwnJenZGQ=", + "requires": { + "chromium-pickle-js": "^0.1.0", + "commander": "^2.9.0", + "cuint": "^0.2.1", + "glob": "^6.0.4", + "minimatch": "^3.0.0", + "mkdirp": "^0.5.0", + "mksnapshot": "^0.3.0" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "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" + } + } + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-traverse": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ast-traverse/-/ast-traverse-0.1.1.tgz", + "integrity": "sha1-ac8rg4bxnc2hux4F1o/jWdiJfeY=" + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=" + }, + "ast-util": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/ast-util/-/ast-util-0.6.0.tgz", + "integrity": "sha1-DZE9BPDpgx5T+ZkdyZAJ4tp3SBA=", + "requires": { + "ast-types": "~0.6.7", + "private": "~0.1.6" + }, + "dependencies": { + "ast-types": { + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.6.16.tgz", + "integrity": "sha1-BCBbcu3dGVqP6qCB8R0ClKJN7ZM=" + } + } + }, + "async": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.0.1.tgz", + "integrity": "sha1-twnMAoCpw28J9FNr6CPIOKkEniU=", + "requires": { + "lodash": "^4.8.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + }, + "atomdoc": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/atomdoc/-/atomdoc-1.0.6.tgz", + "integrity": "sha512-DU9ABgZw7egM0mxAe2AZX1RqEDyXu/PeIsVni/R3hxeuXEyyf+GVfygcYwclx1d7bEUVVMP+zTB8Aw4itei4sA==", + "requires": { + "marked": "^0.3.6" + } + }, + "autoprefixer": { + "version": "8.6.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz", + "integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==", + "requires": { + "browserslist": "^3.2.8", + "caniuse-lite": "^1.0.30000864", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^6.0.23", + "postcss-value-parser": "^3.2.3" + } + }, + "aws-sdk": { + "version": "2.275.1", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.275.1.tgz", + "integrity": "sha512-lcpgoiHLhdcolUT7aJdg/CmlYO5ecf+3A+4dIceO72mFovCWZde1Rvr07QNbQ8gT0paqr5j2rs2b6c23Y/K0RQ==", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.8", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.1.0", + "xml2js": "0.4.19" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "babel-core": { + "version": "5.8.38", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-5.8.38.tgz", + "integrity": "sha1-H8ruedfmG3ULALjlT238nQr4ZVg=", + "requires": { + "babel-plugin-constant-folding": "^1.0.1", + "babel-plugin-dead-code-elimination": "^1.0.2", + "babel-plugin-eval": "^1.0.1", + "babel-plugin-inline-environment-variables": "^1.0.1", + "babel-plugin-jscript": "^1.0.4", + "babel-plugin-member-expression-literals": "^1.0.1", + "babel-plugin-property-literals": "^1.0.1", + "babel-plugin-proto-to-assign": "^1.0.3", + "babel-plugin-react-constant-elements": "^1.0.3", + "babel-plugin-react-display-name": "^1.0.3", + "babel-plugin-remove-console": "^1.0.1", + "babel-plugin-remove-debugger": "^1.0.1", + "babel-plugin-runtime": "^1.0.7", + "babel-plugin-undeclared-variables-check": "^1.0.2", + "babel-plugin-undefined-to-void": "^1.1.6", + "babylon": "^5.8.38", + "bluebird": "^2.9.33", + "chalk": "^1.0.0", + "convert-source-map": "^1.1.0", + "core-js": "^1.0.0", + "debug": "^2.1.1", + "detect-indent": "^3.0.0", + "esutils": "^2.0.0", + "fs-readdir-recursive": "^0.1.0", + "globals": "^6.4.0", + "home-or-tmp": "^1.0.0", + "is-integer": "^1.0.4", + "js-tokens": "1.0.1", + "json5": "^0.4.0", + "lodash": "^3.10.0", + "minimatch": "^2.0.3", + "output-file-sync": "^1.1.0", + "path-exists": "^1.0.0", + "path-is-absolute": "^1.0.0", + "private": "^0.1.6", + "regenerator": "0.8.40", + "regexpu": "^1.3.0", + "repeating": "^1.1.2", + "resolve": "^1.1.6", + "shebang-regex": "^1.0.0", + "slash": "^1.0.0", + "source-map": "^0.5.0", + "source-map-support": "^0.2.10", + "to-fast-properties": "^1.0.0", + "trim-right": "^1.0.0", + "try-resolve": "^1.0.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "babel-plugin-constant-folding": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-constant-folding/-/babel-plugin-constant-folding-1.0.1.tgz", + "integrity": "sha1-g2HTZMmORJw2kr26Ue/whEKQqo4=" + }, + "babel-plugin-dead-code-elimination": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-dead-code-elimination/-/babel-plugin-dead-code-elimination-1.0.2.tgz", + "integrity": "sha1-X3xFEnTc18zNv7s+C4XdKBIfD2U=" + }, + "babel-plugin-eval": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz", + "integrity": "sha1-ovrtJc5r5preS/7CY/cBaRlZUNo=" + }, + "babel-plugin-inline-environment-variables": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-inline-environment-variables/-/babel-plugin-inline-environment-variables-1.0.1.tgz", + "integrity": "sha1-H1jOkSB61qgmqL9kX6/mj/X+P/4=" + }, + "babel-plugin-jscript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/babel-plugin-jscript/-/babel-plugin-jscript-1.0.4.tgz", + "integrity": "sha1-jzQsOCduh6R9X6CovT1etsytj8w=" + }, + "babel-plugin-member-expression-literals": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-member-expression-literals/-/babel-plugin-member-expression-literals-1.0.1.tgz", + "integrity": "sha1-zF7bD6qNyScXDnTW0cAkQAIWJNM=" + }, + "babel-plugin-property-literals": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-property-literals/-/babel-plugin-property-literals-1.0.1.tgz", + "integrity": "sha1-AlIwGQAZKYCxwRjv6kjOk6q4MzY=" + }, + "babel-plugin-proto-to-assign": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/babel-plugin-proto-to-assign/-/babel-plugin-proto-to-assign-1.0.4.tgz", + "integrity": "sha1-xJ56/QL1d7xNoF6i3wAiUM980SM=", + "requires": { + "lodash": "^3.9.3" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "babel-plugin-react-constant-elements": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/babel-plugin-react-constant-elements/-/babel-plugin-react-constant-elements-1.0.3.tgz", + "integrity": "sha1-lGc26DeEKcvDSdz/YvUcFDs041o=" + }, + "babel-plugin-react-display-name": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/babel-plugin-react-display-name/-/babel-plugin-react-display-name-1.0.3.tgz", + "integrity": "sha1-dU/jiSboQkpOexWrbqYTne4FFPw=" + }, + "babel-plugin-remove-console": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-remove-console/-/babel-plugin-remove-console-1.0.1.tgz", + "integrity": "sha1-2PJFVsOgUAXUKqqv0neH9T/wE6c=" + }, + "babel-plugin-remove-debugger": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-remove-debugger/-/babel-plugin-remove-debugger-1.0.1.tgz", + "integrity": "sha1-/S6jzWGkKK0fO5yJiC/0KT6MFMc=" + }, + "babel-plugin-runtime": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-runtime/-/babel-plugin-runtime-1.0.7.tgz", + "integrity": "sha1-v3x9lm3Vbs1cF/ocslPJrLflSq8=" + }, + "babel-plugin-undeclared-variables-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-undeclared-variables-check/-/babel-plugin-undeclared-variables-check-1.0.2.tgz", + "integrity": "sha1-XPGqU52BP/ZOmWQSkK9iCWX2Xe4=", + "requires": { + "leven": "^1.0.2" + } + }, + "babel-plugin-undefined-to-void": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/babel-plugin-undefined-to-void/-/babel-plugin-undefined-to-void-1.1.6.tgz", + "integrity": "sha1-f1eO+LeN+uYAM4XYQXph7aBuL4E=" + }, + "babylon": { + "version": "5.8.38", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-5.8.38.tgz", + "integrity": "sha1-7JsSCxG/bM1Bc6GL8hfmC3mFn/0=" + }, + "bail": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", + "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "requires": { + "hoek": "0.9.x" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "breakable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/breakable/-/breakable-1.0.0.tgz", + "integrity": "sha1-eEp5eRWjjq0nutRWtVcstLuqeME=" + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "builtins": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.4.tgz", + "integrity": "sha1-7G1MpLpaOhc3SfEBRr3Noo6m1l0=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + } + } + }, + "caniuse-lite": { + "version": "1.0.30000865", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", + "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "ccount": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz", + "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chainit": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chainit/-/chainit-2.1.1.tgz", + "integrity": "sha1-5TRdnAcdRz5zJ0yIrqZskVE2KME=", + "requires": { + "queue": "~1.0.2" + } + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "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" + } + }, + "character-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz", + "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==" + }, + "character-entities-html4": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz", + "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==" + }, + "character-entities-legacy": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz", + "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==" + }, + "character-reference-invalid": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz", + "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==" + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "chromium-pickle-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.1.0.tgz", + "integrity": "sha1-HUixB9ghJqLz4hHC6iX4A7pVGyE=" + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "cli-width": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", + "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=" + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "clone-regexp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz", + "integrity": "sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==", + "requires": { + "is-regexp": "^1.0.0", + "is-supported-regexp-flag": "^1.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "coffee-script": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz", + "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=" + }, + "coffeelint": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/coffeelint/-/coffeelint-1.15.7.tgz", + "integrity": "sha1-9mmCqUBV1zU3bFz18cu54oFDNOk=", + "requires": { + "coffee-script": "~1.10.0", + "glob": "^4.0.0", + "ignore": "^3.0.9", + "optimist": "^0.6.1", + "resolve": "^0.6.3", + "strip-json-comments": "^1.0.2" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "resolve": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", + "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=" + } + } + }, + "collapse-white-space": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz", + "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "requires": { + "color-name": "1.1.1" + } + }, + "color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", + "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==" + }, + "commoner": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", + "integrity": "sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=", + "requires": { + "commander": "^2.5.0", + "detective": "^4.3.1", + "glob": "^5.0.15", + "graceful-fs": "^4.1.2", + "iconv-lite": "^0.4.5", + "mkdirp": "^0.5.0", + "private": "^0.1.6", + "q": "^1.1.2", + "recast": "^0.11.17" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "requires": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + } + } + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.5.tgz", + "integrity": "sha512-94j37OtvxS5w7qr7Ta6dt67tWdnOxigBVN4VnSxNXFez9o18PGQ0D33SchKP17r9LAcWVTYV72G6vDayAUBFIg==", + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", + "requires": { + "lru-cache": "^4.0.0", + "which": "^1.2.8" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "optional": true, + "requires": { + "boom": "0.4.x" + } + }, + "cson-parser": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-1.0.9.tgz", + "integrity": "sha1-t5/BuCp3V0NoDw7/uL+tMRNNrHQ=", + "requires": { + "coffee-script": "1.9.0" + }, + "dependencies": { + "coffee-script": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.9.0.tgz", + "integrity": "sha1-dJLLvD8DYcxdiGWv9yN1Uv8z4fc=" + } + } + }, + "css-parse": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", + "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=" + }, + "css-value": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "integrity": "sha1-Xv1sLupeof1rasV+wEJ7GEUkJOo=" + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "optional": true + }, + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=" + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, + "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" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=" + }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "decompress-zip": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.3.0.tgz", + "integrity": "sha1-rjvLfjTGWHmt/nfhnDD4ZgK0vbA=", + "requires": { + "binary": "^0.3.0", + "graceful-fs": "^4.1.3", + "mkpath": "^0.1.0", + "nopt": "^3.0.1", + "q": "^1.1.2", + "readable-stream": "^1.1.8", + "touch": "0.0.3" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "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=" + }, + "deepmerge": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-0.2.10.tgz", + "integrity": "sha1-iQa/nlJaT78bIDsq/LRkAkmCEhk=" + }, + "deferred-leveldown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz", + "integrity": "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==", + "requires": { + "abstract-leveldown": "~5.0.0", + "inherits": "^2.0.3" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "defs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/defs/-/defs-1.1.1.tgz", + "integrity": "sha1-siYJ8sehG6ej2xFoBcE5scr/qdI=", + "requires": { + "alter": "~0.2.0", + "ast-traverse": "~0.1.1", + "breakable": "~1.0.0", + "esprima-fb": "~15001.1001.0-dev-harmony-fb", + "simple-fmt": "~0.1.0", + "simple-is": "~0.2.0", + "stringmap": "~0.2.2", + "stringset": "~0.2.1", + "tryor": "~0.1.2", + "yargs": "~3.27.0" + }, + "dependencies": { + "yargs": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.27.0.tgz", + "integrity": "sha1-ISBUaTFuk5Ex1Z8toMbX+YIh6kA=", + "requires": { + "camelcase": "^1.2.1", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "os-locale": "^1.4.0", + "window-size": "^0.1.2", + "y18n": "^3.2.0" + } + } + } + }, + "deglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", + "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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" + } + }, + "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" + } + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-indent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz", + "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=", + "requires": { + "get-stdin": "^4.0.1", + "minimist": "^1.1.0", + "repeating": "^1.1.0" + } + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } + }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=" + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "requires": { + "arrify": "^1.0.1", + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "donna": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/donna/-/donna-1.0.16.tgz", + "integrity": "sha1-w/+yM9P2Zk0qJvGDJ4mNq9MmZZ0=", + "requires": { + "async": ">= 0.1.22", + "builtins": "0.0.4", + "coffee-script": "1.10.x", + "optimist": "~0.6", + "source-map": "0.1.29", + "underscore": ">= 0.1.0", + "underscore.string": ">= 0.1.0", + "walkdir": ">= 0.0.2" + }, + "dependencies": { + "source-map": { + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.29.tgz", + "integrity": "sha1-OdVxoJiPt6VIpnbE3nLbeJFNFzw=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "^1.0.0" + } + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "~1.1.9" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } + }, + "editor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/editor/-/editor-1.0.0.tgz", + "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=" + }, + "electron-chromedriver": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-2.0.0.tgz", + "integrity": "sha512-kERk/Wzhc9RzW9jUKXA5kJc4m8BlL6c9p5QH+CrIlst0saeqZL1Up7vzD4ZOnuBDpAVBBYJ4jhkAKIssf8ZlXg==", + "requires": { + "electron-download": "^4.1.0", + "extract-zip": "^1.6.5" + } + }, + "electron-download": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.0.tgz", + "integrity": "sha1-v5MsdG8vh//MCdHdRy8v9rkYeEU=", + "requires": { + "debug": "^2.2.0", + "env-paths": "^1.0.0", + "fs-extra": "^2.0.0", + "minimist": "^1.2.0", + "nugget": "^2.0.0", + "path-exists": "^3.0.0", + "rc": "^1.1.2", + "semver": "^5.3.0", + "sumchecker": "^2.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "electron-link": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/electron-link/-/electron-link-0.2.2.tgz", + "integrity": "sha1-uWvx/MrowwyAuiaTBq+UVOYtP2U=", + "requires": { + "ast-util": "^0.6.0", + "encoding-down": "~5.0.0", + "indent-string": "^2.1.0", + "leveldown": "~4.0.0", + "levelup": "~3.0.0", + "recast": "^0.12.6", + "resolve": "^1.5.0", + "source-map": "^0.5.6" + }, + "dependencies": { + "ast-types": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", + "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "recast": { + "version": "0.12.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", + "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", + "requires": { + "ast-types": "0.10.1", + "core-js": "^2.4.1", + "esprima": "~4.0.0", + "private": "~0.1.5", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + } + } + }, + "electron-mksnapshot": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/electron-mksnapshot/-/electron-mksnapshot-2.0.0.tgz", + "integrity": "sha512-OoZwZJNKgHP+DwhCGVTJEuDSeb478hOzAbHeg7dKGCHDbKKmUWmjGc+pEjxGutpqQ3Mn8hCdLzdx2c/lAJcTLA==", + "requires": { + "electron-download": "^4.1.0", + "extract-zip": "^1.6.5" + } + }, + "electron-osx-sign": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.3.2.tgz", + "integrity": "sha1-iPp9brrbXZx5NouWSRoNjEYwFG4=", + "requires": { + "debug": "^2.2.0", + "minimist": "^1.1.1", + "run-series": "^1.1.1" + } + }, + "electron-packager": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-7.3.0.tgz", + "integrity": "sha1-WDP3Xz/WwMSQiXrQ5kf6EtM7V30=", + "requires": { + "asar": "^0.11.0", + "electron-download": "^2.0.0", + "electron-osx-sign": "^0.3.0", + "extract-zip": "^1.0.3", + "fs-extra": "^0.28.0", + "get-package-info": "0.0.2", + "minimist": "^1.1.1", + "plist": "^1.1.0", + "rcedit": "^0.5.1", + "resolve": "^1.1.6", + "run-series": "^1.1.1" + }, + "dependencies": { + "electron-download": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-2.2.1.tgz", + "integrity": "sha1-PXivNkXJZDXjvz35uIKhTMLKKUw=", + "requires": { + "debug": "^2.2.0", + "home-path": "^1.0.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.0", + "mv": "^2.0.3", + "nugget": "^1.5.1", + "path-exists": "^1.0.0", + "rc": "^1.1.2" + } + }, + "fs-extra": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.28.0.tgz", + "integrity": "sha1-mhwHCOqMUWkperBv2MuRT1ZHsnI=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "nugget": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-1.6.2.tgz", + "integrity": "sha1-iMpuA7pXBqmRc/XaCQJZPWvK4Qc=", + "requires": { + "debug": "^2.1.3", + "minimist": "^1.1.0", + "pretty-bytes": "^1.0.2", + "progress-stream": "^1.1.0", + "request": "^2.45.0", + "single-line-log": "^0.4.1", + "throttleit": "0.0.2" + } + }, + "single-line-log": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", + "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" + } + } + }, + "electron-to-chromium": { + "version": "1.3.52", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", + "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=" + }, + "electron-winstaller": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-2.6.4.tgz", + "integrity": "sha1-a0gHboc6bqNWJR8Ve2i55dwDtak=", + "requires": { + "asar": "^0.11.0", + "bluebird": "^3.3.4", + "debug": "^2.2.0", + "fs-extra": "^0.26.7", + "lodash.template": "^4.2.2", + "temp": "^0.8.3" + }, + "dependencies": { + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + } + } + }, + "encoding-down": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz", + "integrity": "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==", + "requires": { + "abstract-leveldown": "^5.0.0", + "inherits": "^2.0.3", + "level-codec": "^9.0.0", + "level-errors": "^2.0.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + }, + "env-paths": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", + "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=" + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "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==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.45", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + }, + "es6-iterator": { + "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.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.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=" + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.7.1.tgz", + "integrity": "sha1-f6qEWZ4P6kIvBLwy20kFQFGj8Ro=", + "requires": { + "chalk": "^1.1.3", + "concat-stream": "^1.4.6", + "debug": "^2.1.1", + "doctrine": "^1.2.2", + "escope": "^3.6.0", + "espree": "^3.3.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "glob": "^7.0.3", + "globals": "^9.2.0", + "ignore": "^3.1.5", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "levn": "^0.3.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", + "optionator": "^0.8.1", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.6.0", + "strip-bom": "^3.0.0", + "strip-json-comments": "~1.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + }, + "dependencies": { + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "requires": { + "os-homedir": "^1.0.0" + } + } + } + }, + "eslint-config-standard": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-6.2.0.tgz", + "integrity": "sha1-HSOE7gdN5va2wPK76XaGMDJWWu4=" + }, + "eslint-config-standard-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.2.0.tgz", + "integrity": "sha1-wkDibtkZoRpCqk3oBZRys4Jo1iA=" + }, + "eslint-plugin-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.0.0.tgz", + "integrity": "sha1-FShjXQFg80hOQlzOIWnLdM7AGGo=" + }, + "eslint-plugin-react": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.4.1.tgz", + "integrity": "sha1-fRqt50fbFYkvce7h/qSt35e8+is=", + "requires": { + "doctrine": "^1.2.2", + "jsx-ast-utils": "^1.3.1" + } + }, + "eslint-plugin-standard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz", + "integrity": "sha1-NYlpn/nJF/LCX3apFmh/ZBw2n/M=" + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "esprima-fb": { + "version": "15001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=" + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "execa": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.4.0.tgz", + "integrity": "sha1-TrZGejaglfq7KXD/nV4/t7zm68M=", + "requires": { + "cross-spawn-async": "^2.1.1", + "is-stream": "^1.1.0", + "npm-run-path": "^1.0.0", + "object-assign": "^4.0.1", + "path-key": "^1.0.0", + "strip-eof": "^1.0.0" + } + }, + "execall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", + "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", + "requires": { + "clone-regexp": "^1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "^2.1.0" + } + }, + "expand-template": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", + "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==" + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-future": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", + "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=" + }, + "fast-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", + "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.0.1", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.1", + "micromatch": "^3.1.10" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "requires": { + "pend": "~1.2.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "file-utils": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/file-utils/-/file-utils-0.1.5.tgz", + "integrity": "sha1-3IFTyFU4fLTaywoXJVMfpESmtIw=", + "requires": { + "findup-sync": "~0.1.2", + "glob": "~3.2.6", + "iconv-lite": "~0.2.11", + "isbinaryfile": "~0.1.9", + "lodash": "~2.1.0", + "minimatch": "~0.2.12", + "rimraf": "~2.2.2" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "requires": { + "inherits": "2", + "minimatch": "0.3" + }, + "dependencies": { + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=" + }, + "lodash": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.1.0.tgz", + "integrity": "sha1-Bjfqqjaooc/IZcOt+5Qhib+wmY0=" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "requires": { + "glob": "~3.2.9", + "lodash": "~2.4.1" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "requires": { + "inherits": "2", + "minimatch": "0.3" + } + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-admin": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/fs-admin/-/fs-admin-0.1.6.tgz", + "integrity": "sha512-JHRSPVRBrYggAGM6kpvNvFdxuFmoDxamnBVQT/JApZtVji7bHKbhLOka1Y2pNSQ/OVChbmZFKcWdpwuZEpA65w==", + "requires": { + "mocha": "^3.5.0", + "nan": "^2.6.2" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "fs-plus": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-2.10.1.tgz", + "integrity": "sha1-MgR4HXhAYR5jZOe2+wWMljJ8WqU=", + "requires": { + "async": "^1.5.2", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.2", + "underscore-plus": "1.x" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + } + } + }, + "fs-readdir-recursive": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz", + "integrity": "sha1-MVtPuMHKW4xH3v7zGdBz2tNWgFk=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "^1.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-package-info": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-0.0.2.tgz", + "integrity": "sha1-csOPvuLnZyhCSgDcFOJN0aKMI5E=", + "requires": { + "bluebird": "^3.1.1", + "lodash.get": "^4.0.0", + "resolve": "^1.1.6" + }, + "dependencies": { + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + } + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "ghauth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ghauth/-/ghauth-2.0.1.tgz", + "integrity": "sha1-ebfWiwvPjn0IUqI7FHU539MUrPY=", + "requires": { + "bl": "~0.9.4", + "hyperquest": "~1.2.0", + "mkdirp": "~0.5.0", + "read": "~1.0.5", + "xtend": "~4.0.0" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "~1.0.26" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "github-url-from-git": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-url-from-git/-/github-url-from-git-1.5.0.tgz", + "integrity": "sha1-+YX+3MCpqledyI16/waNVcxiUaA=" + }, + "github-url-from-username-repo": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/github-url-from-username-repo/-/github-url-from-username-repo-1.0.2.tgz", + "integrity": "sha1-fdeTMNKr5pwQws73lxTJchV5Hfo=" + }, + "github-url-to-object": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/github-url-to-object/-/github-url-to-object-1.6.0.tgz", + "integrity": "sha1-iR73+7+rqP7XFRCs2xtOk0apcNw=", + "requires": { + "is-url": "^1.1.0" + } + }, + "glob": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz", + "integrity": "sha1-CqI1kxpKlqwT1g/6wvuHe9btT1g=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "^2.0.0" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + }, + "globals": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-6.4.1.tgz", + "integrity": "sha1-hJgDKzttHMge68X3lpDY/in6v08=" + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=" + }, + "gonzales-pe": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.3.tgz", + "integrity": "sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw==", + "requires": { + "minimist": "1.1.x" + }, + "dependencies": { + "minimist": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz", + "integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=" + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "^5.1.0", + "har-schema": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hawk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", + "integrity": "sha1-uQuxaYByhUEdp//LjdJZhQLTtS0=", + "optional": true, + "requires": { + "boom": "0.4.x", + "cryptiles": "0.2.x", + "hoek": "0.9.x", + "sntp": "0.2.x" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=" + }, + "home-or-tmp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz", + "integrity": "sha1-S58eQIAMPlDGwn94FnavzOcfOYU=", + "requires": { + "os-tmpdir": "^1.0.1", + "user-home": "^1.1.1" + } + }, + "home-path": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/home-path/-/home-path-1.0.6.tgz", + "integrity": "sha512-wo+yjrdAtoXt43Vy92a+0IPCYViiyLAHyp0QVS4xL/tfvVz5sXIW1ubLZk3nhVkD92fQpUMKX+fzMjr5F489vw==" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=" + }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "requires": { + "domelementtype": "^1.3.0", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "http-basic": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-2.5.1.tgz", + "integrity": "sha1-jORHvbW2xXf4pj4/p4BW7Eu02/s=", + "requires": { + "caseless": "~0.11.0", + "concat-stream": "^1.4.6", + "http-response-object": "^1.0.0" + }, + "dependencies": { + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" + } + } + }, + "http-response-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-1.1.0.tgz", + "integrity": "sha1-p8TnWq6C87tJBOT0P2FWc7TVGMM=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "hyperquest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperquest/-/hyperquest-1.2.0.tgz", + "integrity": "sha1-OeH+9miI3Hzg3sbA3YFPb8iUStU=", + "requires": { + "duplexer2": "~0.0.2", + "through2": "~0.6.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "import-lazy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz", + "integrity": "sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + }, + "dependencies": { + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } + } + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.8.5.tgz", + "integrity": "sha1-29dAz2yjtzEpamPOb22WGFHzNt8=", + "requires": { + "ansi-regex": "^1.1.1", + "chalk": "^1.0.0", + "cli-width": "^1.0.1", + "figures": "^1.3.5", + "lodash": "^3.3.1", + "readline2": "^0.1.1", + "rx": "^2.4.3", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=" + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "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-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-alphabetical": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.2.tgz", + "integrity": "sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg==" + }, + "is-alphanumeric": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz", + "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=" + }, + "is-alphanumerical": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz", + "integrity": "sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg==", + "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=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-decimal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.2.tgz", + "integrity": "sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg==" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "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", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-hexadecimal": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz", + "integrity": "sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A==" + }, + "is-integer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-integer/-/is-integer-1.0.7.tgz", + "integrity": "sha1-a96Bqs3feLZZtmKdYpytxRqIbVw=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==" + }, + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-supported-regexp-flag": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz", + "integrity": "sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-whitespace-character": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", + "integrity": "sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ==" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-word-character": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.2.tgz", + "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-0.1.9.tgz", + "integrity": "sha1-Fe7ONcSrcI2JJNqZ+4dPK1zAtsQ=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jju": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.3.0.tgz", + "integrity": "sha1-2t2e8BkkvHKLA/L3l5vb1i96Kqo=" + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "joanna": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/joanna/-/joanna-0.0.10.tgz", + "integrity": "sha512-V0b0S+7yFBesai5c+F1jGt3cWDLRVFkn8q4T6fcEzY5/7Wa+A9N4sl/cqdpr7vQ7IAThOT0baC5n3NNxY8gXjg==", + "requires": { + "babylon": "^6.8.4", + "tello": "^1.0.6", + "walkdir": ">= 0.0.2" + }, + "dependencies": { + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + } + } + }, + "js-base64": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.6.tgz", + "integrity": "sha512-O9SR2NVICx6rCqh1qsU91QZ5IoNa+2T1ROJ0OQlfvATKGmnjsAvg3r0E5ufPZ4a95jdKTPXhFWiE/sOZ7a5Rtg==" + }, + "js-tokens": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.1.tgz", + "integrity": "sha1-zENaXIuUrRWst5gxQPyAGCyJrq4=" + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + }, + "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==" + }, + "json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "requires": { + "jju": "^1.1.0" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "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=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + }, + "json5": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", + "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jsx-ast-utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", + "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "klaw-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-1.1.2.tgz", + "integrity": "sha1-tbxnokTiYbDqcdl+WG6gUh5zSpo=", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^2.3.11" + } + }, + "known-css-properties": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.6.1.tgz", + "integrity": "sha512-nQRpMcHm1cQ6gmztdvLcIvxocznSMqH/y6XtERrWrHaymOYdDGroRqetJvJycxGEr1aakXiigDgn7JnzuXlk6A==" + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lazystream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-0.1.0.tgz", + "integrity": "sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA=", + "requires": { + "readable-stream": "~1.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "legal-eagle": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/legal-eagle/-/legal-eagle-0.14.0.tgz", + "integrity": "sha1-ITk4bWO9NdZY03hBYMgL1aHbSD4=", + "requires": { + "read-installed": "3.1.3", + "underscore": "~1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "level-codec": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.0.tgz", + "integrity": "sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg==" + }, + "level-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.0.tgz", + "integrity": "sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg==", + "requires": { + "errno": "~0.1.1" + } + }, + "level-iterator-stream": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", + "integrity": "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.5", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "leveldown": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-4.0.1.tgz", + "integrity": "sha512-ZlBKVSsglPIPJnz4ggB8o2R0bxDxbsMzuQohbfgoFMVApyTE118DK5LNRG0cRju6rt3OkGxe0V6UYACGlq/byg==", + "requires": { + "abstract-leveldown": "~5.0.0", + "bindings": "~1.3.0", + "fast-future": "~1.0.2", + "nan": "~2.10.0", + "prebuild-install": "^4.0.0" + } + }, + "levelup": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-3.0.1.tgz", + "integrity": "sha512-TrrLDPC/BfP35ei2uK+L6Cc7kpI1NxIChwp+BUB6jrHG3A8gtrr9jx1UZ9bi2w1O6VN7jYO4LUoq1iKRP5AREg==", + "requires": { + "deferred-leveldown": "~4.0.0", + "level-errors": "~2.0.0", + "level-iterator-stream": "~2.0.0", + "xtend": "~4.0.0" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "leven": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/leven/-/leven-1.0.2.tgz", + "integrity": "sha1-kUS27ryl8dBoAWnxpncNzqYLdcM=" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=" + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash._shimkeys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", + "requires": { + "lodash._objecttypes": "~2.4.1" + } + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "requires": { + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } + }, + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", + "requires": { + "lodash._objecttypes": "~2.4.1", + "lodash.keys": "~2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "requires": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" + } + } + } + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "requires": { + "lodash._objecttypes": "~2.4.1" + } + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha1-lDbjTtJgk+1/+uGTYUQ1CRXZrdg=" + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "^2.0.1" + }, + "dependencies": { + "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==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "longest-streak": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.2.tgz", + "integrity": "sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA==" + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-escapes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.2.tgz", + "integrity": "sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA==" + }, + "markdown-table": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.2.tgz", + "integrity": "sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw==" + }, + "marked": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + }, + "mathml-tag-names": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz", + "integrity": "sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg==" + }, + "mdast-util-compact": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz", + "integrity": "sha1-zbX4TitqLTEU3zO9BdnLMuPECDo=", + "requires": { + "unist-util-modify-children": "^1.0.0", + "unist-util-visit": "^1.1.0" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "merge2": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", + "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==" + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "~1.33.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "minidump": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/minidump/-/minidump-0.9.0.tgz", + "integrity": "sha1-Ei6d8kTzCPNEnvunpOLDIfQmwfk=" + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "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" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "mkpath": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz", + "integrity": "sha1-dVSm+Nhxg0zJe1RisSLEwSTW3pE=" + }, + "mksnapshot": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/mksnapshot/-/mksnapshot-0.3.1.tgz", + "integrity": "sha1-JQHAVldDbXQs6Vik/5LHfkDdN+Y=", + "requires": { + "decompress-zip": "0.3.0", + "fs-extra": "0.26.7", + "request": "^2.79.0" + }, + "dependencies": { + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + } + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "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" + } + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "requires": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "requires": { + "glob": "^6.0.1" + } + } + } + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "natives": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", + "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "node-abi": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.3.tgz", + "integrity": "sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg==", + "requires": { + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + } + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz", + "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + }, + "normalize-selector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", + "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=" + }, + "npm": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.2.0.tgz", + "integrity": "sha512-GnlNsOnxwVJX4WSfyQY0gY3LnUX2cc46XU0eu1g+WSuZgDRUGmw8tuptitJu6byp0RWGT8ZEAKajblwdhQHN8A==", + "requires": { + "JSONStream": "^1.3.3", + "abbrev": "~1.1.1", + "ansicolors": "~0.3.2", + "ansistyles": "~0.1.3", + "aproba": "~1.2.0", + "archy": "~1.0.0", + "bin-links": "^1.1.2", + "bluebird": "~3.5.1", + "byte-size": "^4.0.3", + "cacache": "^11.0.2", + "call-limit": "~1.1.0", + "chownr": "~1.0.1", + "cli-columns": "^3.1.2", + "cli-table3": "^0.5.0", + "cmd-shim": "~2.0.2", + "columnify": "~1.5.4", + "config-chain": "~1.1.11", + "debuglog": "*", + "detect-indent": "~5.0.0", + "detect-newline": "^2.1.0", + "dezalgo": "~1.0.3", + "editor": "~1.0.0", + "figgy-pudding": "^3.1.0", + "find-npm-prefix": "^1.0.2", + "fs-vacuum": "~1.2.10", + "fs-write-stream-atomic": "~1.0.10", + "gentle-fs": "^2.0.1", + "glob": "~7.1.2", + "graceful-fs": "~4.1.11", + "has-unicode": "~2.0.1", + "hosted-git-info": "^2.6.0", + "iferr": "^1.0.0", + "imurmurhash": "*", + "inflight": "~1.0.6", + "inherits": "~2.0.3", + "ini": "^1.3.5", + "init-package-json": "^1.10.3", + "is-cidr": "^2.0.6", + "json-parse-better-errors": "^1.0.2", + "lazy-property": "~1.0.0", + "libcipm": "^2.0.0", + "libnpmhook": "^4.0.1", + "libnpx": "^10.2.0", + "lock-verify": "^2.0.2", + "lockfile": "^1.0.4", + "lodash._baseindexof": "*", + "lodash._baseuniq": "~4.6.0", + "lodash._bindcallback": "*", + "lodash._cacheindexof": "*", + "lodash._createcache": "*", + "lodash._getnative": "*", + "lodash.clonedeep": "~4.5.0", + "lodash.restparam": "*", + "lodash.union": "~4.6.0", + "lodash.uniq": "~4.5.0", + "lodash.without": "~4.4.0", + "lru-cache": "^4.1.3", + "meant": "~1.0.1", + "mississippi": "^3.0.0", + "mkdirp": "~0.5.1", + "move-concurrently": "^1.0.1", + "node-gyp": "^3.7.0", + "nopt": "~4.0.1", + "normalize-package-data": "~2.4.0", + "npm-audit-report": "^1.3.1", + "npm-cache-filename": "~1.0.2", + "npm-install-checks": "~3.0.0", + "npm-lifecycle": "^2.0.3", + "npm-package-arg": "^6.1.0", + "npm-packlist": "~1.1.10", + "npm-pick-manifest": "^2.1.0", + "npm-profile": "^3.0.2", + "npm-registry-client": "^8.5.1", + "npm-registry-fetch": "^1.1.0", + "npm-user-validate": "~1.0.0", + "npmlog": "~4.1.2", + "once": "~1.4.0", + "opener": "~1.4.3", + "osenv": "^0.1.5", + "pacote": "^8.1.6", + "path-is-inside": "~1.0.2", + "promise-inflight": "~1.0.1", + "qrcode-terminal": "^0.12.0", + "query-string": "^6.1.0", + "qw": "~1.0.1", + "read": "~1.0.7", + "read-cmd-shim": "~1.0.1", + "read-installed": "~4.0.3", + "read-package-json": "^2.0.13", + "read-package-tree": "^5.2.1", + "readable-stream": "^2.3.6", + "readdir-scoped-modules": "*", + "request": "^2.81.0", + "retry": "^0.12.0", + "rimraf": "~2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.5.0", + "sha": "~2.0.1", + "slide": "~1.1.6", + "sorted-object": "~2.0.1", + "sorted-union-stream": "~2.1.3", + "ssri": "^6.0.0", + "tar": "^4.4.4", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "uid-number": "0.0.6", + "umask": "~1.1.0", + "unique-filename": "~1.1.0", + "unpipe": "~1.0.0", + "update-notifier": "^2.5.0", + "uuid": "^3.3.2", + "validate-npm-package-license": "^3.0.3", + "validate-npm-package-name": "~3.0.0", + "which": "^1.3.1", + "worker-farm": "^1.6.0", + "wrappy": "~1.0.2", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "JSONStream": { + "version": "1.3.3", + "bundled": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "agent-base": { + "version": "4.2.0", + "bundled": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.4.1", + "bundled": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "ansi-align": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.0.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansicolors": { + "version": "0.3.2", + "bundled": true + }, + "ansistyles": { + "version": "0.1.3", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "asap": { + "version": "2.0.6", + "bundled": true + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.7.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bin-links": { + "version": "1.1.2", + "bundled": true, + "requires": { + "bluebird": "^3.5.0", + "cmd-shim": "^2.0.2", + "gentle-fs": "^2.0.0", + "graceful-fs": "^4.1.11", + "write-file-atomic": "^2.3.0" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.5.1", + "bundled": true + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.x.x" + } + }, + "boxen": { + "version": "1.3.0", + "bundled": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.0.0", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "builtins": { + "version": "1.0.3", + "bundled": true + }, + "byline": { + "version": "5.0.0", + "bundled": true + }, + "byte-size": { + "version": "4.0.3", + "bundled": true + }, + "cacache": { + "version": "11.0.2", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "figgy-pudding": "^3.1.0", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.0", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "call-limit": { + "version": "1.1.0", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.1", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true + }, + "ci-info": { + "version": "1.1.3", + "bundled": true + }, + "cidr-regex": { + "version": "2.0.9", + "bundled": true, + "requires": { + "ip-regex": "^2.1.0" + } + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, + "cli-columns": { + "version": "3.1.2", + "bundled": true, + "requires": { + "string-width": "^2.0.0", + "strip-ansi": "^3.0.1" + } + }, + "cli-table3": { + "version": "0.5.0", + "bundled": true, + "requires": { + "colors": "^1.1.2", + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + } + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "bundled": true + }, + "cmd-shim": { + "version": "2.0.2", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "mkdirp": "~0.5.0" + } + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "^1.1.1" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.0", + "bundled": true, + "optional": true + }, + "columnify": { + "version": "1.5.4", + "bundled": true, + "requires": { + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" + } + }, + "combined-stream": { + "version": "1.0.6", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "concat-stream": { + "version": "1.6.2", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "bundled": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "configstore": { + "version": "3.1.2", + "bundled": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "copy-concurrently": { + "version": "1.0.5", + "bundled": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.x.x" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + }, + "cyclist": { + "version": "0.2.2", + "bundled": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "bundled": true + } + } + }, + "debuglog": { + "version": "1.0.1", + "bundled": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "requires": { + "clone": "^1.0.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "dezalgo": { + "version": "1.0.3", + "bundled": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "bundled": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "dotenv": { + "version": "5.0.1", + "bundled": true + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "duplexify": { + "version": "3.6.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } + }, + "editor": { + "version": "1.0.0", + "bundled": true + }, + "encoding": { + "version": "0.1.12", + "bundled": true, + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "err-code": { + "version": "1.1.2", + "bundled": true + }, + "errno": { + "version": "0.1.7", + "bundled": true, + "requires": { + "prr": "~1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "bundled": true + }, + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "figgy-pudding": { + "version": "3.1.0", + "bundled": true + }, + "find-npm-prefix": { + "version": "1.0.2", + "bundled": true + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "from2": { + "version": "2.3.0", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs-vacuum": { + "version": "1.2.10", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "path-is-inside": "^1.0.1", + "rimraf": "^2.5.2" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "genfun": { + "version": "4.0.1", + "bundled": true + }, + "gentle-fs": { + "version": "2.0.1", + "bundled": true, + "requires": { + "aproba": "^1.1.2", + "fs-vacuum": "^1.2.10", + "graceful-fs": "^4.1.11", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "path-is-inside": "^1.0.2", + "read-cmd-shim": "^1.0.1", + "slide": "^1.1.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": 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" + } + }, + "global-dirs": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ini": "^1.3.4" + } + }, + "got": { + "version": "6.7.1", + "bundled": true, + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "hosted-git-info": { + "version": "2.6.0", + "bundled": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "bundled": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "bundled": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "bundled": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "iferr": { + "version": "1.0.0", + "bundled": true + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", + "bundled": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "init-package-json": { + "version": "1.10.3", + "bundled": true, + "requires": { + "glob": "^7.1.1", + "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "1 || 2", + "semver": "2.x || 3.x || 4 || 5", + "validate-npm-package-license": "^3.0.1", + "validate-npm-package-name": "^3.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "ip": { + "version": "1.1.5", + "bundled": true + }, + "ip-regex": { + "version": "2.1.0", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-ci": { + "version": "1.1.0", + "bundled": true, + "requires": { + "ci-info": "^1.0.0" + } + }, + "is-cidr": { + "version": "2.0.6", + "bundled": true, + "requires": { + "cidr-regex": "^2.0.8" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "bundled": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "is-obj": { + "version": "1.0.1", + "bundled": true + }, + "is-path-inside": { + "version": "1.0.1", + "bundled": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "bundled": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "latest-version": { + "version": "3.1.0", + "bundled": true, + "requires": { + "package-json": "^4.0.0" + } + }, + "lazy-property": { + "version": "1.0.0", + "bundled": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "libcipm": { + "version": "2.0.0", + "bundled": true, + "requires": { + "bin-links": "^1.1.2", + "bluebird": "^3.5.1", + "find-npm-prefix": "^1.0.2", + "graceful-fs": "^4.1.11", + "lock-verify": "^2.0.2", + "npm-lifecycle": "^2.0.3", + "npm-logical-tree": "^1.2.1", + "npm-package-arg": "^6.1.0", + "pacote": "^8.1.6", + "protoduck": "^5.0.0", + "read-package-json": "^2.0.13", + "rimraf": "^2.6.2", + "worker-farm": "^1.6.0" + } + }, + "libnpmhook": { + "version": "4.0.1", + "bundled": true, + "requires": { + "figgy-pudding": "^3.1.0", + "npm-registry-fetch": "^3.0.0" + }, + "dependencies": { + "npm-registry-fetch": { + "version": "3.1.1", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^3.1.0", + "lru-cache": "^4.1.2", + "make-fetch-happen": "^4.0.0", + "npm-package-arg": "^6.0.0" + } + } + } + }, + "libnpx": { + "version": "10.2.0", + "bundled": true, + "requires": { + "dotenv": "^5.0.1", + "npm-package-arg": "^6.0.0", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.0", + "update-notifier": "^2.3.0", + "which": "^1.3.0", + "y18n": "^4.0.0", + "yargs": "^11.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lock-verify": { + "version": "2.0.2", + "bundled": true, + "requires": { + "npm-package-arg": "^5.1.2 || 6", + "semver": "^5.4.1" + } + }, + "lockfile": { + "version": "1.0.4", + "bundled": true, + "requires": { + "signal-exit": "^3.0.2" + } + }, + "lodash._baseindexof": { + "version": "3.1.0", + "bundled": true + }, + "lodash._baseuniq": { + "version": "4.6.0", + "bundled": true, + "requires": { + "lodash._createset": "~4.0.0", + "lodash._root": "~3.0.0" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "bundled": true + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "bundled": true + }, + "lodash._createcache": { + "version": "3.1.2", + "bundled": true, + "requires": { + "lodash._getnative": "^3.0.0" + } + }, + "lodash._createset": { + "version": "4.0.3", + "bundled": true + }, + "lodash._getnative": { + "version": "3.9.1", + "bundled": true + }, + "lodash._root": { + "version": "3.0.1", + "bundled": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "bundled": true + }, + "lodash.restparam": { + "version": "3.6.1", + "bundled": true + }, + "lodash.union": { + "version": "4.6.0", + "bundled": true + }, + "lodash.uniq": { + "version": "4.5.0", + "bundled": true + }, + "lodash.without": { + "version": "4.4.0", + "bundled": true + }, + "lowercase-keys": { + "version": "1.0.1", + "bundled": true + }, + "lru-cache": { + "version": "4.1.3", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "bundled": true, + "requires": { + "pify": "^3.0.0" + } + }, + "make-fetch-happen": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^11.0.1", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + } + }, + "meant": { + "version": "1.0.1", + "bundled": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mime-db": { + "version": "1.33.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.18", + "bundled": true, + "requires": { + "mime-db": "~1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.3", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mississippi": { + "version": "3.0.0", + "bundled": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "bundled": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "mute-stream": { + "version": "0.0.7", + "bundled": true + }, + "node-fetch-npm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-gyp": { + "version": "3.7.0", + "bundled": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": ">=2.9.0 <2.82.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + } + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-audit-report": { + "version": "1.3.1", + "bundled": true, + "requires": { + "cli-table3": "^0.5.0", + "console-control-strings": "^1.1.0" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true + }, + "npm-cache-filename": { + "version": "1.0.2", + "bundled": true + }, + "npm-install-checks": { + "version": "3.0.0", + "bundled": true, + "requires": { + "semver": "^2.3.0 || 3.x || 4 || 5" + } + }, + "npm-lifecycle": { + "version": "2.0.3", + "bundled": true, + "requires": { + "byline": "^5.0.0", + "graceful-fs": "^4.1.11", + "node-gyp": "^3.6.2", + "resolve-from": "^4.0.0", + "slide": "^1.1.6", + "uid-number": "0.0.6", + "umask": "^1.1.0", + "which": "^1.3.0" + } + }, + "npm-logical-tree": { + "version": "1.2.1", + "bundled": true + }, + "npm-package-arg": { + "version": "6.1.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.6.0", + "osenv": "^0.1.5", + "semver": "^5.5.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "2.1.0", + "bundled": true, + "requires": { + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, + "npm-profile": { + "version": "3.0.2", + "bundled": true, + "requires": { + "aproba": "^1.1.2 || 2", + "make-fetch-happen": "^2.5.0 || 3 || 4" + } + }, + "npm-registry-client": { + "version": "8.5.1", + "bundled": true, + "requires": { + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", + "npmlog": "2 || ^3.1.0 || ^4.0.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "safe-buffer": "^5.1.1", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3", + "ssri": "^5.2.4" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.1" + } + } + } + }, + "npm-registry-fetch": { + "version": "1.1.0", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "figgy-pudding": "^2.0.1", + "lru-cache": "^4.1.2", + "make-fetch-happen": "^3.0.0", + "npm-package-arg": "^6.0.0", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "cacache": { + "version": "10.0.4", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + }, + "dependencies": { + "mississippi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + } + } + }, + "figgy-pudding": { + "version": "2.0.1", + "bundled": true + }, + "make-fetch-happen": { + "version": "3.0.0", + "bundled": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^10.0.4", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.0", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^3.0.1", + "ssri": "^5.2.4" + } + }, + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "smart-buffer": { + "version": "1.1.15", + "bundled": true + }, + "socks": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ip": "^1.1.4", + "smart-buffer": "^1.0.13" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "bundled": true, + "requires": { + "agent-base": "^4.1.0", + "socks": "^1.1.10" + } + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.1" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-user-validate": { + "version": "1.0.0", + "bundled": true + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.4.3", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "package-json": { + "version": "4.0.1", + "bundled": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "pacote": { + "version": "8.1.6", + "bundled": true, + "requires": { + "bluebird": "^3.5.1", + "cacache": "^11.0.2", + "get-stream": "^3.0.0", + "glob": "^7.1.2", + "lru-cache": "^4.1.3", + "make-fetch-happen": "^4.0.1", + "minimatch": "^3.0.4", + "minipass": "^2.3.3", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.10", + "npm-pick-manifest": "^2.1.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.0", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.5.0", + "ssri": "^6.0.0", + "tar": "^4.4.3", + "unique-filename": "^1.1.0", + "which": "^1.3.0" + } + }, + "parallel-transform": { + "version": "1.1.0", + "bundled": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-is-inside": { + "version": "1.0.2", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "pify": { + "version": "3.0.0", + "bundled": true + }, + "prepend-http": { + "version": "1.0.4", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true + }, + "promise-retry": { + "version": "1.1.1", + "bundled": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + } + } + }, + "promzard": { + "version": "0.3.0", + "bundled": true, + "requires": { + "read": "1" + } + }, + "proto-list": { + "version": "1.2.4", + "bundled": true + }, + "protoduck": { + "version": "5.0.0", + "bundled": true, + "requires": { + "genfun": "^4.0.1" + } + }, + "prr": { + "version": "1.0.1", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "bundled": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "query-string": { + "version": "6.1.0", + "bundled": true, + "requires": { + "decode-uri-component": "^0.2.0", + "strict-uri-encode": "^2.0.0" + } + }, + "qw": { + "version": "1.0.1", + "bundled": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "read": { + "version": "1.0.7", + "bundled": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2" + } + }, + "read-installed": { + "version": "4.0.3", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "^4.1.2", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + } + }, + "read-package-json": { + "version": "2.0.13", + "bundled": true, + "requires": { + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "json-parse-better-errors": "^1.0.1", + "normalize-package-data": "^2.0.0", + "slash": "^1.0.0" + } + }, + "read-package-tree": { + "version": "5.2.1", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "once": "^1.3.0", + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "bundled": true, + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "bundled": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "requires": { + "rc": "^1.0.1" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve-from": { + "version": "4.0.0", + "bundled": true + }, + "retry": { + "version": "0.12.0", + "bundled": true + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + }, + "run-queue": { + "version": "1.0.3", + "bundled": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "semver-diff": { + "version": "2.1.0", + "bundled": true, + "requires": { + "semver": "^5.0.3" + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "sha": { + "version": "2.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "readable-stream": "^2.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "slash": { + "version": "1.0.0", + "bundled": true + }, + "slide": { + "version": "1.1.6", + "bundled": true + }, + "smart-buffer": { + "version": "4.0.1", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.x.x" + } + }, + "socks": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + } + }, + "sorted-object": { + "version": "2.0.1", + "bundled": true + }, + "sorted-union-stream": { + "version": "2.1.3", + "bundled": true, + "requires": { + "from2": "^1.3.0", + "stream-iterate": "^1.1.0" + }, + "dependencies": { + "from2": { + "version": "1.3.0", + "bundled": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~1.1.10" + } + }, + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.1.14", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + }, + "sshpk": { + "version": "1.14.2", + "bundled": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "ssri": { + "version": "6.0.0", + "bundled": true + }, + "stream-each": { + "version": "1.2.2", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-iterate": { + "version": "1.2.0", + "bundled": true, + "requires": { + "readable-stream": "^2.1.5", + "stream-shift": "^1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "bundled": true + }, + "strict-uri-encode": { + "version": "2.0.0", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringstream": { + "version": "0.0.6", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "supports-color": { + "version": "5.4.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tar": { + "version": "4.4.4", + "bundled": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.3", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "term-size": { + "version": "1.2.0", + "bundled": true, + "requires": { + "execa": "^0.7.0" + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true + }, + "through": { + "version": "2.3.8", + "bundled": true + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.3.4", + "bundled": true, + "requires": { + "punycode": "^1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "bundled": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "umask": { + "version": "1.1.0", + "bundled": true + }, + "unique-filename": { + "version": "1.1.0", + "bundled": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "bundled": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "bundled": true + }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, + "update-notifier": { + "version": "2.5.0", + "bundled": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "util-extend": { + "version": "1.0.3", + "bundled": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "bundled": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "^1.0.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1" + } + }, + "worker-farm": { + "version": "1.6.0", + "bundled": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.3.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "11.0.0", + "bundled": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + }, + "dependencies": { + "y18n": { + "version": "3.2.1", + "bundled": true + } + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", + "requires": { + "path-key": "^1.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nugget": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", + "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", + "requires": { + "debug": "^2.1.3", + "minimist": "^1.1.0", + "pretty-bytes": "^1.0.2", + "progress-stream": "^1.1.0", + "request": "^2.45.0", + "single-line-log": "^1.1.2", + "throttleit": "0.0.2" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, + "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=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + } + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://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=" + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "parse-entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.1.2.tgz", + "integrity": "sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg==", + "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-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "passwd-user": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/passwd-user/-/passwd-user-2.1.0.tgz", + "integrity": "sha1-+tnbauJS+LCI4MXezSCn2gxdnx4=", + "requires": { + "execa": "^0.4.0", + "pify": "^2.3.0" + } + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-exists": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=" + }, + "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-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pegjs": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.9.0.tgz", + "integrity": "sha1-9q76LjzlYWkgjlIXnf5B+JFBo2k=" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", + "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", + "requires": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=" + }, + "plist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz", + "integrity": "sha1-CEtQk93JJQbiWfh0uNmxr7jHlZM=", + "requires": { + "base64-js": "0.0.8", + "util-deprecate": "1.0.2", + "xmlbuilder": "4.0.0", + "xmldom": "0.1.x" + }, + "dependencies": { + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "xmlbuilder": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.0.0.tgz", + "integrity": "sha1-mLj2UcowqmJANvEn0RzGbce5B6M=", + "requires": { + "lodash": "^3.5.0" + } + } + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, + "dependencies": { + "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==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-html": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.28.0.tgz", + "integrity": "sha512-H+ucbGVR+lsZySspOApeQU9yC6Q3t75lwJYa3Im93fKAUt5DScKOSErShC0aC7USdn2jsT1LxubcC5vYu/VJYw==", + "requires": { + "htmlparser2": "^3.9.2" + } + }, + "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==", + "requires": { + "postcss": "^5.2.16" + }, + "dependencies": { + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "postcss-markdown": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/postcss-markdown/-/postcss-markdown-0.28.0.tgz", + "integrity": "sha512-F0Vc8eHKDKTmensntXpd35LSAoXXtykhPY+IRfn4AnN4m+irav3QawmtSWLhsmbElKna8l1/HObYnbiM/Wok9Q==", + "requires": { + "remark": "^9.0.0", + "unist-util-find-all-after": "^1.0.2" + } + }, + "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=" + }, + "postcss-reporter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", + "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", + "requires": { + "chalk": "^2.0.1", + "lodash": "^4.17.4", + "log-symbols": "^2.0.0", + "postcss": "^6.0.8" + }, + "dependencies": { + "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==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=" + }, + "postcss-safe-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-3.0.1.tgz", + "integrity": "sha1-t1Pv9sfArqXoN1++TN6L+QY/8UI=", + "requires": { + "postcss": "^6.0.6" + } + }, + "postcss-sass": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.3.2.tgz", + "integrity": "sha512-0HgxikiZ07VKYr98KT+k7/rAzyMgZlP+3+R8vUti56T2dPdhW0OhPGDQzddxY/N2iDtBVZQqCHRDA09j5I6EWg==", + "requires": { + "gonzales-pe": "4.2.3", + "postcss": "6.0.22" + }, + "dependencies": { + "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==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "postcss": { + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", + "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-scss": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-1.0.6.tgz", + "integrity": "sha512-4EFYGHcEw+H3E06PT/pQQri06u/1VIIPjeJQaM8skB80vZuXMhp4cSNV5azmdNkontnOID/XYWEvEEELLFB1ww==", + "requires": { + "postcss": "^6.0.23" + } + }, + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-syntax": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.28.0.tgz", + "integrity": "sha512-9W3T1fSE9QWKyW6s84kZapv0BP5uvj7mNBp34kwI93uGWULzZjaKv4xR4phubBD53cRgaM/qnvquVK1KLsl+Kg==" + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=" + }, + "pragma-singleton": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pragma-singleton/-/pragma-singleton-1.0.3.tgz", + "integrity": "sha1-aJQxe7jUcVflneKkoAnbfm9j4w4=" + }, + "prebuild-install": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-4.0.0.tgz", + "integrity": "sha512-7tayxeYboJX0RbVzdnKyGl2vhQRWr6qfClEXDhOkXjuaOKCw2q8aiuFhONRYVsG/czia7KhpykIlI2S2VaPunA==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^1.0.2", + "github-from-package": "0.0.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "node-abi": "^2.2.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "os-homedir": "^1.0.1", + "pump": "^2.0.1", + "rc": "^1.1.6", + "simple-get": "^2.7.0", + "tar-fs": "^1.13.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.1.0" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=" + }, + "progress-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", + "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", + "requires": { + "speedometer": "~0.1.2", + "through2": "~0.2.3" + } + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "publish-release": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/publish-release/-/publish-release-1.6.0.tgz", + "integrity": "sha512-t+NFXTQN/VDTg9yJ8Uv5ZWQ7Ud1T5W1tPW+bmuo4g6uYVQTVNiwwRF6Td3EtXFTOafpEXJQEZqGG7IvIJwLwIg==", + "requires": { + "async": "^0.9.0", + "ghauth": "^2.0.0", + "github-url-to-object": "^1.4.2", + "inquirer": "^0.8.2", + "lodash": "^3.6.0", + "mime": "^1.3.4", + "minimist": "^1.1.1", + "pkginfo": "^0.3.0", + "pretty-bytes": "^1.0.4", + "progress-stream": "^1.0.1", + "request": "^2.54.0", + "single-line-log": "^0.4.1", + "string-editor": "^0.1.0" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "single-line-log": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-0.4.1.tgz", + "integrity": "sha1-h6VWSfdJ14PsDc2AToFA2Yc8fO4=" + } + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "queue": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-1.0.2.tgz", + "integrity": "sha1-LZr55hyaGuRVem842FtTTq/yBYE=" + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=" + }, + "random-seed": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/random-seed/-/random-seed-0.3.0.tgz", + "integrity": "sha1-2UXy4fOPSejViRNDG4v2u5N1Vs0=", + "requires": { + "json-stringify-safe": "^5.0.1" + } + }, + "randomatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", + "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + } + } + }, + "rcedit": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-0.5.1.tgz", + "integrity": "sha1-0L3PXSgKnRwp2m8RjMzizhU87x0=" + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-installed": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-3.1.3.tgz", + "integrity": "sha1-wJCSoTwhF/IoQsrRaATzsFkSnRE=", + "requires": { + "debuglog": "^1.0.1", + "graceful-fs": "2 || 3", + "read-package-json": "1", + "readdir-scoped-modules": "^1.0.0", + "semver": "2 || 3 || 4", + "slide": "~1.1.3", + "util-extend": "^1.0.1" + }, + "dependencies": { + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "optional": true, + "requires": { + "natives": "^1.1.0" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + } + } + }, + "read-package-json": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-1.3.3.tgz", + "integrity": "sha1-73nf2kbhZTdu6KV++/7dTRsCm6Q=", + "requires": { + "glob": "^5.0.3", + "graceful-fs": "2 || 3", + "json-parse-helpfulerror": "^1.0.2", + "normalize-package-data": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "optional": true, + "requires": { + "natives": "^1.1.0" + } + }, + "normalize-package-data": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-1.0.3.tgz", + "integrity": "sha1-i+lVuJB6+XXxpFhOqLubQUkjEvU=", + "requires": { + "github-url-from-git": "^1.3.0", + "github-url-from-username-repo": "^1.0.0", + "semver": "2 || 3 || 4" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz", + "integrity": "sha1-n6+jfShr5dksuuve4DDcm19AZ0c=", + "requires": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "readline2": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-0.1.1.tgz", + "integrity": "sha1-mUQ7pug7gw7zBRv9fcJBqCco1Wg=", + "requires": { + "mute-stream": "0.0.4", + "strip-ansi": "^2.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz", + "integrity": "sha1-QchHGUZGN15qGl0Qw8oFTvn8mA0=" + }, + "mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha1-qSGZYKbV1dBGWXruUSUsZlX3F34=" + }, + "strip-ansi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-2.0.1.tgz", + "integrity": "sha1-32LBqpTtLxFOHQ8h/R1QSCt5pg4=", + "requires": { + "ansi-regex": "^1.0.0" + } + } + } + }, + "recast": { + "version": "0.10.33", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.10.33.tgz", + "integrity": "sha1-lCgI96oBbx+nFCxGHX5XBKqo1pc=", + "requires": { + "ast-types": "0.8.12", + "esprima-fb": "~15001.1001.0-dev-harmony-fb", + "private": "~0.1.5", + "source-map": "~0.5.0" + }, + "dependencies": { + "ast-types": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.12.tgz", + "integrity": "sha1-oNkOQ1G7iHcWyD/WN+v4GK9K38w=" + } + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerator": { + "version": "0.8.40", + "resolved": "https://registry.npmjs.org/regenerator/-/regenerator-0.8.40.tgz", + "integrity": "sha1-oORXxY69uuV1yfjNdRJ+k3VkNdg=", + "requires": { + "commoner": "~0.10.3", + "defs": "~1.1.0", + "esprima-fb": "~15001.1001.0-dev-harmony-fb", + "private": "~0.1.5", + "recast": "0.10.33", + "through": "~2.3.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexpu/-/regexpu-1.3.0.tgz", + "integrity": "sha1-5TTcmRqeWEYFDJjebX3UpVyeoW0=", + "requires": { + "esprima": "^2.6.0", + "recast": "^0.10.10", + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + } + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "~0.5.0" + } + }, + "remark": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", + "integrity": "sha512-amw8rGdD5lHbMEakiEsllmkdBP+/KpjW/PRK6NSGPZKCQowh0BT4IWXDAkRMyG3SB9dKPXWMviFjNusXzXNn3A==", + "requires": { + "remark-parse": "^5.0.0", + "remark-stringify": "^5.0.0", + "unified": "^6.0.0" + } + }, + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "requires": { + "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" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "remark-stringify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-5.0.0.tgz", + "integrity": "sha512-Ws5MdA69ftqQ/yhRF9XhVV29mhxbfGhbz0Rx5bQH+oJcNhhSM6nCu1EpLod+DjrFGrU0BMPs+czVmJZU7xiS7w==", + "requires": { + "ccount": "^1.0.0", + "is-alphanumeric": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "longest-streak": "^2.0.1", + "markdown-escapes": "^1.0.0", + "markdown-table": "^1.1.0", + "mdast-util-compact": "^1.0.0", + "parse-entities": "^1.0.2", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "stringify-entities": "^1.0.1", + "unherit": "^1.0.4", + "xtend": "^4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rgb2hex": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.1.8.tgz", + "integrity": "sha512-kPH3Zm3UrBIfJv17AtJJGLRxak+Hvvz6SnsTBIajqB2Zbh+A4EEjkMWKkmGhms0cJlzOOjZcu1LX5K3vnON7ug==" + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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" + } + }, + "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" + } + } + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "requires": { + "once": "^1.3.0" + } + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" + }, + "run-series": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.8.tgz", + "integrity": "sha512-+GztYEPRpIsQoCSraWHDBs9WVy4eVME16zhOtDB4H9J4xN0XRhknnmLOl+4gRgZtu8dpp9N/utSPjKH/xmDzXg==" + }, + "rx": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/rx/-/rx-2.5.3.tgz", + "integrity": "sha1-Ia3H2A8CACr1Da6X/Z2/JIdV9WY=" + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "season": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/season/-/season-5.3.0.tgz", + "integrity": "sha1-KC05fmQW9EkjKHvVVFCtCAuV22U=", + "requires": { + "cson-parser": "1.0.9", + "fs-plus": "2.x", + "optimist": "~0.4.0" + }, + "dependencies": { + "optimist": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.4.0.tgz", + "integrity": "sha1-y47Dfy/jqphky2eidSUOfhliCiU=", + "requires": { + "wordwrap": "~0.0.2" + } + } + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz", + "integrity": "sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg=" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-fmt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz", + "integrity": "sha1-GRv1ZqWeZTBILLJatTtKjchcOms=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "simple-is": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz", + "integrity": "sha1-Krt1qt453rXMgVzhDmGRFkhQuvA=" + }, + "single-line-log": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", + "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", + "requires": { + "string-width": "^1.0.1" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + } + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "optional": true, + "requires": { + "hoek": "0.9.x" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", + "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", + "requires": { + "source-map": "0.1.32" + }, + "dependencies": { + "source-map": { + "version": "0.1.32", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", + "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + }, + "specificity": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", + "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==" + }, + "speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "standard": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/standard/-/standard-8.4.0.tgz", + "integrity": "sha1-SDNS5D+us1om6OwWOZTlE4wxtlA=", + "requires": { + "eslint": "~3.7.1", + "eslint-config-standard": "6.2.0", + "eslint-config-standard-jsx": "3.2.0", + "eslint-plugin-promise": "~3.0.0", + "eslint-plugin-react": "~6.4.1", + "eslint-plugin-standard": "~2.0.1", + "standard-engine": "~5.1.0" + } + }, + "standard-engine": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-5.1.1.tgz", + "integrity": "sha1-y3derhxQz6jnarJUVt0SKvfzR4g=", + "requires": { + "deglob": "^2.0.0", + "find-root": "^1.0.0", + "get-stdin": "^5.0.1", + "home-or-tmp": "^2.0.0", + "minimist": "^1.1.0", + "pkg-config": "^1.0.1" + }, + "dependencies": { + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=" + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + } + } + }, + "state-toggle": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.1.tgz", + "integrity": "sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og==" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "string-editor": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/string-editor/-/string-editor-0.1.2.tgz", + "integrity": "sha1-9f8bWsSu16xsL7jeI20VUbIPYdA=", + "requires": { + "editor": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "stringify-entities": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-1.3.2.tgz", + "integrity": "sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A==", + "requires": { + "character-entities-html4": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "stringmap": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz", + "integrity": "sha1-VWwTeyWPlCuHdvWy71gqoGnX0bE=" + }, + "stringset": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/stringset/-/stringset-0.2.1.tgz", + "integrity": "sha1-7yWcTjSTRDd/zRyRPdLoSMnAQrU=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "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=" + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=" + }, + "stylelint": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-9.3.0.tgz", + "integrity": "sha512-u59pWTlrdwjqriJtTvO1a0wRK1mfbQQp7jLt27SX4zl2HmtVHOM/I1wd43xHTvUJZDKp1PTOpqRAamU3gFvmOA==", + "requires": { + "autoprefixer": "^8.0.0", + "balanced-match": "^1.0.0", + "chalk": "^2.4.1", + "cosmiconfig": "^5.0.0", + "debug": "^3.0.0", + "execall": "^1.0.0", + "file-entry-cache": "^2.0.0", + "get-stdin": "^6.0.0", + "globby": "^8.0.0", + "globjoin": "^0.1.4", + "html-tags": "^2.0.0", + "ignore": "^3.3.3", + "import-lazy": "^3.1.0", + "imurmurhash": "^0.1.4", + "known-css-properties": "^0.6.0", + "lodash": "^4.17.4", + "log-symbols": "^2.0.0", + "mathml-tag-names": "^2.0.1", + "meow": "^5.0.0", + "micromatch": "^2.3.11", + "normalize-selector": "^0.2.0", + "pify": "^3.0.0", + "postcss": "^6.0.16", + "postcss-html": "^0.28.0", + "postcss-less": "^2.0.0", + "postcss-markdown": "^0.28.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-reporter": "^5.0.0", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^3.0.1", + "postcss-sass": "^0.3.0", + "postcss-scss": "^1.0.2", + "postcss-selector-parser": "^3.1.0", + "postcss-syntax": "^0.28.0", + "postcss-value-parser": "^3.3.0", + "resolve-from": "^4.0.0", + "signal-exit": "^3.0.2", + "specificity": "^0.3.1", + "string-width": "^2.1.0", + "style-search": "^0.1.0", + "sugarss": "^1.0.0", + "svg-tags": "^1.0.0", + "table": "^4.0.1" + }, + "dependencies": { + "ajv": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", + "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.1" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=" + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "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==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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": "8.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", + "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "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=" + }, + "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==" + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=" + }, + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" + } + }, + "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" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "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==" + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "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=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "requires": { + "ajv": "^6.0.1", + "ajv-keywords": "^3.0.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=" + } + } + }, + "stylelint-config-recommended": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-2.1.0.tgz", + "integrity": "sha512-ajMbivOD7JxdsnlS5945KYhvt7L/HwN6YeYF2BH6kE4UCLJR0YvXMf+2j7nQpJyYLZx9uZzU5G1ZOSBiWAc6yA==" + }, + "stylelint-config-standard": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-18.2.0.tgz", + "integrity": "sha512-07x0TaSIzvXlbOioUU4ORkCIM07kyIuojkbSVCyFWNVgXMXYHfhnQSCkqu+oHWJf3YADAnPGWzdJ53NxkoJ7RA==", + "requires": { + "stylelint-config-recommended": "^2.1.0" + } + }, + "sugarss": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-1.0.1.tgz", + "integrity": "sha512-3qgLZytikQQEVn1/FrhY7B68gPUUGY3R1Q1vTiD5xT+Ti1DP/8iZuwFet9ONs5+bmL8pZoDQ6JrQHVgrNlK6mA==", + "requires": { + "postcss": "^6.0.14" + } + }, + "sumchecker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", + "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", + "requires": { + "debug": "^2.2.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=" + }, + "sync-request": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-3.0.1.tgz", + "integrity": "sha1-yqEjWq+Im6UBB2oYNMQ2gwqC+3M=", + "requires": { + "concat-stream": "^1.4.7", + "http-response-object": "^1.0.1", + "then-request": "^2.0.1" + } + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "requires": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "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=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "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=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.1.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "tello": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tello/-/tello-1.0.7.tgz", + "integrity": "sha512-N/EvP7dLmiNQwg0NFY1igz69Fj6G8RGM2AuVSpJfDWYb831w9Ary81/jwRhgIarFDH6deK7jytHyYMo6FtHbiA==", + "requires": { + "atomdoc": "1.0.6", + "optimist": "~0.6", + "underscore": "~1.6" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "^1.0.0", + "rimraf": "~2.2.6" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "terser": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.8.1.tgz", + "integrity": "sha512-FRin3gKQ0vm0xPPLuxw1FqpVgv1b2pBpYCaFb5qe6A7sD749Fnq1VbDiX3CEFM0BV0fqDzFtBfgmxhxCdzKQIg==", + "requires": { + "commander": "~2.16.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "then-request": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-2.2.0.tgz", + "integrity": "sha1-ZnizL6DKIY/laZgbvYhxtZQGDYE=", + "requires": { + "caseless": "~0.11.0", + "concat-stream": "^1.4.7", + "http-basic": "^2.5.1", + "http-response-object": "^1.1.0", + "promise": "^7.1.1", + "qs": "^6.1.0" + }, + "dependencies": { + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" + } + } + }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "requires": { + "readable-stream": "~1.1.9", + "xtend": "~2.1.1" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "touch": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", + "integrity": "sha1-Ua7z1ElXHU8oel2Hyci0kYGg2x0=", + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1" + } + } + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "trim-trailing-lines": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz", + "integrity": "sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg==" + }, + "trough": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.2.tgz", + "integrity": "sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ==" + }, + "try-resolve": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/try-resolve/-/try-resolve-1.0.1.tgz", + "integrity": "sha1-z95vq9ctY+V5fPqrhzq76OcA6RI=" + }, + "tryor": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz", + "integrity": "sha1-gUXkynyv9ArN48z5Rui4u3W0Fys=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + }, + "underscore-plus": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.6.8.tgz", + "integrity": "sha512-88PrCeMKeAAC1L4xjSiiZ3Fg6kZOYrLpLGVPPeqKq/662DfQe/KTSKdSR/Q/tucKNnfW2MNAUGSCkDf8HmXC5Q==", + "requires": { + "underscore": "~1.8.3" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } + } + }, + "underscore.string": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz", + "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=", + "requires": { + "sprintf-js": "^1.0.3", + "util-deprecate": "^1.0.2" + } + }, + "unherit": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", + "integrity": "sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g==", + "requires": { + "inherits": "^2.0.1", + "xtend": "^4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "unified": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "unist-util-find-all-after": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-1.0.2.tgz", + "integrity": "sha512-nDl79mKpffXojLpCimVXnxhlH/jjaTnDuScznU9J4jjsaUtBdDbxmlc109XtcqxY4SDO0SwzngsxxW8DIISt1w==", + "requires": { + "unist-util-is": "^2.0.0" + } + }, + "unist-util-is": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-2.1.2.tgz", + "integrity": "sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw==" + }, + "unist-util-modify-children": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz", + "integrity": "sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg==", + "requires": { + "array-iterate": "^1.0.0" + } + }, + "unist-util-remove-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz", + "integrity": "sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q==", + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" + }, + "unist-util-visit": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.3.1.tgz", + "integrity": "sha512-0fdB9EQJU0tho5tK0VzOJzAQpPv2LyLZ030b10GxuzAWEfvd54mpY7BMjQ1L69k2YNvL+SvxRzH0yUIehOO8aA==", + "requires": { + "unist-util-is": "^2.1.1" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } + }, + "vfile-location": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.3.tgz", + "integrity": "sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A==" + }, + "vfile-message": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.0.1.tgz", + "integrity": "sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug==", + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + }, + "walkdir": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.12.tgz", + "integrity": "sha512-HFhaD4mMWPzFSqhpyDG48KDdrjfn409YQuVW7ckZYhW4sE87mYtWifdB/+73RA7+p4s4K18n5Jfx1kHthE1gBw==" + }, + "webdriverio": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-2.4.5.tgz", + "integrity": "sha1-wD7ajhp+tCMDhYjm5z8nCyx03gs=", + "requires": { + "archiver": "~0.6.1", + "async": "^0.9.0", + "chainit": "^2.1.1", + "css-parse": "^1.7.0", + "css-value": "0.0.1", + "deepmerge": "~0.2.7", + "pragma-singleton": "~1.0.3", + "q": "^1.1.2", + "request": "~2.34.0", + "rgb2hex": "^0.1.0", + "url": "^0.10.1", + "wgxpath": "^0.23.0" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "optional": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "optional": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=" + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "optional": true, + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime": "~1.2.11" + } + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "^0.1.5", + "ctype": "0.5.3" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=" + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "oauth-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", + "optional": true + }, + "qs": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=" + }, + "request": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.34.0.tgz", + "integrity": "sha1-tdi5UmrdSi1GKfTUFxJFc5lkRa4=", + "requires": { + "aws-sign2": "~0.5.0", + "forever-agent": "~0.5.0", + "form-data": "~0.1.0", + "hawk": "~1.0.0", + "http-signature": "~0.10.0", + "json-stringify-safe": "~5.0.0", + "mime": "~1.2.9", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.3.0", + "qs": "~0.6.0", + "tough-cookie": ">=0.12.0", + "tunnel-agent": "~0.3.0" + } + }, + "tunnel-agent": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz", + "integrity": "sha1-rWgbaPUyGtKCfEz7G31d8s/pQu4=", + "optional": true + } + } + }, + "wgxpath": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/wgxpath/-/wgxpath-0.23.0.tgz", + "integrity": "sha1-2z/IOJ2BhOluunA3SJc1wTYiep8=" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "^0.5.1" + } + }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "~0.4.0" + } + }, + "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=" + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "lodash.assign": "^4.0.3", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.1", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^2.4.1" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "requires": { + "camelcase": "^3.0.0", + "lodash.assign": "^4.0.6" + } + } + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "requires": { + "fd-slicer": "~1.0.1" + } + }, + "zip-stream": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-0.2.3.tgz", + "integrity": "sha1-rvCVN2z+E4lZqBNBmB0mM4tG2NM=", + "requires": { + "debug": "~0.7.4", + "lodash.defaults": "~2.4.1", + "readable-stream": "~1.0.24" + }, + "dependencies": { + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + } + } +} diff --git a/script/package.json b/script/package.json index 5946496ef..dd57e304d 100644 --- a/script/package.json +++ b/script/package.json @@ -2,14 +2,16 @@ "name": "atom-build-scripts", "description": "Atom build scripts", "dependencies": { + "7zip-bin": "^4.0.2", "async": "2.0.1", + "aws-sdk": "^2.5.2", "babel-core": "5.8.38", "coffeelint": "1.15.7", "colors": "1.1.2", "donna": "1.0.16", - "electron-chromedriver": "~1.7", - "electron-link": "0.1.2", - "electron-mksnapshot": "~1.7", + "electron-chromedriver": "~2.0", + "electron-link": "0.2.2", + "electron-mksnapshot": "~2.0", "electron-packager": "7.3.0", "electron-winstaller": "2.6.4", "fs-admin": "^0.1.5", @@ -23,9 +25,10 @@ "minidump": "0.9.0", "mkdirp": "0.5.1", "normalize-package-data": "2.3.5", - "npm": "5.3.0", + "npm": "6.2.0", "passwd-user": "2.1.0", "pegjs": "0.9.0", + "publish-release": "^1.6.0", "random-seed": "^0.3.0", "season": "5.3.0", "semver": "5.3.0", @@ -34,6 +37,7 @@ "stylelint-config-standard": "^18.1.0", "sync-request": "3.0.1", "tello": "1.0.7", + "terser": "^3.8.1", "webdriverio": "2.4.5", "yargs": "4.8.1" } diff --git a/script/publish-release b/script/publish-release new file mode 100644 index 000000000..2e9115c4d --- /dev/null +++ b/script/publish-release @@ -0,0 +1,65 @@ +#!/usr/bin/env node + +'use strict' + +const path = require('path') +const glob = require('glob') +const publishRelease = require('publish-release') +const uploadToS3 = require('./lib/upload-to-s3') +const CONFIG = require('./config') + +const yargs = require('yargs') +const argv = yargs + .usage('Usage: $0 [options]') + .help('help') + .describe('assets-path', 'Path to the folder where all release assets are stored') + .describe('s3-path', 'Indicates the S3 path in which the assets should be uploaded') + .describe('create-github-release', 'Creates a GitHub release for this build, draft if release branch or public if Nightly') + .wrap(yargs.terminalWidth()) + .argv + +const assetsPath = argv.assetsPath || path.join(CONFIG.repositoryRootPath, 'out') +const assetsPattern = '/**/*(*.exe|*.zip|*.nupkg|*.tar.gz|*.rpm|*.deb|RELEASES*|atom-api.json)' +const assets = glob.sync(assetsPattern, { root: assetsPath, nodir: true }) +const bucketPath = argv.s3Path || `releases/v${CONFIG.computedAppVersion}/` + +if (!assets || assets.length === 0) { + console.error(`No assets found under specified path: ${assetsPath}`) + process.exit(1) +} + +console.log(`Uploading ${assets.length} release assets for ${CONFIG.computedAppVersion} to S3 under '${bucketPath}'`) + +uploadToS3( + process.env.ATOM_RELEASES_S3_KEY, + process.env.ATOM_RELEASES_S3_SECRET, + process.env.ATOM_RELEASES_S3_BUCKET, + bucketPath, + assets).then( + () => { + if (argv.createGithubRelease) { + console.log(`Creating GitHub release v${CONFIG.computedAppVersion}`) + publishRelease({ + token: process.env.GITHUB_TOKEN, + owner: 'atom', + repo: CONFIG.channel !== 'nightly' ? 'atom' : 'atom-nightly-releases', + name: CONFIG.computedAppVersion, + tag: `v${CONFIG.computedAppVersion}`, + draft: false, + prerelease: CONFIG.channel !== 'stable', + reuseRelease: true, + skipIfPublished: true, + assets + }, function (err, release) { + if (err) { + console.error("An error occurred while publishing the release:\n\n", err) + } else { + console.log("Release published successfully: ", release.html_url) + } + }) + } else { + console.log("Skipping GitHub release creation") + } + }).catch((err) => { + console.error('An error occurred while uploading the release:', err) + }) diff --git a/script/publish-release.cmd b/script/publish-release.cmd new file mode 100644 index 000000000..46e077a3c --- /dev/null +++ b/script/publish-release.cmd @@ -0,0 +1,5 @@ +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\publish-release" %* +) ELSE ( + node "%~dp0\publish-release" %* +) diff --git a/script/test b/script/test index c6c3a6a61..64688daa1 100755 --- a/script/test +++ b/script/test @@ -22,7 +22,7 @@ if (process.platform === 'darwin') { assert(executablePaths.length === 1, `More than one application to run tests against was found. ${executablePaths.join(',')}`) executablePath = path.join(executablePaths[0], 'Contents', 'MacOS', path.basename(executablePaths[0], '.app')) } else if (process.platform === 'linux') { - const executablePaths = glob.sync(path.join(CONFIG.buildOutputPath, '**', 'atom')) + const executablePaths = glob.sync(path.join(CONFIG.buildOutputPath, 'atom-*', 'atom')) assert(executablePaths.length === 1, `More than one application to run tests against was found. ${executablePaths.join(',')}`) executablePath = executablePaths[0] } else if (process.platform === 'win32') { diff --git a/script/vsts/README.md b/script/vsts/README.md new file mode 100644 index 000000000..0e956d8d0 --- /dev/null +++ b/script/vsts/README.md @@ -0,0 +1,65 @@ +# Atom Release Build Documentation + +## Overview + +This folder contains build configuration and scripts for automating Atom's +release pipeline using [Visual Studio Team Services](https://azure.microsoft.com/en-us/services/visual-studio-team-services/). +VSTS allows us to leverage [multi-phase jobs](https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-jobs.md) to generate Atom installation packages +on Windows, macOS, and Linux and then publish a new release automatically once +the build completes successfully. + +## Nightly Release Build + +Our scheduled nightly release uses a mutli-phase job to automatically generate Atom +Nightly installation packages and then publish them to GitHub and atom.io. + +The [Atom Nightly build definition](https://github.visualstudio.com/Atom/_build/index?context=mine&path=%5C&definitionId=1&_a=completed) +is configured with the [`nightly-release.yml`](nightly-release.yml) file. More +information on VSTS' YAML configuration format can be found in their [Getting Started](https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md) +documentation. + +### Versioning Phase + +In this phase, we run [`script/vsts/generate-version.js`](generate-version.js) to +determine the version of the next Atom Nightly release. This script consults the +GitHub v3 API to get the list of releases on the [`atom/atom-nightly-releases`](https://github.com/atom/atom-nightly-releases) +repo. We look for the most recent, non-draft release and then parse its version +number (e.g. `1.30.0-nightly4`) to extract the base version and the monotonically-increasing +nightly release number. + +Once we have the version and release number, we compare the base version number +(`1.30.0`) against the one in `package.json` of the latest commit in the local +repo. If those versions are the same, we increment the release number (`1.30.0-nightly5`). +If those versions are different, we use `0` for the release number to start a +new series of Nightly releases for the new version (`1.31.0-nightly0`). + +Once the release version has been determined, it is set as our custom `ReleaseVersion` +[output variable](https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-outputvariables.md) +by writing out a special string to `stdout` which is recognized by VSTS. This +variable will be used in later build steps. + +If any part of the build process fails from this point forward, the same version +number *should* be chosen in the next build unless the base version number has +been changed in `master`. + +### OS-specific Build Phases + +In this part of the build, we use [phase templates](https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md) +for [Windows](windows.yml), [macOS](macos.yml), and [Linux](linux.yml) to build +Atom simultaneously across those platforms and then run the Atom test suite to +verify the builds. If build, test, and linting come back clean, we take the build +assets generated in the `out` folder on each OS and then stage them as build artifacts. + +For each OS build, we refer to the `ReleaseVersion` variable, set in the previous +phase, to configure the `ATOM_RELEASE_VERSION` environment variable to override +the version contained in Atom's `package.json`. + +### Publish Phase + +If all three OS builds have completed successfully, the publish phase will launch the +[`script/publish-release`](../publish-release) script to collect the release +artifacts created from those builds and then upload them to the S3 bucket from +which Atom release assets are served. If the upload process is successful, a new +release will be created on the `atom/atom-nightly-releases` repo using the +`ReleaseVersion` with a `v` prefix as the tag name. The release assets will also +be uploaded to the GitHub release at this time. diff --git a/script/vsts/get-release-version.js b/script/vsts/get-release-version.js new file mode 100644 index 000000000..13fbfbea5 --- /dev/null +++ b/script/vsts/get-release-version.js @@ -0,0 +1,59 @@ +const path = require('path') +const request = require('request-promise-native') + +const repositoryRootPath = path.resolve(__dirname, '..', '..') +const appMetadata = require(path.join(repositoryRootPath, 'package.json')) + +const yargs = require('yargs') +const argv = yargs + .usage('Usage: $0 [options]') + .help('help') + .describe('nightly', 'Indicates that a nightly version should be produced') + .wrap(yargs.terminalWidth()) + .argv + +async function getReleaseVersion () { + let releaseVersion = appMetadata.version + if (argv.nightly) { + const releases = await request({ + url: 'https://api.github.com/repos/atom/atom-nightly-releases/releases', + headers: {'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'Atom Release Build'}, + json: true + }) + + let releaseNumber = 0 + const baseVersion = appMetadata.version.split('-')[0] + if (releases && releases.length > 0) { + const latestRelease = releases.find(r => !r.draft) + const versionMatch = latestRelease.tag_name.match(/^v?(\d+\.\d+\.\d+)-nightly(\d+)$/) + + if (versionMatch && versionMatch[1] === baseVersion) { + releaseNumber = parseInt(versionMatch[2]) + 1 + } + } + + releaseVersion = `${baseVersion}-nightly${releaseNumber}` + } + + // Set our ReleaseVersion build variable and update VSTS' build number to + // include the version. Writing these strings to stdout causes VSTS to set + // the associated variables. + console.log(`##vso[task.setvariable variable=ReleaseVersion;isOutput=true]${releaseVersion}`) + if (!process.env.SYSTEM_PULLREQUEST_PULLREQUESTNUMBER) { + // Only set the build number on non-PR builds as it causes build errors when + // non-admins send PRs to the repo + console.log(`##vso[build.updatebuildnumber]${releaseVersion}+${process.env.BUILD_BUILDNUMBER}`) + } + + // Write out some variables that indicate whether artifacts should be uploaded + const buildBranch = process.env.BUILD_SOURCEBRANCHNAME + const isReleaseBranch = process.env.IS_RELEASE_BRANCH || argv.nightly || buildBranch.match(/\d\.\d+-releases/) !== null + const isSignedZipBranch = + process.env.IS_SIGNED_ZIP_BRANCH || + buildBranch.startsWith('electron-') || + buildBranch === 'master' && !process.env.SYSTEM_PULLREQUEST_PULLREQUESTNUMBER + console.log(`##vso[task.setvariable variable=IsReleaseBranch;isOutput=true]${isReleaseBranch}`) + console.log(`##vso[task.setvariable variable=IsSignedZipBranch;isOutput=true]${isSignedZipBranch}`) +} + +getReleaseVersion() diff --git a/script/vsts/nightly-release.yml b/script/vsts/nightly-release.yml new file mode 100644 index 000000000..ef68ef335 --- /dev/null +++ b/script/vsts/nightly-release.yml @@ -0,0 +1,58 @@ +phases: + +- phase: GetReleaseVersion + steps: + # This has to be done separately because VSTS inexplicably + # exits the script block after `npm install` completes. + - script: | + cd script\vsts + npm install + displayName: npm install + - script: node script\vsts\get-release-version.js --nightly + name: Version + +# Import OS-specific build definitions +- template: platforms/windows.yml +- template: platforms/macos.yml +- template: platforms/linux.yml + +- phase: Release + queue: Hosted # Need this for Python 2.7 + + dependsOn: + - GetReleaseVersion + - Windows + - Linux + - macOS + + variables: + ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ] + + steps: + - task: NodeTool@0 + inputs: + versionSpec: 8.9.3 + displayName: Install Node.js 8.9.3 + + # This has to be done separately because VSTS inexplicably + # exits the script block after `npm install` completes. + - script: | + cd script + npm install + displayName: npm install + + - task: DownloadBuildArtifacts@0 + inputs: + itemPattern: '**' + downloadType: 'specific' + displayName: Download Release Artifacts + + - script: | + $(Build.SourcesDirectory)\script\publish-release.cmd --create-github-release --assets-path "$(System.ArtifactsDirectory)" + env: + GITHUB_TOKEN: $(GITHUB_TOKEN) + ATOM_RELEASE_VERSION: $(ReleaseVersion) + ATOM_RELEASES_S3_KEY: $(ATOM_RELEASES_S3_KEY) + ATOM_RELEASES_S3_SECRET: $(ATOM_RELEASES_S3_SECRET) + ATOM_RELEASES_S3_BUCKET: $(ATOM_RELEASES_S3_BUCKET) + displayName: Create Nightly Release diff --git a/script/vsts/package-lock.json b/script/vsts/package-lock.json new file mode 100644 index 000000000..18d2190b1 --- /dev/null +++ b/script/vsts/package-lock.json @@ -0,0 +1,704 @@ +{ + "name": "atom-release-scripts", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "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==", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "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-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "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", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" + } + }, + "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=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.2" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.0" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "4.17.10" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "2.3.4" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "uuid": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.0.tgz", + "integrity": "sha512-ijO9N2xY/YaOqQ5yz5c4sy2ZjWmA6AR6zASb/gdpeKZ8+948CxwfMW9RrKVk5may6ev8c0/Xguu32e2Llelpqw==" + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", + "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "lodash.assign": "4.2.0", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + } + }, + "yargs-parser": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", + "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.2.0" + } + } + } +} diff --git a/script/vsts/package.json b/script/vsts/package.json new file mode 100644 index 000000000..4e0b450d5 --- /dev/null +++ b/script/vsts/package.json @@ -0,0 +1,9 @@ +{ + "name": "atom-release-scripts", + "description": "Atom release scripts", + "dependencies": { + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "yargs": "4.8.1" + } +} diff --git a/script/vsts/platforms/linux.yml b/script/vsts/platforms/linux.yml new file mode 100644 index 000000000..51e7e5001 --- /dev/null +++ b/script/vsts/platforms/linux.yml @@ -0,0 +1,63 @@ +phases: +- phase: Linux + dependsOn: GetReleaseVersion + variables: + ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ] + queue: + name: Hosted Ubuntu 1604 + timeoutInMinutes: 180 + + steps: + - task: NodeTool@0 + inputs: + versionSpec: 8.9.3 + displayName: Install Node.js 8.9.3 + + - script: npm install --global npm@6.2.0 + displayName: Update npm + + - script: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends build-essential xvfb clang-3.5 fakeroot git libsecret-1-dev rpm libx11-dev libxkbfile-dev xz-utils xorriso zsync libxss1 libgconf2-4 libgtk-3-0 + displayName: Install apt dependencies + + - script: | + script/build --create-debian-package --create-rpm-package --compress-artifacts + env: + ATOM_RELEASE_VERSION: $(ReleaseVersion) + displayName: Build Atom + + - script: script/lint + displayName: Run linter + + - script: | + sudo /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 + export DISPLAY=':99.0' + Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + script/test + env: + CI: true + CI_PROVIDER: VSTS + displayName: Run tests + condition: and(succeeded(), ne(variables['Atom.SkipTests'], 'true')) + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.SourcesDirectory)/out/atom.x86_64.rpm + ArtifactName: atom.x86_64.rpm + ArtifactType: Container + displayName: Upload atom.x84_64.rpm + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.SourcesDirectory)/out/atom-amd64.deb + ArtifactName: atom-amd64.deb + ArtifactType: Container + displayName: Upload atom-amd64.deb + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.SourcesDirectory)/out/atom-amd64.tar.gz + ArtifactName: atom-amd64.tar.gz + ArtifactType: Container + displayName: Upload atom-amd64.tar.gz diff --git a/script/vsts/platforms/macos.yml b/script/vsts/platforms/macos.yml new file mode 100644 index 000000000..e7443860e --- /dev/null +++ b/script/vsts/platforms/macos.yml @@ -0,0 +1,72 @@ +phases: +- phase: macOS + dependsOn: GetReleaseVersion + variables: + ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ] + IsReleaseBranch: $[ dependencies.GetReleaseVersion.outputs['Version.IsReleaseBranch'] ] + IsSignedZipBranch: $[ dependencies.GetReleaseVersion.outputs['Version.IsSignedZipBranch'] ] + queue: + name: Hosted macOS Preview + timeoutInMinutes: 180 + + steps: + - task: NodeTool@0 + inputs: + versionSpec: 8.9.3 + displayName: Install Node.js 8.9.3 + + - script: npm install --global npm@6.2.0 + displayName: Update npm + + - script: | + if [ $IS_RELEASE_BRANCH == "true" ] || [ $IS_SIGNED_ZIP_BRANCH == "true" ]; then + script/build --code-sign --compress-artifacts + else + script/build --compress-artifacts + fi + displayName: Build Atom + env: + IS_RELEASE_BRANCH: $(IsReleaseBranch) + IS_SIGNED_ZIP_BRANCH: $(IsSignedZipBranch) + ATOM_RELEASE_VERSION: $(ReleaseVersion) + ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL: $(ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL) + ATOM_MAC_CODE_SIGNING_CERT_PASSWORD: $(ATOM_MAC_CODE_SIGNING_CERT_PASSWORD) + ATOM_MAC_CODE_SIGNING_KEYCHAIN: $(ATOM_MAC_CODE_SIGNING_KEYCHAIN) + ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD: $(ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD) + + - script: script/lint + displayName: Run linter + + - script: | + osascript -e 'tell application "System Events" to keystroke "x"' # clear screen saver + caffeinate -s script/test # Run with caffeinate to prevent screen saver + env: + CI: true + CI_PROVIDER: VSTS + displayName: Run tests + condition: and(succeeded(), ne(variables['Atom.SkipTests'], 'true')) + + - script: | + cp $(Build.SourcesDirectory)/out/*.zip $(Build.ArtifactStagingDirectory) + displayName: Stage Artifacts + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.ArtifactStagingDirectory)/atom-mac.zip + ArtifactName: atom-mac.zip + ArtifactType: Container + displayName: Upload atom-mac.zip + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.ArtifactStagingDirectory)/atom-mac-symbols.zip + ArtifactName: atom-mac-symbols.zip + ArtifactType: Container + displayName: Upload atom-mac-symbols.zip + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.SourcesDirectory)/docs/output/atom-api.json + ArtifactName: atom-api.json + ArtifactType: Container + displayName: Upload atom-api.json diff --git a/script/vsts/platforms/windows.yml b/script/vsts/platforms/windows.yml new file mode 100644 index 000000000..aba06b2a3 --- /dev/null +++ b/script/vsts/platforms/windows.yml @@ -0,0 +1,93 @@ +phases: +- phase: Windows + dependsOn: GetReleaseVersion + variables: + ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ] + IsReleaseBranch: $[ dependencies.GetReleaseVersion.outputs['Version.IsReleaseBranch'] ] + IsSignedZipBranch: $[ dependencies.GetReleaseVersion.outputs['Version.IsSignedZipBranch'] ] + queue: + name: Hosted + timeoutInMinutes: 180 + parallel: 2 + matrix: + x64: + buildArch: x64 + # TODO: x86 is currently not supported on VSTS + # x86: + # buildArch: x86 + + steps: + - task: NodeTool@0 + inputs: + versionSpec: 8.9.3 + displayName: Install Node.js 8.9.3 + + - script: | + ECHO Installing npm-windows-upgrade + npm install --global --production npm-windows-upgrade + ECHO Upgrading npm + npm-windows-upgrade --no-spinner --no-prompt --npm-version 6.2.0 + + - script: | + IF NOT EXIST C:\tmp MKDIR C:\tmp + SET SQUIRREL_TEMP=C:\tmp + IF [%IS_RELEASE_BRANCH%]==[true] ( + ECHO Creating production artifacts for release branch %BUILD_SOURCEBRANCHNAME% + script\build.cmd --code-sign --compress-artifacts --create-windows-installer + ) ELSE ( + IF [%IS_SIGNED_ZIP_BRANCH%]==[true] ( + ECHO Creating signed CI artifacts for branch %BUILD_SOURCEBRANCHNAME% + script\build.cmd --code-sign --compress-artifacts + ) ELSE ( + ECHO Pull request build, no code signing will be performed + script\build.cmd --compress-artifacts + ) + ) + env: + ATOM_RELEASE_VERSION: $(ReleaseVersion) + ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL: $(ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL) + ATOM_WIN_CODE_SIGNING_CERT_PASSWORD: $(ATOM_WIN_CODE_SIGNING_CERT_PASSWORD) + IS_RELEASE_BRANCH: $(IsReleaseBranch) + IS_SIGNED_ZIP_BRANCH: $(IsSignedZipBranch) + displayName: Build Atom + + - script: script\lint.cmd + displayName: Run linter + + - script: script\test.cmd + env: + CI: true + CI_PROVIDER: VSTS + displayName: Run tests + condition: and(succeeded(), ne(variables['Atom.SkipTests'], 'true')) + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.SourcesDirectory)/out/atom-x64-windows.zip + ArtifactName: atom-x64-windows.zip + ArtifactType: Container + displayName: Upload atom-x64-windows.zip + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.SourcesDirectory)/out/AtomSetup-x64.exe + ArtifactName: AtomSetup-x64.exe + ArtifactType: Container + displayName: Upload AtomSetup-x64.exe + condition: and(succeeded(), eq(variables['IsReleaseBranch'], 'true')) + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.SourcesDirectory)/out/atom-x64-$(ReleaseVersion)-full.nupkg + ArtifactName: atom-x64-$(ReleaseVersion)-full.nupkg + ArtifactType: Container + displayName: Upload atom-x64-$(ReleaseVersion)-full.nupkg + condition: and(succeeded(), eq(variables['IsReleaseBranch'], 'true')) + + - task: PublishBuildArtifacts@1 + inputs: + PathtoPublish: $(Build.SourcesDirectory)/out/RELEASES-x64 + ArtifactName: RELEASES-x64 + ArtifactType: Container + displayName: Upload RELEASES-x64 + condition: and(succeeded(), eq(variables['IsReleaseBranch'], 'true')) diff --git a/script/vsts/pull-requests.yml b/script/vsts/pull-requests.yml new file mode 100644 index 000000000..8f17bacff --- /dev/null +++ b/script/vsts/pull-requests.yml @@ -0,0 +1,19 @@ +trigger: none # No CI builds, only PR builds + +phases: + +- phase: GetReleaseVersion + steps: + # This has to be done separately because VSTS inexplicably + # exits the script block after `npm install` completes. + - script: | + cd script\vsts + npm install + displayName: npm install + - script: node script\vsts\get-release-version.js + name: Version + +# Import OS-specific build definitions +- template: platforms/windows.yml +- template: platforms/macos.yml +- template: platforms/linux.yml diff --git a/script/vsts/release-branch-build.yml b/script/vsts/release-branch-build.yml new file mode 100644 index 000000000..cbbf73ffb --- /dev/null +++ b/script/vsts/release-branch-build.yml @@ -0,0 +1,64 @@ +trigger: +- master +- 1.* # VSTS only supports wildcards at the end + +phases: + +- phase: GetReleaseVersion + steps: + # This has to be done separately because VSTS inexplicably + # exits the script block after `npm install` completes. + - script: | + cd script\vsts + npm install + displayName: npm install + - script: node script\vsts\get-release-version.js + name: Version + +# Import OS-specific build definitions +- template: platforms/windows.yml +- template: platforms/macos.yml +- template: platforms/linux.yml + +- phase: UploadArtifacts + queue: Hosted # Need this for Python 2.7 + + dependsOn: + - GetReleaseVersion + - Windows + - Linux + - macOS + + variables: + ReleaseVersion: $[ dependencies.GetReleaseVersion.outputs['Version.ReleaseVersion'] ] + IsReleaseBranch: $[ dependencies.GetReleaseVersion.outputs['Version.IsReleaseBranch'] ] + IsSignedZipBranch: $[ dependencies.GetReleaseVersion.outputs['Version.IsSignedZipBranch'] ] + + steps: + - task: NodeTool@0 + inputs: + versionSpec: 8.9.3 + displayName: Install Node.js 8.9.3 + + # This has to be done separately because VSTS inexplicably + # exits the script block after `npm install` completes. + - script: | + cd script + npm install + displayName: npm install + + - task: DownloadBuildArtifacts@0 + inputs: + itemPattern: '**' + downloadType: 'specific' + displayName: Download Release Artifacts + + - script: | + $(Build.SourcesDirectory)\script\publish-release.cmd --assets-path "$(System.ArtifactsDirectory)" --s3-path "vsts-artifacts/$(Build.BuildId)/" + env: + ATOM_RELEASE_VERSION: $(ReleaseVersion) + ATOM_RELEASES_S3_KEY: $(ATOM_RELEASES_S3_KEY) + ATOM_RELEASES_S3_SECRET: $(ATOM_RELEASES_S3_SECRET) + ATOM_RELEASES_S3_BUCKET: $(ATOM_RELEASES_S3_BUCKET) + displayName: Upload CI Artifacts to S3 + condition: and(succeeded(), eq(variables['IsSignedZipBranch'], 'true')) diff --git a/spec/async-spec-helpers.js b/spec/async-spec-helpers.js index 73002c049..90cb85e23 100644 --- a/spec/async-spec-helpers.js +++ b/spec/async-spec-helpers.js @@ -1,7 +1,5 @@ -/** @babel */ - -export function beforeEach (fn) { - global.beforeEach(function () { +function beforeEach (fn) { + global.beforeEach(() => { const result = fn() if (result instanceof Promise) { waitsForPromise(() => result) @@ -9,8 +7,8 @@ export function beforeEach (fn) { }) } -export function afterEach (fn) { - global.afterEach(function () { +function afterEach (fn) { + global.afterEach(() => { const result = fn() if (result instanceof Promise) { waitsForPromise(() => result) @@ -18,14 +16,14 @@ export function afterEach (fn) { }) } -['it', 'fit', 'ffit', 'fffit'].forEach(function (name) { - module.exports[name] = function (description, fn) { +;['it', 'fit', 'ffit', 'fffit'].forEach(name => { + exports[name] = (description, fn) => { if (fn === undefined) { global[name](description) return } - global[name](description, function () { + global[name](description, () => { const result = fn() if (result instanceof Promise) { waitsForPromise(() => result) @@ -34,7 +32,7 @@ export function afterEach (fn) { } }) -export async function conditionPromise (condition, description = 'anonymous condition') { +async function conditionPromise (condition, description = 'anonymous condition') { const startTime = Date.now() while (true) { @@ -50,23 +48,23 @@ export async function conditionPromise (condition, description = 'anonymous cond } } -export function timeoutPromise (timeout) { - return new Promise(function (resolve) { +function timeoutPromise (timeout) { + return new Promise(resolve => { global.setTimeout(resolve, timeout) }) } function waitsForPromise (fn) { const promise = fn() - global.waitsFor('spec promise to resolve', function (done) { - promise.then(done, function (error) { + global.waitsFor('spec promise to resolve', done => { + promise.then(done, error => { jasmine.getEnv().currentSpec.fail(error) done() }) }) } -export function emitterEventPromise (emitter, event, timeout = 15000) { +function emitterEventPromise (emitter, event, timeout = 15000) { return new Promise((resolve, reject) => { const timeoutHandle = setTimeout(() => { reject(new Error(`Timed out waiting for '${event}' event`)) @@ -78,7 +76,7 @@ export function emitterEventPromise (emitter, event, timeout = 15000) { }) } -export function promisify (original) { +function promisify (original) { return function (...args) { return new Promise((resolve, reject) => { args.push((err, ...results) => { @@ -94,10 +92,18 @@ export function promisify (original) { } } -export function promisifySome (obj, fnNames) { +function promisifySome (obj, fnNames) { const result = {} for (const fnName of fnNames) { result[fnName] = promisify(obj[fnName]) } return result } + +exports.afterEach = afterEach +exports.beforeEach = beforeEach +exports.conditionPromise = conditionPromise +exports.emitterEventPromise = emitterEventPromise +exports.promisify = promisify +exports.promisifySome = promisifySome +exports.timeoutPromise = timeoutPromise diff --git a/spec/atom-environment-spec.js b/spec/atom-environment-spec.js index 5574e9663..aea5313e8 100644 --- a/spec/atom-environment-spec.js +++ b/spec/atom-environment-spec.js @@ -258,7 +258,7 @@ describe('AtomEnvironment', () => { atomEnv.destroy() }) - it('ignores mousedown/keydown events happening after calling unloadEditorWindow', () => { + it('ignores mousedown/keydown events happening after calling prepareToUnloadEditorWindow', async () => { const atomEnv = new AtomEnvironment({ applicationDelegate: global.atom.applicationDelegate }) @@ -276,18 +276,19 @@ describe('AtomEnvironment', () => { let mousedown = new MouseEvent('mousedown') atomEnv.document.dispatchEvent(mousedown) - atomEnv.unloadEditorWindow() expect(atomEnv.saveState).not.toHaveBeenCalled() + await atomEnv.prepareToUnloadEditorWindow() + expect(atomEnv.saveState).toHaveBeenCalledWith({isUnloading: true}) advanceClock(atomEnv.saveStateDebounceInterval) idleCallbacks.shift()() - expect(atomEnv.saveState).not.toHaveBeenCalled() + expect(atomEnv.saveState.calls.length).toBe(1) mousedown = new MouseEvent('mousedown') atomEnv.document.dispatchEvent(mousedown) advanceClock(atomEnv.saveStateDebounceInterval) idleCallbacks.shift()() - expect(atomEnv.saveState).not.toHaveBeenCalled() + expect(atomEnv.saveState.calls.length).toBe(1) atomEnv.destroy() }) @@ -746,29 +747,6 @@ describe('AtomEnvironment', () => { }) }) - describe('::updateAvailable(info) (called via IPC from browser process)', () => { - let subscription - - afterEach(() => { - if (subscription) subscription.dispose() - }) - - it('invokes onUpdateAvailable listeners', async () => { - if (process.platform !== 'darwin') return // Test tied to electron autoUpdater, we use something else on Linux and Win32 - - const updateAvailablePromise = new Promise(resolve => { - subscription = atom.onUpdateAvailable(resolve) - }) - - atom.listenForUpdates() - const {autoUpdater} = require('electron').remote - autoUpdater.emit('update-downloaded', null, 'notes', 'version') - - const {releaseVersion} = await updateAvailablePromise - expect(releaseVersion).toBe('version') - }) - }) - describe('::getReleaseChannel()', () => { let version diff --git a/spec/atom-reporter.coffee b/spec/atom-reporter.coffee index a522d9298..9af21a7dd 100644 --- a/spec/atom-reporter.coffee +++ b/spec/atom-reporter.coffee @@ -33,6 +33,8 @@ formatStackTrace = (spec, message='', stackTrace) -> line = line.trim() # at jasmine.Spec. (path:1:2) -> at path:1:2 .replace(/^at jasmine\.Spec\. \(([^)]+)\)/, 'at $1') + # at jasmine.Spec.it (path:1:2) -> at path:1:2 + .replace(/^at jasmine\.Spec\.f*it \(([^)]+)\)/, 'at $1') # at it (path:1:2) -> at path:1:2 .replace(/^at f*it \(([^)]+)\)/, 'at $1') # at spec/file-test.js -> at file-test.js diff --git a/spec/auto-update-manager-spec.js b/spec/auto-update-manager-spec.js index 780c9816b..ab9e0ed70 100644 --- a/spec/auto-update-manager-spec.js +++ b/spec/auto-update-manager-spec.js @@ -1,11 +1,8 @@ -'use babel' - -import AutoUpdateManager from '../src/auto-update-manager' -import {remote} from 'electron' +const AutoUpdateManager = require('../src/auto-update-manager') +const {remote} = require('electron') const electronAutoUpdater = remote.require('electron').autoUpdater describe('AutoUpdateManager (renderer)', () => { - if (process.platform !== 'darwin') return // Tests are tied to electron autoUpdater, we use something else on Linux and Win32 let autoUpdateManager diff --git a/spec/babel-spec.coffee b/spec/babel-spec.coffee index 400e5c03e..9e9195783 100644 --- a/spec/babel-spec.coffee +++ b/spec/babel-spec.coffee @@ -42,6 +42,11 @@ describe "Babel transpiler support", -> transpiled = require('./fixtures/babel/flow-comment.js') expect(transpiled(3)).toBe 4 + describe 'when a .js file starts with // @flow', -> + it "transpiles it using babel", -> + transpiled = require('./fixtures/babel/flow-slash-comment.js') + expect(transpiled(3)).toBe 4 + describe "when a .js file does not start with 'use babel';", -> it "does not transpile it using babel", -> spyOn(console, 'error') diff --git a/spec/command-installer-spec.js b/spec/command-installer-spec.js index 6a2a31e77..b303d4954 100644 --- a/spec/command-installer-spec.js +++ b/spec/command-installer-spec.js @@ -1,6 +1,7 @@ const path = require('path') const fs = require('fs-plus') const temp = require('temp').track() +const {it, fit, ffit, fffit, beforeEach, afterEach} = require('./async-spec-helpers'); const CommandInstaller = require('../src/command-installer') describe('CommandInstaller on #darwin', () => { @@ -56,8 +57,8 @@ describe('CommandInstaller on #darwin', () => { const appDelegate = jasmine.createSpyObj('appDelegate', ['confirm']) installer = new CommandInstaller(appDelegate) installer.initialize('2.0.2') - spyOn(installer, 'installAtomCommand').andCallFake((__, callback) => callback()) - spyOn(installer, 'installApmCommand').andCallFake((__, callback) => callback()) + spyOn(installer, 'installAtomCommand').andCallFake((__, callback) => callback(undefined, 'atom')) + spyOn(installer, 'installApmCommand').andCallFake((__, callback) => callback(undefined, 'apm')) installer.installShellCommandsInteractively() @@ -140,4 +141,41 @@ describe('CommandInstaller on #darwin', () => { }) }) }) + + describe('when using a nightly version of atom', () => { + beforeEach(() => { + installer = new CommandInstaller() + installer.initialize('2.2.0-nightly0') + }) + + it("symlinks the atom command as 'atom-nightly'", () => { + const installedAtomPath = path.join(installationPath, 'atom-nightly') + expect(fs.isFileSync(installedAtomPath)).toBeFalsy() + + waitsFor(done => { + installer.installAtomCommand(false, error => { + expect(error).toBeNull() + expect(fs.realpathSync(installedAtomPath)).toBe(fs.realpathSync(atomBinPath)) + expect(fs.isExecutableSync(installedAtomPath)).toBe(true) + expect(fs.isFileSync(path.join(installationPath, 'atom'))).toBe(false) + done() + }) + }) + }) + + it("symlinks the apm command as 'apm-nightly'", () => { + const installedApmPath = path.join(installationPath, 'apm-nightly') + expect(fs.isFileSync(installedApmPath)).toBeFalsy() + + waitsFor(done => { + installer.installApmCommand(false, error => { + expect(error).toBeNull() + expect(fs.realpathSync(installedApmPath)).toBe(fs.realpathSync(apmBinPath)) + expect(fs.isExecutableSync(installedApmPath)).toBeTruthy() + expect(fs.isFileSync(path.join(installationPath, 'nightly'))).toBe(false) + done() + }) + }) + }) + }) }) diff --git a/spec/config-file-spec.js b/spec/config-file-spec.js index 8b3c3ee62..ae5e05fe6 100644 --- a/spec/config-file-spec.js +++ b/spec/config-file-spec.js @@ -62,7 +62,7 @@ describe('ConfigFile', () => { }) }) - describe('when the file is updated with invalid CSON', () => { + describe('when the file is updated with invalid CSON', () => { it('notifies onDidError observers', async () => { configFile = new ConfigFile(filePath) subscription = await configFile.watch() @@ -91,6 +91,27 @@ describe('ConfigFile', () => { }) }) }) + + describe('ConfigFile.at()', () => { + let path0, path1 + + beforeEach(() => { + path0 = filePath + path1 = path.join(fs.realpathSync(temp.mkdirSync()), 'the-config.cson') + + configFile = ConfigFile.at(path0) + }) + + it('returns an existing ConfigFile', () => { + const cf = ConfigFile.at(path0) + expect(cf).toEqual(configFile) + }) + + it('creates a new ConfigFile for unrecognized paths', () => { + const cf = ConfigFile.at(path1) + expect(cf).not.toEqual(configFile) + }) + }) }) function writeFileSync (filePath, content, seconds = 2) { diff --git a/spec/config-spec.js b/spec/config-spec.js index b618d7fa2..53cf9fffc 100644 --- a/spec/config-spec.js +++ b/spec/config-spec.js @@ -108,17 +108,6 @@ describe('Config', () => { expect(atom.config.get('foo.bar.baz', {scope: ['.source.coffee']})).toBe(100) }) ) - - describe('when the first component of the scope descriptor matches a legacy scope alias', () => - it('falls back to properties defined for the legacy scope if no value is found for the original scope descriptor', () => { - atom.config.setLegacyScopeAliasForNewScope('javascript', '.source.js') - atom.config.set('foo', 100, {scopeSelector: '.source.js'}) - atom.config.set('foo', 200, {scopeSelector: 'javascript for_statement'}) - - expect(atom.config.get('foo', {scope: ['javascript', 'for_statement', 'identifier']})).toBe(200) - expect(atom.config.get('foo', {scope: ['javascript', 'function', 'identifier']})).toBe(100) - }) - ) }) }) @@ -147,22 +136,6 @@ describe('Config', () => { {scopeSelector: '*', value: 40} ]) }) - - describe('when the first component of the scope descriptor matches a legacy scope alias', () => - it('includes the values defined for the legacy scope', () => { - atom.config.setLegacyScopeAliasForNewScope('javascript', '.source.js') - - expect(atom.config.set('foo', 41)).toBe(true) - expect(atom.config.set('foo', 42, {scopeSelector: 'javascript'})).toBe(true) - expect(atom.config.set('foo', 43, {scopeSelector: '.source.js'})).toBe(true) - - expect(atom.config.getAll('foo', {scope: ['javascript']})).toEqual([ - {scopeSelector: 'javascript', value: 42}, - {scopeSelector: '.js.source', value: 43}, - {scopeSelector: '*', value: 41} - ]) - }) - ) }) describe('.set(keyPath, value, {source, scopeSelector})', () => { diff --git a/spec/dock-spec.js b/spec/dock-spec.js index 6cdbc21f0..4713347a8 100644 --- a/spec/dock-spec.js +++ b/spec/dock-spec.js @@ -3,6 +3,9 @@ const Grim = require('grim') import {it, fit, ffit, fffit, beforeEach, afterEach} from './async-spec-helpers' +import etch from 'etch' + +const getNextUpdatePromise = () => etch.getScheduler().nextUpdatePromise describe('Dock', () => { describe('when a dock is activated', () => { @@ -157,8 +160,10 @@ describe('Dock', () => { const dockElement = dock.getElement() dock.setState({size: 300}) + await getNextUpdatePromise() expect(dockElement.offsetWidth).toBe(300) dockElement.querySelector('.atom-dock-resize-handle').dispatchEvent(new MouseEvent('mousedown', {detail: 2})) + await getNextUpdatePromise() expect(dockElement.offsetWidth).toBe(item.getPreferredWidth()) }) @@ -178,8 +183,10 @@ describe('Dock', () => { const dockElement = dock.getElement() dock.setState({size: 300}) + await getNextUpdatePromise() expect(dockElement.offsetHeight).toBe(300) dockElement.querySelector('.atom-dock-resize-handle').dispatchEvent(new MouseEvent('mousedown', {detail: 2})) + await getNextUpdatePromise() expect(dockElement.offsetHeight).toBe(item.getPreferredHeight()) }) @@ -310,7 +317,7 @@ describe('Dock', () => { }) describe('drag handling', () => { - it('expands docks to match the preferred size of the dragged item', () => { + it('expands docks to match the preferred size of the dragged item', async () => { jasmine.attachToDOM(atom.workspace.getElement()) const element = document.createElement('div') @@ -325,7 +332,8 @@ describe('Dock', () => { Object.defineProperty(dragEvent, 'target', {value: element}) atom.workspace.getElement().handleDragStart(dragEvent) - expect(atom.workspace.getLeftDock().wrapperElement.offsetWidth).toBe(144) + await getNextUpdatePromise() + expect(atom.workspace.getLeftDock().refs.wrapperElement.offsetWidth).toBe(144) }) it('does nothing when text nodes are dragged', () => { diff --git a/spec/fixtures/babel/flow-slash-comment.js b/spec/fixtures/babel/flow-slash-comment.js new file mode 100644 index 000000000..b73cc7833 --- /dev/null +++ b/spec/fixtures/babel/flow-slash-comment.js @@ -0,0 +1,4 @@ +// @flow + +const f: Function = v => v + 1 +module.exports = f diff --git a/spec/fixtures/git/master.git/config b/spec/fixtures/git/master.git/config index af107929f..c9da546d6 100644 --- a/spec/fixtures/git/master.git/config +++ b/spec/fixtures/git/master.git/config @@ -4,3 +4,6 @@ bare = false logallrefupdates = true ignorecase = true +[remote "origin"] + url = https://github.com/example-user/example-repo.git + fetch = +refs/heads/*:refs/remotes/origin/* diff --git a/spec/fixtures/packages/package-with-tree-sitter-grammar/grammars/some-language.cson b/spec/fixtures/packages/package-with-tree-sitter-grammar/grammars/some-language.cson index 5eb473456..f6b32e532 100644 --- a/spec/fixtures/packages/package-with-tree-sitter-grammar/grammars/some-language.cson +++ b/spec/fixtures/packages/package-with-tree-sitter-grammar/grammars/some-language.cson @@ -1,6 +1,6 @@ name: 'Some Language' -id: 'some-language' +scopeName: 'some-language' type: 'tree-sitter' diff --git a/spec/grammar-registry-spec.js b/spec/grammar-registry-spec.js index 93f83eb26..fb0a4fb1f 100644 --- a/spec/grammar-registry-spec.js +++ b/spec/grammar-registry-spec.js @@ -14,6 +14,7 @@ describe('GrammarRegistry', () => { beforeEach(() => { grammarRegistry = new GrammarRegistry({config: atom.config}) + expect(subscriptionCount(grammarRegistry)).toBe(1) }) describe('.assignLanguageMode(buffer, languageId)', () => { @@ -54,13 +55,13 @@ describe('GrammarRegistry', () => { }) describe('.grammarForId(languageId)', () => { - it('converts the language id to a text-mate language id when `core.useTreeSitterParsers` is false', () => { + it('returns a text-mate grammar when `core.useTreeSitterParsers` is false', () => { atom.config.set('core.useTreeSitterParsers', false) grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/javascript.cson')) grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/tree-sitter-javascript.cson')) - const grammar = grammarRegistry.grammarForId('javascript') + const grammar = grammarRegistry.grammarForId('source.js') expect(grammar instanceof FirstMate.Grammar).toBe(true) expect(grammar.scopeName).toBe('source.js') @@ -68,7 +69,7 @@ describe('GrammarRegistry', () => { expect(grammarRegistry.grammarForId('javascript')).toBe(undefined) }) - it('converts the language id to a tree-sitter language id when `core.useTreeSitterParsers` is true', () => { + it('returns a tree-sitter grammar when `core.useTreeSitterParsers` is true', () => { atom.config.set('core.useTreeSitterParsers', true) grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/javascript.cson')) @@ -76,7 +77,7 @@ describe('GrammarRegistry', () => { const grammar = grammarRegistry.grammarForId('source.js') expect(grammar instanceof TreeSitterGrammar).toBe(true) - expect(grammar.id).toBe('javascript') + expect(grammar.scopeName).toBe('source.js') grammarRegistry.removeGrammar(grammar) expect(grammarRegistry.grammarForId('source.js') instanceof FirstMate.Grammar).toBe(true) @@ -122,11 +123,11 @@ describe('GrammarRegistry', () => { buffer.setPath('test.js') grammarRegistry.maintainLanguageMode(buffer) - grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/javascript.cson')) - expect(buffer.getLanguageMode().getLanguageId()).toBe('source.js') + const textMateGrammar = grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/javascript.cson')) + expect(buffer.getLanguageMode().grammar).toBe(textMateGrammar) grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/tree-sitter-javascript.cson')) - expect(buffer.getLanguageMode().getLanguageId()).toBe('source.js') + expect(buffer.getLanguageMode().grammar).toBe(textMateGrammar) }) it('updates the buffer\'s grammar when a more appropriate tree-sitter grammar is added for its path', async () => { @@ -138,11 +139,11 @@ describe('GrammarRegistry', () => { buffer.setPath('test.js') grammarRegistry.maintainLanguageMode(buffer) - grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/tree-sitter-javascript.cson')) - expect(buffer.getLanguageMode().getLanguageId()).toBe('javascript') + const treeSitterGrammar = grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/tree-sitter-javascript.cson')) + expect(buffer.getLanguageMode().grammar).toBe(treeSitterGrammar) grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/javascript.cson')) - expect(buffer.getLanguageMode().getLanguageId()).toBe('javascript') + expect(buffer.getLanguageMode().grammar).toBe(treeSitterGrammar) }) it('can be overridden by calling .assignLanguageMode', () => { @@ -207,16 +208,16 @@ describe('GrammarRegistry', () => { const disposable = grammarRegistry.maintainLanguageMode(buffer) expect(retainedBufferCount(grammarRegistry)).toBe(1) - expect(subscriptionCount(grammarRegistry)).toBe(2) + expect(subscriptionCount(grammarRegistry)).toBe(3) buffer.destroy() expect(retainedBufferCount(grammarRegistry)).toBe(0) - expect(subscriptionCount(grammarRegistry)).toBe(0) + expect(subscriptionCount(grammarRegistry)).toBe(1) expect(buffer.emitter.getTotalListenerCount()).toBe(0) disposable.dispose() expect(retainedBufferCount(grammarRegistry)).toBe(0) - expect(subscriptionCount(grammarRegistry)).toBe(0) + expect(subscriptionCount(grammarRegistry)).toBe(1) }) it('does not retain the buffer when the grammar registry is destroyed', () => { @@ -225,12 +226,12 @@ describe('GrammarRegistry', () => { const disposable = grammarRegistry.maintainLanguageMode(buffer) expect(retainedBufferCount(grammarRegistry)).toBe(1) - expect(subscriptionCount(grammarRegistry)).toBe(2) + expect(subscriptionCount(grammarRegistry)).toBe(3) grammarRegistry.clear() expect(retainedBufferCount(grammarRegistry)).toBe(0) - expect(subscriptionCount(grammarRegistry)).toBe(0) + expect(subscriptionCount(grammarRegistry)).toBe(1) expect(buffer.emitter.getTotalListenerCount()).toBe(0) }) }) @@ -282,32 +283,6 @@ describe('GrammarRegistry', () => { expect(atom.grammars.selectGrammar('/hu.git/config').name).toBe('Null Grammar') }) - describe('when the grammar has a contentRegExp field', () => { - it('favors grammars whose contentRegExp matches a prefix of the file\'s content', () => { - atom.grammars.addGrammar({ - id: 'javascript-1', - fileTypes: ['js'] - }) - atom.grammars.addGrammar({ - id: 'flow-javascript', - contentRegExp: new RegExp('//.*@flow'), - fileTypes: ['js'] - }) - atom.grammars.addGrammar({ - id: 'javascript-2', - fileTypes: ['js'] - }) - - const selectedGrammar = atom.grammars.selectGrammar('test.js', dedent` - // Copyright EvilCorp - // @flow - - module.exports = function () { return 1 + 1 } - `) - expect(selectedGrammar.id).toBe('flow-javascript') - }) - }) - it("uses the filePath's shebang line if the grammar cannot be determined by the extension or basename", async () => { await atom.packages.activatePackage('language-javascript') await atom.packages.activatePackage('language-ruby') @@ -437,9 +412,127 @@ describe('GrammarRegistry', () => { grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/tree-sitter-javascript.cson')) const grammar = grammarRegistry.selectGrammar('test.js') - expect(grammar.id).toBe('javascript') expect(grammar instanceof TreeSitterGrammar).toBe(true) }) + + it('only favors a tree-sitter grammar if it actually matches in some way (regression)', () => { + atom.config.set('core.useTreeSitterParsers', true) + grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/tree-sitter-javascript.cson')) + + const grammar = grammarRegistry.selectGrammar('test', '') + expect(grammar.name).toBe('Null Grammar') + }) + }) + + describe('tree-sitter grammars with content regexes', () => { + it('recognizes C++ header files', () => { + atom.config.set('core.useTreeSitterParsers', true) + grammarRegistry.loadGrammarSync(require.resolve('language-c/grammars/tree-sitter-c.cson')) + grammarRegistry.loadGrammarSync(require.resolve('language-c/grammars/tree-sitter-cpp.cson')) + grammarRegistry.loadGrammarSync(require.resolve('language-coffee-script/grammars/coffeescript.cson')) + + let grammar = grammarRegistry.selectGrammar('test.h', dedent ` + #include + + typedef struct { + void verb(); + } Noun; + `) + expect(grammar.name).toBe('C') + + grammar = grammarRegistry.selectGrammar('test.h', dedent ` + #include + + class Noun { + public: + void verb(); + }; + `) + expect(grammar.name).toBe('C++') + + // The word `class` only indicates C++ in `.h` files, not in all files. + grammar = grammarRegistry.selectGrammar('test.coffee', dedent ` + module.exports = + class Noun + verb: -> true + `) + expect(grammar.name).toBe('CoffeeScript') + }) + + it('recognizes C++ files that do not match the content regex (regression)', () => { + atom.config.set('core.useTreeSitterParsers', true) + grammarRegistry.loadGrammarSync(require.resolve('language-c/grammars/tree-sitter-c.cson')) + grammarRegistry.loadGrammarSync(require.resolve('language-c/grammars/c++.cson')) + grammarRegistry.loadGrammarSync(require.resolve('language-c/grammars/tree-sitter-cpp.cson')) + + let grammar = grammarRegistry.selectGrammar('test.cc', dedent ` + int a(); + `) + expect(grammar.name).toBe('C++') + }) + + it('does not apply content regexes from grammars without filetype or first line matches', () => { + atom.config.set('core.useTreeSitterParsers', true) + grammarRegistry.loadGrammarSync(require.resolve('language-c/grammars/tree-sitter-cpp.cson')) + + let grammar = grammarRegistry.selectGrammar('', dedent ` + class Foo + # this is ruby, not C++ + end + `) + + expect(grammar.name).toBe('Null Grammar') + }) + + it('recognizes shell scripts with shebang lines', () => { + atom.config.set('core.useTreeSitterParsers', true) + grammarRegistry.loadGrammarSync(require.resolve('language-shellscript/grammars/shell-unix-bash.cson')) + grammarRegistry.loadGrammarSync(require.resolve('language-shellscript/grammars/tree-sitter-bash.cson')) + + let grammar = grammarRegistry.selectGrammar('test.h', dedent ` + #!/bin/bash + + echo "hi" + `) + expect(grammar.name).toBe('Shell Script') + expect(grammar instanceof TreeSitterGrammar).toBeTruthy() + + grammar = grammarRegistry.selectGrammar('test.h', dedent ` + # vim: set ft=bash + + echo "hi" + `) + expect(grammar.name).toBe('Shell Script') + expect(grammar instanceof TreeSitterGrammar).toBeTruthy() + + atom.config.set('core.useTreeSitterParsers', false) + grammar = grammarRegistry.selectGrammar('test.h', dedent ` + #!/bin/bash + + echo "hi" + `) + expect(grammar.name).toBe('Shell Script') + expect(grammar instanceof TreeSitterGrammar).toBeFalsy() + }) + + it('recognizes JavaScript files that use Flow', () => { + atom.config.set('core.useTreeSitterParsers', true) + grammarRegistry.loadGrammarSync(require.resolve('language-javascript/grammars/tree-sitter-javascript.cson')) + grammarRegistry.loadGrammarSync(require.resolve('language-typescript/grammars/tree-sitter-flow.cson')) + + let grammar = grammarRegistry.selectGrammar('test.js', dedent` + // Copyright something + // @flow + + module.exports = function () { return 1 + 1 } + `) + expect(grammar.name).toBe('Flow JavaScript') + + grammar = grammarRegistry.selectGrammar('test.js', dedent` + module.exports = function () { return 1 + 1 } + `) + expect(grammar.name).toBe('JavaScript') + }) }) }) @@ -452,6 +545,34 @@ describe('GrammarRegistry', () => { }) }) + describe('.addInjectionPoint(languageId, {type, language, content})', () => { + const injectionPoint = { + type: 'some_node_type', + language() { return 'some_language_name' }, + content(node) { return node } + } + + beforeEach(() => { + atom.config.set('core.useTreeSitterParsers', true) + }) + + it('adds an injection point to the grammar with the given id', async () => { + await atom.packages.activatePackage('language-javascript') + atom.grammars.addInjectionPoint('javascript', injectionPoint) + const grammar = atom.grammars.grammarForId('javascript') + expect(grammar.injectionPoints).toContain(injectionPoint) + }) + + describe('when called before a grammar with the given id is loaded', () => { + it('adds the injection point once the grammar is loaded', async () => { + atom.grammars.addInjectionPoint('javascript', injectionPoint) + await atom.packages.activatePackage('language-javascript') + const grammar = atom.grammars.grammarForId('javascript') + expect(grammar.injectionPoints).toContain(injectionPoint) + }) + }) + }) + describe('serialization', () => { it('persists editors\' grammar overrides', async () => { const buffer1 = new TextBuffer() diff --git a/spec/main-process/atom-application.test.js b/spec/main-process/atom-application.test.js index 16aef8e27..c49e36b5d 100644 --- a/spec/main-process/atom-application.test.js +++ b/spec/main-process/atom-application.test.js @@ -606,6 +606,8 @@ describe('AtomApplication', function () { assert(!electron.app.didQuit()) await Promise.all([window1.lastPrepareToUnloadPromise, window2.lastPrepareToUnloadPromise]) + assert(!electron.app.didQuit()) + await atomApplication.lastBeforeQuitPromise await new Promise(process.nextTick) assert(electron.app.didQuit()) }) @@ -634,6 +636,29 @@ describe('AtomApplication', function () { assert(electron.app.didQuit()) }) + it('closes successfully unloaded windows when quitting', async () => { + const atomApplication = buildAtomApplication() + const [window1] = await atomApplication.launch(parseCommandLine([])) + const [window2] = await atomApplication.launch(parseCommandLine([])) + await Promise.all([window1.loadedPromise, window2.loadedPromise]) + await evalInWebContents(window1.browserWindow.webContents, sendBackToMainProcess => { + atom.workspace.getActiveTextEditor().insertText('unsaved text') + sendBackToMainProcess() + }) + + // Choosing "Cancel" + mockElectronShowMessageBox({response: 1}) + electron.app.quit() + await atomApplication.lastBeforeQuitPromise + assert(atomApplication.getAllWindows().length === 1) + + // Choosing "Don't save" + mockElectronShowMessageBox({response: 2}) + electron.app.quit() + await atomApplication.lastBeforeQuitPromise + assert(atomApplication.getAllWindows().length === 0) + }) + function buildAtomApplication (params = {}) { const atomApplication = new AtomApplication(Object.assign({ resourcePath: ATOM_RESOURCE_PATH, diff --git a/spec/main-process/file-recovery-service.test.js b/spec/main-process/file-recovery-service.test.js index 2a8f2088c..45c10c25b 100644 --- a/spec/main-process/file-recovery-service.test.js +++ b/spec/main-process/file-recovery-service.test.js @@ -1,6 +1,8 @@ const {dialog} = require('electron') const FileRecoveryService = require('../../src/main-process/file-recovery-service') const fs = require('fs-plus') +const fsreal = require('fs') +const EventEmitter = require('events').EventEmitter const sinon = require('sinon') const {escapeRegExp} = require('underscore-plus') const temp = require('temp').track() @@ -116,13 +118,22 @@ describe("FileRecoveryService", () => { const mockWindow = {} const filePath = temp.path() fs.writeFileSync(filePath, "content") - fs.chmodSync(filePath, 0444) let logs = [] spies.stub(console, 'log', (message) => logs.push(message)) spies.stub(dialog, 'showMessageBox') + // Copy files to be recovered before mocking fs.createWriteStream await recoveryService.willSavePath(mockWindow, filePath) + + // Stub out fs.createWriteStream so that we can return a fake error when + // attempting to copy the recovered file to its original location + var fakeEmitter = new EventEmitter() + var onStub = spies.stub(fakeEmitter, 'on') + onStub.withArgs('error').yields(new Error('Nope')).returns(fakeEmitter) + onStub.withArgs('open').returns(fakeEmitter) + spies.stub(fsreal, 'createWriteStream').withArgs(filePath).returns(fakeEmitter) + await recoveryService.didCrashWindow(mockWindow) let recoveryFiles = fs.listTreeSync(recoveryDirectory) assert.equal(recoveryFiles.length, 1) diff --git a/spec/main-process/mocha-test-runner.js b/spec/main-process/mocha-test-runner.js index 433727c56..61d533417 100644 --- a/spec/main-process/mocha-test-runner.js +++ b/spec/main-process/mocha-test-runner.js @@ -1,10 +1,9 @@ -"use babel" +const Mocha = require('mocha') +const fs = require('fs-plus') +const {assert} = require('chai') -import Mocha from 'mocha' -import fs from 'fs-plus' -import {assert} from 'chai' - -export default function (testPaths) { +module.exports = +function (testPaths) { global.assert = assert let reporterOptions = { @@ -24,6 +23,7 @@ export default function (testPaths) { reporter: 'mocha-multi-reporters', reporterOptions }) + for (let testPath of testPaths) { if (fs.isDirectorySync(testPath)) { for (let testFilePath of fs.listTreeSync(testPath)) { @@ -36,7 +36,7 @@ export default function (testPaths) { } } - mocha.run(function (failures) { + mocha.run(failures => { if (failures === 0) { process.exit(0) } else { diff --git a/spec/main-process/parse-command-line.test.js b/spec/main-process/parse-command-line.test.js index 0cd1f5b13..bb5d625a9 100644 --- a/spec/main-process/parse-command-line.test.js +++ b/spec/main-process/parse-command-line.test.js @@ -1,10 +1,8 @@ -/** @babel */ +const parseCommandLine = require('../../src/main-process/parse-command-line') -import parseCommandLine from '../../src/main-process/parse-command-line' - -describe('parseCommandLine', function () { - describe('when --uri-handler is not passed', function () { - it('parses arguments as normal', function () { +describe('parseCommandLine', () => { + describe('when --uri-handler is not passed', () => { + it('parses arguments as normal', () => { const args = parseCommandLine(['-d', '--safe', '--test', '/some/path', 'atom://test/url', 'atom://other/url']) assert.isTrue(args.devMode) assert.isTrue(args.safeMode) @@ -14,8 +12,8 @@ describe('parseCommandLine', function () { }) }) - describe('when --uri-handler is passed', function () { - it('ignores other arguments and limits to one URL', function () { + describe('when --uri-handler is passed', () => { + it('ignores other arguments and limits to one URL', () => { const args = parseCommandLine(['-d', '--uri-handler', '--safe', '--test', '/some/path', 'atom://test/url', 'atom://other/url']) assert.isUndefined(args.devMode) assert.isUndefined(args.safeMode) diff --git a/spec/menu-manager-spec.coffee b/spec/menu-manager-spec.coffee index 3bbd8b9da..c7b15aae6 100644 --- a/spec/menu-manager-spec.coffee +++ b/spec/menu-manager-spec.coffee @@ -58,10 +58,8 @@ describe "MenuManager", -> menu.add [{label: "A", submenu: [{label: "B", command: "b"}]}] atom.keymaps.add 'test', 'atom-workspace': 'ctrl-b': 'b' menu.update() - - waits 50 - - runs -> expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toEqual ['ctrl-b'] + advanceClock(1) + expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toEqual ['ctrl-b'] it "omits key bindings that are mapped to unset! in any context", -> # it would be nice to be smarter about omitting, but that would require a much @@ -69,10 +67,8 @@ describe "MenuManager", -> menu.add [{label: "A", submenu: [{label: "B", command: "b"}]}] atom.keymaps.add 'test', 'atom-workspace': 'ctrl-b': 'b' atom.keymaps.add 'test', 'atom-text-editor': 'ctrl-b': 'unset!' - - waits 50 - - runs -> expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toBeUndefined() + advanceClock(1) + expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toBeUndefined() it "omits key bindings that could conflict with AltGraph characters on macOS", -> Object.defineProperty process, 'platform', value: 'darwin' @@ -87,12 +83,10 @@ describe "MenuManager", -> 'alt-shift-C': 'c' 'alt-cmd-d': 'd' - waits 50 - - runs -> - expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toBeUndefined() - expect(menu.sendToBrowserProcess.argsForCall[0][1]['c']).toBeUndefined() - expect(menu.sendToBrowserProcess.argsForCall[0][1]['d']).toEqual(['alt-cmd-d']) + advanceClock(1) + expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toBeUndefined() + expect(menu.sendToBrowserProcess.argsForCall[0][1]['c']).toBeUndefined() + expect(menu.sendToBrowserProcess.argsForCall[0][1]['d']).toEqual(['alt-cmd-d']) it "omits key bindings that could conflict with AltGraph characters on Windows", -> Object.defineProperty process, 'platform', value: 'win32' @@ -107,12 +101,10 @@ describe "MenuManager", -> 'ctrl-alt-shift-C': 'c' 'ctrl-alt-cmd-d': 'd' - waits 50 - - runs -> - expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toBeUndefined() - expect(menu.sendToBrowserProcess.argsForCall[0][1]['c']).toBeUndefined() - expect(menu.sendToBrowserProcess.argsForCall[0][1]['d']).toEqual(['ctrl-alt-cmd-d']) + advanceClock(1) + expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toBeUndefined() + expect(menu.sendToBrowserProcess.argsForCall[0][1]['c']).toBeUndefined() + expect(menu.sendToBrowserProcess.argsForCall[0][1]['d']).toEqual(['ctrl-alt-cmd-d']) it "updates the application menu when a keymap is reloaded", -> spyOn(menu, 'update') diff --git a/spec/package-manager-spec.js b/spec/package-manager-spec.js index b1ecf834d..dd87f85fa 100644 --- a/spec/package-manager-spec.js +++ b/spec/package-manager-spec.js @@ -30,13 +30,15 @@ describe('PackageManager', () => { expect(packageManger.packageDirPaths[0]).toBe(path.join(configDirPath, 'packages')) }) - it('adds regular package path and dev package path in dev mode', () => { + it('adds regular package path, dev package path, and Atom repo package path in dev mode and dev resource path is set', () => { const packageManger = new PackageManager({}) const configDirPath = path.join('~', 'someConfig') - packageManger.initialize({configDirPath, devMode: true}) - expect(packageManger.packageDirPaths.length).toBe(2) + const resourcePath = path.join('~', '/atom') + packageManger.initialize({configDirPath, resourcePath, devMode: true}) + expect(packageManger.packageDirPaths.length).toBe(3) expect(packageManger.packageDirPaths).toContain(path.join(configDirPath, 'packages')) expect(packageManger.packageDirPaths).toContain(path.join(configDirPath, 'dev', 'packages')) + expect(packageManger.packageDirPaths).toContain(path.join(resourcePath, 'packages')) }) }) @@ -1032,6 +1034,7 @@ describe('PackageManager', () => { }) it('loads any tree-sitter grammars defined in the package', async () => { + atom.config.set('core.useTreeSitterParsers', true) await atom.packages.activatePackage('package-with-tree-sitter-grammar') const grammar = atom.grammars.selectGrammar('test.somelang') expect(grammar.name).toBe('Some Language') diff --git a/spec/pane-spec.js b/spec/pane-spec.js index 8ef274c2d..ddb92b96e 100644 --- a/spec/pane-spec.js +++ b/spec/pane-spec.js @@ -219,6 +219,34 @@ describe('Pane', () => { runs(() => expect(eventOrder).toEqual(['add', 'remove'])) }) + it('subscribes to be notified when item terminates its pending state', () => { + const fakeDisposable = { dispose: () => {} } + const spy = jasmine.createSpy('onDidTerminatePendingState').andReturn((fakeDisposable)) + + const pane = new Pane(paneParams({items: []})) + const item = { + getTitle: () => '', + onDidTerminatePendingState: spy + } + pane.addItem(item) + + expect(spy).toHaveBeenCalled() + }) + + it('subscribes to be notified when item is destroyed', () => { + const fakeDisposable = { dispose: () => {} } + const spy = jasmine.createSpy('onDidDestroy').andReturn((fakeDisposable)) + + const pane = new Pane(paneParams({items: []})) + const item = { + getTitle: () => '', + onDidDestroy: spy + } + pane.addItem(item) + + expect(spy).toHaveBeenCalled() + }) + describe('when using the old API of ::addItem(item, index)', () => { beforeEach(() => spyOn(Grim, 'deprecate')) diff --git a/spec/project-spec.js b/spec/project-spec.js index 2d38058fe..861a0f53a 100644 --- a/spec/project-spec.js +++ b/spec/project-spec.js @@ -969,6 +969,77 @@ describe('Project', () => { }) }) + describe('.observeRepositories()', () => { + it('invokes the observer with current and future repositories', () => { + const observed = [] + + const directory1 = temp.mkdirSync('git-repo1') + const gitDirPath1 = fs.absolute(path.join(__dirname, 'fixtures', 'git', 'master.git')) + fs.copySync(gitDirPath1, path.join(directory1, '.git')) + + const directory2 = temp.mkdirSync('git-repo2') + const gitDirPath2 = fs.absolute(path.join(__dirname, 'fixtures', 'git', 'repo-with-submodules', 'git.git')) + fs.copySync(gitDirPath2, path.join(directory2, '.git')) + + atom.project.setPaths([directory1]) + + const disposable = atom.project.observeRepositories((repo) => observed.push(repo)) + expect(observed.length).toBe(1) + expect(observed[0].getReferenceTarget('refs/heads/master')).toBe('ef046e9eecaa5255ea5e9817132d4001724d6ae1') + + atom.project.addPath(directory2) + expect(observed.length).toBe(2) + expect(observed[1].getReferenceTarget('refs/heads/master')).toBe('d2b0ad9cbc6f6c4372e8956e5cc5af771b2342e5') + + disposable.dispose() + }) + }) + + describe('.onDidAddRepository()', () => { + it('invokes callback when a path is added and the path is the root of a repository', () => { + const observed = [] + const disposable = atom.project.onDidAddRepository((repo) => observed.push(repo)) + + const projectRootPath = temp.mkdirSync() + const fixtureRepoPath = fs.absolute(path.join(__dirname, 'fixtures', 'git', 'master.git')) + fs.copySync(fixtureRepoPath, path.join(projectRootPath, '.git')) + + atom.project.addPath(projectRootPath) + expect(observed.length).toBe(1) + expect(observed[0].getOriginURL()).toEqual('https://github.com/example-user/example-repo.git') + + disposable.dispose() + }) + + it('invokes callback when a path is added and the path is subdirectory of a repository', () => { + const observed = [] + const disposable = atom.project.onDidAddRepository((repo) => observed.push(repo)) + + const projectRootPath = temp.mkdirSync() + const fixtureRepoPath = fs.absolute(path.join(__dirname, 'fixtures', 'git', 'master.git')) + fs.copySync(fixtureRepoPath, path.join(projectRootPath, '.git')) + + const projectSubDirPath = path.join(projectRootPath, 'sub-dir') + fs.mkdirSync(projectSubDirPath) + + atom.project.addPath(projectSubDirPath) + expect(observed.length).toBe(1) + expect(observed[0].getOriginURL()).toEqual('https://github.com/example-user/example-repo.git') + + disposable.dispose() + }) + + it('does not invoke callback when a path is added and the path is not part of a repository', () => { + const observed = [] + const disposable = atom.project.onDidAddRepository((repo) => observed.push(repo)) + + atom.project.addPath(temp.mkdirSync('not-a-repository')) + expect(observed.length).toBe(0) + + disposable.dispose() + }) + }) + describe('.relativize(path)', () => { it('returns the path, relative to whichever root directory it is inside of', () => { atom.project.addPath(temp.mkdirSync('another-path')) diff --git a/spec/sample-with-comments.js b/spec/sample-with-comments.js deleted file mode 100644 index 66dc9051d..000000000 --- a/spec/sample-with-comments.js +++ /dev/null @@ -1 +0,0 @@ -undefined \ No newline at end of file diff --git a/spec/selection-spec.js b/spec/selection-spec.js index cb586da26..e9cf1c617 100644 --- a/spec/selection-spec.js +++ b/spec/selection-spec.js @@ -85,6 +85,17 @@ describe('Selection', () => { }) }) + describe("when the selection's range is moved", () => { + it('notifies ::onDidChangeRange observers', () => { + selection.setBufferRange([[2, 0], [2, 10]]) + const changeScreenRangeHandler = jasmine.createSpy('changeScreenRangeHandler') + selection.onDidChangeRange(changeScreenRangeHandler) + buffer.insert([2, 5], 'abc') + expect(changeScreenRangeHandler).toHaveBeenCalled() + expect(changeScreenRangeHandler.mostRecentCall.args[0]).not.toBeUndefined() + }); + }); + describe("when only the selection's tail is moved (regression)", () => { it('notifies ::onDidChangeRange observers', () => { selection.setBufferRange([[2, 0], [2, 10]], {reversed: true}) @@ -93,6 +104,7 @@ describe('Selection', () => { buffer.insert([2, 5], 'abc') expect(changeScreenRangeHandler).toHaveBeenCalled() + expect(changeScreenRangeHandler.mostRecentCall.args[0]).not.toBeUndefined() }) }) @@ -154,4 +166,118 @@ describe('Selection', () => { expect(editor.isFoldedAtBufferRow(0)).toBe(false) }) }) + + describe('within a read-only editor', () => { + beforeEach(() => { + editor.setReadOnly(true) + selection.setBufferRange([[0, 0], [0, 13]]) + }) + + const modifications = [ + { + name: 'insertText', + op: opts => selection.insertText('yes', opts) + }, + { + name: 'backspace', + op: opts => selection.backspace(opts) + }, + { + name: 'deleteToPreviousWordBoundary', + op: opts => selection.deleteToPreviousWordBoundary(opts) + }, + { + name: 'deleteToNextWordBoundary', + op: opts => selection.deleteToNextWordBoundary(opts) + }, + { + name: 'deleteToBeginningOfWord', + op: opts => selection.deleteToBeginningOfWord(opts) + }, + { + name: 'deleteToBeginningOfLine', + op: opts => selection.deleteToBeginningOfLine(opts) + }, + { + name: 'delete', + op: opts => selection.delete(opts) + }, + { + name: 'deleteToEndOfLine', + op: opts => selection.deleteToEndOfLine(opts) + }, + { + name: 'deleteToEndOfWord', + op: opts => selection.deleteToEndOfWord(opts) + }, + { + name: 'deleteToBeginningOfSubword', + op: opts => selection.deleteToBeginningOfSubword(opts) + }, + { + name: 'deleteToEndOfSubword', + op: opts => selection.deleteToEndOfSubword(opts) + }, + { + name: 'deleteSelectedText', + op: opts => selection.deleteSelectedText(opts) + }, + { + name: 'deleteLine', + op: opts => selection.deleteLine(opts) + }, + { + name: 'joinLines', + op: opts => selection.joinLines(opts) + }, + { + name: 'outdentSelectedRows', + op: opts => selection.outdentSelectedRows(opts) + }, + { + name: 'autoIndentSelectedRows', + op: opts => selection.autoIndentSelectedRows(opts) + }, + { + name: 'toggleLineComments', + op: opts => selection.toggleLineComments(opts) + }, + { + name: 'cutToEndOfLine', + op: opts => selection.cutToEndOfLine(false, opts) + }, + { + name: 'cutToEndOfBufferLine', + op: opts => selection.cutToEndOfBufferLine(false, opts) + }, + { + name: 'cut', + op: opts => selection.cut(false, false, opts.bypassReadOnly) + }, + { + name: 'indent', + op: opts => selection.indent(opts) + }, + { + name: 'indentSelectedRows', + op: opts => selection.indentSelectedRows(opts) + }, + ] + + describe('without bypassReadOnly', () => { + for (const {name, op} of modifications) { + it(`throws an error on ${name}`, () => { + expect(op).toThrow() + }) + } + }) + + describe('with bypassReadOnly', () => { + for (const {name, op} of modifications) { + it(`permits ${name}`, () => { + op({bypassReadOnly: true}) + }) + } + }) + }) }) diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index dcc3c6641..f4f1f3568 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -12,7 +12,7 @@ FindParentDir = require 'find-parent-dir' TextEditor = require '../src/text-editor' TextEditorElement = require '../src/text-editor-element' TextMateLanguageMode = require '../src/text-mate-language-mode' -clipboard = require '../src/safe-clipboard' +{clipboard} = require 'electron' jasmineStyle = document.createElement('style') jasmineStyle.textContent = atom.themes.loadStylesheet(atom.themes.resolveStylesheet('../static/jasmine')) diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index f2031258f..66274a99a 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -11,7 +11,7 @@ const fs = require('fs') const path = require('path') const Grim = require('grim') const electron = require('electron') -const clipboard = require('../src/safe-clipboard') +const clipboard = electron.clipboard const SAMPLE_TEXT = fs.readFileSync(path.join(__dirname, 'fixtures', 'sample.js'), 'utf8') @@ -26,6 +26,7 @@ document.registerElement('text-editor-component-test-element', { }) const editors = [] +let verticalScrollbarWidth, horizontalScrollbarHeight describe('TextEditorComponent', () => { beforeEach(() => { @@ -33,8 +34,15 @@ describe('TextEditorComponent', () => { // Force scrollbars to be visible regardless of local system configuration const scrollbarStyle = document.createElement('style') - scrollbarStyle.textContent = '::-webkit-scrollbar { -webkit-appearance: none }' + scrollbarStyle.textContent = 'atom-text-editor ::-webkit-scrollbar { -webkit-appearance: none }' jasmine.attachToDOM(scrollbarStyle) + + if (verticalScrollbarWidth == null) { + const {component, element} = buildComponent({text: 'abcdefgh\n'.repeat(10), width: 30, height: 30}) + verticalScrollbarWidth = getVerticalScrollbarWidth(component) + horizontalScrollbarHeight = getHorizontalScrollbarHeight(component) + element.remove() + } }) afterEach(() => { @@ -184,8 +192,8 @@ describe('TextEditorComponent', () => { }) it('makes the content at least as tall as the scroll container client height', async () => { - const {component, element, editor} = buildComponent({text: 'a', height: 100}) - expect(component.refs.content.offsetHeight).toBe(100) + const {component, element, editor} = buildComponent({text: 'a'.repeat(100), width: 50, height: 100}) + expect(component.refs.content.offsetHeight).toBe(100 - getHorizontalScrollbarHeight(component)) editor.setText('a\n'.repeat(30)) await component.getNextUpdatePromise() @@ -201,7 +209,7 @@ describe('TextEditorComponent', () => { await setEditorHeightInLines(component, 6) // scroll to end - await setScrollTop(component, scrollContainer.scrollHeight - scrollContainer.clientHeight) + await setScrollTop(component, Infinity) expect(component.getFirstVisibleRow()).toBe(editor.getScreenLineCount() - 3) editor.update({scrollPastEnd: false}) @@ -211,7 +219,7 @@ describe('TextEditorComponent', () => { // Always allows at least 3 lines worth of overscroll if the editor is short await setEditorHeightInLines(component, 2) await editor.update({scrollPastEnd: true}) - await setScrollTop(component, scrollContainer.scrollHeight - scrollContainer.clientHeight) + await setScrollTop(component, Infinity) expect(component.getFirstVisibleRow()).toBe(editor.getScreenLineCount() + 1) }) @@ -296,31 +304,6 @@ describe('TextEditorComponent', () => { expect(lineNumberNodeForScreenRow(component, 0).querySelector('.foldable')).toBeNull() }) - it('gracefully handles folds that change the soft-wrap boundary by causing the vertical scrollbar to disappear (regression)', async () => { - const text = ('x'.repeat(100) + '\n') + 'y\n'.repeat(28) + ' z\n'.repeat(50) - const {component, element, editor} = buildComponent({text, height: 1000, width: 500}) - - element.addEventListener('scroll', (event) => { - event.stopPropagation() - }, true) - - editor.setSoftWrapped(true) - jasmine.attachToDOM(element) - await component.getNextUpdatePromise() - - const firstScreenLineLengthWithVerticalScrollbar = element.querySelector('.line').textContent.length - - setScrollTop(component, 620) - await component.getNextUpdatePromise() - - editor.foldBufferRow(28) - await component.getNextUpdatePromise() - - const firstLineElement = element.querySelector('.line') - expect(firstLineElement.dataset.screenRow).toBe('0') - expect(firstLineElement.textContent.length).toBeGreaterThan(firstScreenLineLengthWithVerticalScrollbar) - }) - it('shows the foldable icon on the last screen row of a buffer row that can be folded', async () => { const {component, element, editor} = buildComponent({text: 'abc\n de\nfghijklm\n no', softWrapped: true}) await setEditorWidthInCharacters(component, 5) @@ -361,18 +344,14 @@ describe('TextEditorComponent', () => { expect(getVerticalScrollbarWidth(component)).toBeGreaterThan(0) expect(getHorizontalScrollbarHeight(component)).toBe(0) expect(verticalScrollbar.style.visibility).toBe('') - expect(verticalScrollbar.style.bottom).toBe('0px') expect(horizontalScrollbar.style.visibility).toBe('hidden') - expect(component.refs.scrollbarCorner).toBeUndefined() editor.setText('a'.repeat(100)) await component.getNextUpdatePromise() expect(getVerticalScrollbarWidth(component)).toBe(0) expect(getHorizontalScrollbarHeight(component)).toBeGreaterThan(0) expect(verticalScrollbar.style.visibility).toBe('hidden') - expect(horizontalScrollbar.style.right).toBe('0px') expect(horizontalScrollbar.style.visibility).toBe('') - expect(component.refs.scrollbarCorner).toBeUndefined() editor.setText('') await component.getNextUpdatePromise() @@ -380,37 +359,6 @@ describe('TextEditorComponent', () => { expect(getHorizontalScrollbarHeight(component)).toBe(0) expect(verticalScrollbar.style.visibility).toBe('hidden') expect(horizontalScrollbar.style.visibility).toBe('hidden') - expect(component.refs.scrollbarCorner).toBeUndefined() - - editor.setText(SAMPLE_TEXT) - await component.getNextUpdatePromise() - - // Does not show scrollbars if the content perfectly fits - element.style.width = component.getGutterContainerWidth() + component.getContentWidth() + 'px' - element.style.height = component.getContentHeight() + 'px' - await component.getNextUpdatePromise() - expect(getVerticalScrollbarWidth(component)).toBe(0) - expect(getHorizontalScrollbarHeight(component)).toBe(0) - expect(verticalScrollbar.style.visibility).toBe('hidden') - expect(horizontalScrollbar.style.visibility).toBe('hidden') - - // Shows scrollbars if the only reason we overflow is the presence of the - // scrollbar for the opposite axis. - element.style.width = component.getGutterContainerWidth() + component.getContentWidth() - 1 + 'px' - element.style.height = component.getContentHeight() + component.getHorizontalScrollbarHeight() - 1 + 'px' - await component.getNextUpdatePromise() - expect(getVerticalScrollbarWidth(component)).toBeGreaterThan(0) - expect(getHorizontalScrollbarHeight(component)).toBeGreaterThan(0) - expect(verticalScrollbar.style.visibility).toBe('') - expect(horizontalScrollbar.style.visibility).toBe('') - - element.style.width = component.getGutterContainerWidth() + component.getContentWidth() + component.getVerticalScrollbarWidth() - 1 + 'px' - element.style.height = component.getContentHeight() - 1 + 'px' - await component.getNextUpdatePromise() - expect(getVerticalScrollbarWidth(component)).toBeGreaterThan(0) - expect(getHorizontalScrollbarHeight(component)).toBeGreaterThan(0) - expect(verticalScrollbar.style.visibility).toBe('') - expect(horizontalScrollbar.style.visibility).toBe('') }) describe('when scrollbar styles change or the editor element is detached and then reattached', () => { @@ -564,9 +512,20 @@ describe('TextEditorComponent', () => { it('gives cursors at the end of lines the width of an "x" character', async () => { const {component, element, editor} = buildComponent() + editor.setText('abcde') + await setEditorWidthInCharacters(component, 5.5) + editor.setCursorScreenPosition([0, Infinity]) await component.getNextUpdatePromise() expect(element.querySelector('.cursor').offsetWidth).toBe(Math.round(component.getBaseCharacterWidth())) + + // Clip cursor width when soft-wrap is on and the cursor is at the end of + // the line. This prevents the parent tile from disabling sub-pixel + // anti-aliasing. For some reason, adding overflow: hidden to the cursor + // container doesn't solve this issue so we're adding this workaround instead. + editor.setSoftWrapped(true) + await component.getNextUpdatePromise() + expect(element.querySelector('.cursor').offsetWidth).toBeLessThan(Math.round(component.getBaseCharacterWidth())) }) it('positions and sizes cursors correctly when they are located next to a fold marker', async () => { @@ -672,17 +631,6 @@ describe('TextEditorComponent', () => { expect(scrollContainer.clientWidth).toBe(scrollContainer.scrollWidth) }) - it('accounts for the width of the vertical scrollbar when soft-wrapping lines', async () => { - const {component, element, editor} = buildComponent({ - height: 200, - text: 'a'.repeat(300), - softWrapped: true - }) - await setEditorWidthInCharacters(component, 23) - expect(Math.floor(component.getScrollContainerClientWidth() / component.getBaseCharacterWidth())).toBe(20) - expect(editor.lineLengthForScreenRow(0)).toBe(20) - }) - it('correctly forces the display layer to index visible rows when resizing (regression)', async () => { const text = 'a'.repeat(30) + '\n' + 'b'.repeat(1000) const {component, element, editor} = buildComponent({height: 300, width: 800, attach: false, text}) @@ -707,7 +655,7 @@ describe('TextEditorComponent', () => { editor.setText('a') await component.getNextUpdatePromise() - expect(element.querySelector('.line').offsetWidth).toBe(scrollContainer.offsetWidth) + expect(element.querySelector('.line').offsetWidth).toBe(scrollContainer.offsetWidth - verticalScrollbarWidth) }) it('resizes based on the content when the autoHeight and/or autoWidth options are true', async () => { @@ -717,44 +665,39 @@ describe('TextEditorComponent', () => { const {gutterContainer, scrollContainer} = component.refs const initialWidth = element.offsetWidth const initialHeight = element.offsetHeight - expect(initialWidth).toBe(component.getGutterContainerWidth() + component.getContentWidth() + 2 * editorPadding) - expect(initialHeight).toBe(component.getContentHeight() + 2 * editorPadding) + expect(initialWidth).toBe( + component.getGutterContainerWidth() + + component.getContentWidth() + + verticalScrollbarWidth + + 2 * editorPadding + ) + expect(initialHeight).toBe( + component.getContentHeight() + + horizontalScrollbarHeight + + 2 * editorPadding + ) // When autoWidth is enabled, width adjusts to content editor.setCursorScreenPosition([6, Infinity]) editor.insertText('x'.repeat(50)) await component.getNextUpdatePromise() - expect(element.offsetWidth).toBe(component.getGutterContainerWidth() + component.getContentWidth() + 2 * editorPadding) + expect(element.offsetWidth).toBe( + component.getGutterContainerWidth() + + component.getContentWidth() + + verticalScrollbarWidth + + 2 * editorPadding + ) expect(element.offsetWidth).toBeGreaterThan(initialWidth) // When autoHeight is enabled, height adjusts to content editor.insertText('\n'.repeat(5)) await component.getNextUpdatePromise() - expect(element.offsetHeight).toBe(component.getContentHeight() + 2 * editorPadding) - expect(element.offsetHeight).toBeGreaterThan(initialHeight) - - // When a horizontal scrollbar is visible, autoHeight accounts for it - editor.update({autoWidth: false}) - await component.getNextUpdatePromise() - element.style.width = component.getGutterContainerWidth() + component.getContentHeight() - 20 + 'px' - await component.getNextUpdatePromise() - expect(component.canScrollHorizontally()).toBe(true) - expect(component.canScrollVertically()).toBe(false) - expect(element.offsetHeight).toBe(component.getContentHeight() + component.getHorizontalScrollbarHeight() + 2 * editorPadding) - - // When a vertical scrollbar is visible, autoWidth accounts for it - editor.update({autoWidth: true, autoHeight: false}) - await component.getNextUpdatePromise() - element.style.height = component.getContentHeight() - 20 - await component.getNextUpdatePromise() - expect(component.canScrollHorizontally()).toBe(false) - expect(component.canScrollVertically()).toBe(true) - expect(element.offsetWidth).toBe( - component.getGutterContainerWidth() + - component.getContentWidth() + - component.getVerticalScrollbarWidth() + + expect(element.offsetHeight).toBe( + component.getContentHeight() + + horizontalScrollbarHeight + 2 * editorPadding ) + expect(element.offsetHeight).toBeGreaterThan(initialHeight) }) it('does not render the line number gutter at all if the isLineNumberGutterVisible parameter is false', () => { @@ -875,6 +818,18 @@ describe('TextEditorComponent', () => { expect(element.className).toBe('editor a b') }) + it('does not blow away class names managed by the component when packages change the element class name', async () => { + assertDocumentFocused() + const {component, element, editor} = buildComponent({mini: true}) + element.classList.add('a', 'b') + element.focus() + await component.getNextUpdatePromise() + expect(element.className).toBe('editor mini a b is-focused') + element.className = 'a c d'; + await component.getNextUpdatePromise() + expect(element.className).toBe('a c d editor is-focused mini') + }) + it('ignores resize events when the editor is hidden', async () => { const {component, element, editor} = buildComponent({autoHeight: false}) element.style.height = 5 * component.getLineHeight() + 'px' @@ -1040,7 +995,6 @@ describe('TextEditorComponent', () => { it('does not render scrollbars', async () => { const {component, element, editor} = buildComponent({mini: true, autoHeight: false}) await setEditorWidthInCharacters(component, 10) - await setEditorHeightInLines(component, 1) editor.setText('x'.repeat(20) + 'y'.repeat(20)) await component.getNextUpdatePromise() @@ -1125,7 +1079,7 @@ describe('TextEditorComponent', () => { describe('autoscroll', () => { it('automatically scrolls vertically when the requested range is within the vertical scroll margin of the top or bottom', async () => { - const {component, editor} = buildComponent({height: 120}) + const {component, editor} = buildComponent({height: 120 + horizontalScrollbarHeight}) expect(component.getLastVisibleRow()).toBe(7) editor.scrollToScreenRange([[4, 0], [6, 0]]) @@ -1147,7 +1101,7 @@ describe('TextEditorComponent', () => { it('does not vertically autoscroll by more than half of the visible lines if the editor is shorter than twice the scroll margin', async () => { const {component, element, editor} = buildComponent({autoHeight: false}) - element.style.height = 5.5 * component.measurements.lineHeight + 'px' + element.style.height = 5.5 * component.measurements.lineHeight + horizontalScrollbarHeight + 'px' await component.getNextUpdatePromise() expect(component.getLastVisibleRow()).toBe(5) const scrollMarginInLines = 2 @@ -1177,8 +1131,8 @@ describe('TextEditorComponent', () => { await component.getNextUpdatePromise() const actualScrollCenter = (component.getScrollTop() + component.getScrollBottom()) / 2 - const expectedScrollCenter = Math.round((4 + 7) / 2 * component.getLineHeight()) - expect(actualScrollCenter).toBe(expectedScrollCenter) + const expectedScrollCenter = (4 + 7) / 2 * component.getLineHeight() + expect(actualScrollCenter).toBeCloseTo(expectedScrollCenter, 0) }) it('automatically scrolls horizontally when the requested range is within the horizontal scroll margin of the right edge of the gutter or right edge of the scroll container', async () => { @@ -1191,29 +1145,27 @@ describe('TextEditorComponent', () => { editor.scrollToScreenRange([[1, 12], [2, 28]]) await component.getNextUpdatePromise() - let expectedScrollLeft = Math.round( + let expectedScrollLeft = clientLeftForCharacter(component, 1, 12) - lineNodeForScreenRow(component, 1).getBoundingClientRect().left - (editor.horizontalScrollMargin * component.measurements.baseCharacterWidth) - ) - expect(component.getScrollLeft()).toBe(expectedScrollLeft) + expect(component.getScrollLeft()).toBeCloseTo(expectedScrollLeft, 0) editor.scrollToScreenRange([[1, 12], [2, 28]], {reversed: false}) await component.getNextUpdatePromise() - expectedScrollLeft = Math.round( + expectedScrollLeft = component.getGutterContainerWidth() + clientLeftForCharacter(component, 2, 28) - lineNodeForScreenRow(component, 2).getBoundingClientRect().left + (editor.horizontalScrollMargin * component.measurements.baseCharacterWidth) - component.getScrollContainerClientWidth() - ) - expect(component.getScrollLeft()).toBe(expectedScrollLeft) + expect(component.getScrollLeft()).toBeCloseTo(expectedScrollLeft, 0) }) it('does not horizontally autoscroll by more than half of the visible "base-width" characters if the editor is narrower than twice the scroll margin', async () => { const {component, editor} = buildComponent({autoHeight: false}) await setEditorWidthInCharacters(component, 1.5 * editor.horizontalScrollMargin) - const editorWidthInChars = component.getScrollContainerWidth() / component.getBaseCharacterWidth() + const editorWidthInChars = component.getScrollContainerClientWidth() / component.getBaseCharacterWidth() expect(Math.round(editorWidthInChars)).toBe(9) editor.scrollToScreenRange([[6, 10], [6, 15]]) @@ -1313,22 +1265,22 @@ describe('TextEditorComponent', () => { // Assigns the scrollTop based on the logical position when attached jasmine.attachToDOM(element) - expect(component.getScrollLeft()).toBe(Math.round(2 * component.getBaseCharacterWidth())) + expect(component.getScrollLeft()).toBeCloseTo(2 * component.getBaseCharacterWidth(), 0) // Allows the scrollTopRow to be updated while attached component.setScrollLeftColumn(4) - expect(component.getScrollLeft()).toBe(Math.round(4 * component.getBaseCharacterWidth())) + expect(component.getScrollLeft()).toBeCloseTo(4 * component.getBaseCharacterWidth(), 0) // Preserves the scrollTopRow when detached element.remove() - expect(component.getScrollLeft()).toBe(Math.round(4 * component.getBaseCharacterWidth())) + expect(component.getScrollLeft()).toBeCloseTo(4 * component.getBaseCharacterWidth(), 0) component.setScrollLeftColumn(6) - expect(component.getScrollLeft()).toBe(Math.round(6 * component.getBaseCharacterWidth())) + expect(component.getScrollLeft()).toBeCloseTo(6 * component.getBaseCharacterWidth(), 0) jasmine.attachToDOM(element) element.style.width = '60px' - expect(component.getScrollLeft()).toBe(Math.round(6 * component.getBaseCharacterWidth())) + expect(component.getScrollLeft()).toBeCloseTo(6 * component.getBaseCharacterWidth(), 0) }) }) @@ -2102,6 +2054,37 @@ describe('TextEditorComponent', () => { expect(decorationNode2.firstChild).toBeNull() expect(gutterB.getElement().firstChild.children.length).toBe(0) }) + + it('renders custom line number gutters', async () => { + const {component, editor} = buildComponent() + const gutterA = editor.addGutter({ + name: 'a', + priority: 1, + type: 'line-number', + class: 'a-number', + labelFn: ({bufferRow}) => `a - ${bufferRow}` + }) + const gutterB = editor.addGutter({ + name: 'b', + priority: 1, + type: 'line-number', + class: 'b-number', + labelFn: ({bufferRow}) => `b - ${bufferRow}` + }) + editor.setText('0000\n0001\n0002\n0003\n0004\n') + + await component.getNextUpdatePromise() + + const gutterAElement = gutterA.getElement() + const aNumbers = gutterAElement.querySelectorAll('div.line-number[data-buffer-row]') + const aLabels = Array.from(aNumbers, e => e.textContent) + expect(aLabels).toEqual(['a - 0', 'a - 1', 'a - 2', 'a - 3', 'a - 4', 'a - 5']) + + const gutterBElement = gutterB.getElement() + const bNumbers = gutterBElement.querySelectorAll('div.line-number[data-buffer-row]') + const bLabels = Array.from(bNumbers, e => e.textContent) + expect(bLabels).toEqual(['b - 0', 'b - 1', 'b - 2', 'b - 3', 'b - 4', 'b - 5']) + }) }) describe('block decorations', () => { @@ -2112,7 +2095,8 @@ describe('TextEditorComponent', () => { // render an editor that already contains some block decorations const {component, element} = buildComponent({editor, rowsPerTile: 3}) - await setEditorHeightInLines(component, 4) + element.style.height = 4 * component.getLineHeight() + horizontalScrollbarHeight + 'px' + await component.getNextUpdatePromise() expect(component.getRenderedStartRow()).toBe(0) expect(component.getRenderedEndRow()).toBe(9) expect(component.getScrollHeight()).toBe( @@ -2327,7 +2311,7 @@ describe('TextEditorComponent', () => { component.element.style.width = ( component.getGutterContainerWidth() + component.getScrollContainerClientWidth() * 2 + - component.getVerticalScrollbarWidth() + verticalScrollbarWidth ) + 'px' await component.getNextUpdatePromise() expect(component.getRenderedStartRow()).toBe(0) @@ -3557,12 +3541,12 @@ describe('TextEditorComponent', () => { describe('on the scrollbars', () => { it('delegates the mousedown events to the parent component unless the mousedown was on the actual scrollbar', async () => { const {component, element, editor} = buildComponent({height: 100}) - await setEditorWidthInCharacters(component, 8.5) + await setEditorWidthInCharacters(component, 6) const verticalScrollbar = component.refs.verticalScrollbar const horizontalScrollbar = component.refs.horizontalScrollbar - const leftEdgeOfVerticalScrollbar = verticalScrollbar.element.getBoundingClientRect().right - getVerticalScrollbarWidth(component) - const topEdgeOfHorizontalScrollbar = horizontalScrollbar.element.getBoundingClientRect().bottom - getHorizontalScrollbarHeight(component) + const leftEdgeOfVerticalScrollbar = verticalScrollbar.element.getBoundingClientRect().right - verticalScrollbarWidth + const topEdgeOfHorizontalScrollbar = horizontalScrollbar.element.getBoundingClientRect().bottom - horizontalScrollbarHeight verticalScrollbar.didMouseDown({ button: 0, @@ -4124,7 +4108,7 @@ describe('TextEditorComponent', () => { it('assigns scrollTop on the component when calling setFirstVisibleScreenRow', async () => { const {component, element, editor} = buildComponent({rowsPerTile: 3, autoHeight: false}) - element.style.height = 4 * component.measurements.lineHeight + 'px' + element.style.height = 4 * component.measurements.lineHeight + horizontalScrollbarHeight + 'px' await component.getNextUpdatePromise() expect(component.getMaxScrollTop() / component.getLineHeight()).toBe(9) @@ -4151,17 +4135,17 @@ describe('TextEditorComponent', () => { element.style.width = 30 * component.getBaseCharacterWidth() + 'px' await component.getNextUpdatePromise() expect(editor.getFirstVisibleScreenColumn()).toBe(0) - expect(component.refs.horizontalScrollbar.element.scrollLeft).toBe(0 * component.getBaseCharacterWidth()) + expect(component.refs.horizontalScrollbar.element.scrollLeft).toBe(0) setScrollLeft(component, 5.5 * component.getBaseCharacterWidth()) expect(editor.getFirstVisibleScreenColumn()).toBe(5) await component.getNextUpdatePromise() - expect(component.refs.horizontalScrollbar.element.scrollLeft).toBe(Math.round(5.5 * component.getBaseCharacterWidth())) + expect(component.refs.horizontalScrollbar.element.scrollLeft).toBeCloseTo(5.5 * component.getBaseCharacterWidth(), -1) editor.setFirstVisibleScreenColumn(12) - expect(component.getScrollLeft()).toBe(Math.round(12 * component.getBaseCharacterWidth())) + expect(component.getScrollLeft()).toBeCloseTo(12 * component.getBaseCharacterWidth(), -1) await component.getNextUpdatePromise() - expect(component.refs.horizontalScrollbar.element.scrollLeft).toBe(Math.round(12 * component.getBaseCharacterWidth())) + expect(component.refs.horizontalScrollbar.element.scrollLeft).toBeCloseTo(12 * component.getBaseCharacterWidth(), -1) }) }) @@ -4308,6 +4292,7 @@ async function setEditorWidthInCharacters (component, widthInCharacters) { component.element.style.width = component.getGutterContainerWidth() + widthInCharacters * component.measurements.baseCharacterWidth + + verticalScrollbarWidth + 'px' await component.getNextUpdatePromise() } diff --git a/spec/text-editor-element-spec.js b/spec/text-editor-element-spec.js index 7ffdf374d..d6c33e7ad 100644 --- a/spec/text-editor-element-spec.js +++ b/spec/text-editor-element-spec.js @@ -9,7 +9,7 @@ describe('TextEditorElement', () => { jasmineContent = document.body.querySelector('#jasmine-content') // Force scrollbars to be visible regardless of local system configuration const scrollbarStyle = document.createElement('style') - scrollbarStyle.textContent = '::-webkit-scrollbar { -webkit-appearance: none }' + scrollbarStyle.textContent = 'atom-text-editor ::-webkit-scrollbar { -webkit-appearance: none }' jasmine.attachToDOM(scrollbarStyle) }) @@ -338,18 +338,20 @@ describe('TextEditorElement', () => { element.style.width = '200px' jasmine.attachToDOM(element) + const horizontalScrollbarHeight = element.component.getHorizontalScrollbarHeight() + expect(element.getMaxScrollTop()).toBe(0) await editor.update({autoHeight: false}) - element.style.height = '100px' + element.style.height = 100 + horizontalScrollbarHeight + 'px' await element.getNextUpdatePromise() expect(element.getMaxScrollTop()).toBe(60) - element.style.height = '120px' + element.style.height = 120 + horizontalScrollbarHeight + 'px' await element.getNextUpdatePromise() expect(element.getMaxScrollTop()).toBe(40) - element.style.height = '200px' + element.style.height = 200 + horizontalScrollbarHeight + 'px' await element.getNextUpdatePromise() expect(element.getMaxScrollTop()).toBe(0) }) @@ -392,10 +394,13 @@ describe('TextEditorElement', () => { it('returns true if the given row range intersects the visible row range', async () => { const element = buildTextEditorElement() const editor = element.getModel() + const horizontalScrollbarHeight = element.component.getHorizontalScrollbarHeight() + editor.update({autoHeight: false}) element.getModel().setText('x\n'.repeat(20)) - element.style.height = '120px' + element.style.height = 120 + horizontalScrollbarHeight + 'px' await element.getNextUpdatePromise() + element.setScrollTop(80) await element.getNextUpdatePromise() expect(element.getVisibleRowRange()).toEqual([4, 11]) @@ -412,9 +417,11 @@ describe('TextEditorElement', () => { it('returns a {top/left/width/height} object describing the rectangle between two screen positions, even if they are not on screen', async () => { const element = buildTextEditorElement() const editor = element.getModel() + const horizontalScrollbarHeight = element.component.getHorizontalScrollbarHeight() + editor.update({autoHeight: false}) element.getModel().setText('xxxxxxxxxxxxxxxxxxxxxx\n'.repeat(20)) - element.style.height = '120px' + element.style.height = 120 + horizontalScrollbarHeight + 'px' await element.getNextUpdatePromise() element.setScrollTop(80) await element.getNextUpdatePromise() diff --git a/spec/text-editor-registry-spec.js b/spec/text-editor-registry-spec.js index 4f4d1ee93..4c6d680eb 100644 --- a/spec/text-editor-registry-spec.js +++ b/spec/text-editor-registry-spec.js @@ -1,6 +1,7 @@ const TextEditorRegistry = require('../src/text-editor-registry') const TextEditor = require('../src/text-editor') const TextBuffer = require('text-buffer') +const {Point, Range} = TextBuffer const {it, fit, ffit, fffit} = require('./async-spec-helpers') const dedent = require('dedent') @@ -257,19 +258,19 @@ describe('TextEditorRegistry', function () { describe('when the "tabType" config setting is "auto"', function () { it('enables or disables soft tabs based on the editor\'s content', async function () { + await initialPackageActivation await atom.packages.activatePackage('language-javascript') atom.grammars.assignLanguageMode(editor, 'source.js') atom.config.set('editor.tabType', 'auto') - - registry.maintainConfig(editor) await initialPackageActivation + const languageMode = editor.getBuffer().getLanguageMode() editor.setText(dedent` { hello; } `) - editor.getBuffer().getLanguageMode().retokenizeLines() + let disposable = registry.maintainConfig(editor) expect(editor.getSoftTabs()).toBe(true) editor.setText(dedent` @@ -277,18 +278,17 @@ describe('TextEditorRegistry', function () { hello; } `) - editor.getBuffer().getLanguageMode().retokenizeLines() + disposable.dispose() + disposable = registry.maintainConfig(editor) expect(editor.getSoftTabs()).toBe(false) - editor.setText(dedent` + editor.setTextInBufferRange(new Range(Point.ZERO, Point.ZERO), dedent` /* * Comment with a leading space. */ - { - ${'\t'}hello; - } - ` + editor.getText()) - editor.getBuffer().getLanguageMode().retokenizeLines() + ` + '\n') + disposable.dispose() + disposable = registry.maintainConfig(editor) expect(editor.getSoftTabs()).toBe(false) editor.setText(dedent` @@ -300,8 +300,8 @@ describe('TextEditorRegistry', function () { hello; } `) - - editor.getBuffer().getLanguageMode().retokenizeLines() + disposable.dispose() + disposable = registry.maintainConfig(editor) expect(editor.getSoftTabs()).toBe(false) editor.setText(dedent` @@ -313,7 +313,8 @@ describe('TextEditorRegistry', function () { hello; } `) - editor.getBuffer().getLanguageMode().retokenizeLines() + disposable.dispose() + disposable = registry.maintainConfig(editor) expect(editor.getSoftTabs()).toBe(true) }) }) diff --git a/spec/text-editor-spec.js b/spec/text-editor-spec.js index 69be6be32..9041d3528 100644 --- a/spec/text-editor-spec.js +++ b/spec/text-editor-spec.js @@ -4,7 +4,7 @@ const fs = require('fs') const path = require('path') const temp = require('temp').track() const dedent = require('dedent') -const clipboard = require('../src/safe-clipboard') +const {clipboard} = require('electron') const TextEditor = require('../src/text-editor') const TextBuffer = require('text-buffer') const TextMateLanguageMode = require('../src/text-mate-language-mode') @@ -861,6 +861,15 @@ describe('TextEditor', () => { }) }) }) + + it("clears the goal column", () => { + editor.setText('first\n\nthird') + editor.setCursorScreenPosition([0, 3]) + editor.moveDown() + editor.moveToFirstCharacterOfLine() + editor.moveDown() + expect(editor.getCursorBufferPosition()).toEqual([2, 0]) + }) }) describe('.moveToBeginningOfWord()', () => { @@ -5193,6 +5202,111 @@ describe('TextEditor', () => { }) }) + describe('undo/redo restore selections of editor which initiated original change', () => { + let editor1, editor2 + + beforeEach(async () => { + editor1 = editor + editor2 = new TextEditor({buffer: editor1.buffer}) + + editor1.setText(dedent ` + aaaaaa + bbbbbb + cccccc + dddddd + eeeeee + `) + }) + + it('[editor.transact] restore selection of change-initiated-editor', () => { + editor1.setCursorBufferPosition([0, 0]); editor1.transact(() => editor1.insertText('1')) + editor2.setCursorBufferPosition([1, 0]); editor2.transact(() => editor2.insertText('2')) + editor1.setCursorBufferPosition([2, 0]); editor1.transact(() => editor1.insertText('3')) + editor2.setCursorBufferPosition([3, 0]); editor2.transact(() => editor2.insertText('4')) + + expect(editor1.getText()).toBe(dedent ` + 1aaaaaa + 2bbbbbb + 3cccccc + 4dddddd + eeeeee + `) + + editor2.setCursorBufferPosition([4, 0]) + editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([3, 0]) + editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([2, 0]) + editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([1, 0]) + editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([0, 0]) + expect(editor2.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged + + editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([0, 1]) + editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([1, 1]) + editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([2, 1]) + editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([3, 1]) + expect(editor2.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged + + editor1.setCursorBufferPosition([4, 0]) + editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([3, 0]) + editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([2, 0]) + editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([1, 0]) + editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([0, 0]) + expect(editor1.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged + + editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([0, 1]) + editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([1, 1]) + editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([2, 1]) + editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([3, 1]) + expect(editor1.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged + }) + + it('[manually group checkpoint] restore selection of change-initiated-editor', () => { + const transact = (editor, fn) => { + const checkpoint = editor.createCheckpoint() + fn() + editor.groupChangesSinceCheckpoint(checkpoint) + } + + editor1.setCursorBufferPosition([0, 0]); transact(editor1, () => editor1.insertText('1')) + editor2.setCursorBufferPosition([1, 0]); transact(editor2, () => editor2.insertText('2')) + editor1.setCursorBufferPosition([2, 0]); transact(editor1, () => editor1.insertText('3')) + editor2.setCursorBufferPosition([3, 0]); transact(editor2, () => editor2.insertText('4')) + + expect(editor1.getText()).toBe(dedent ` + 1aaaaaa + 2bbbbbb + 3cccccc + 4dddddd + eeeeee + `) + + editor2.setCursorBufferPosition([4, 0]) + editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([3, 0]) + editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([2, 0]) + editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([1, 0]) + editor1.undo(); expect(editor1.getCursorBufferPosition()).toEqual([0, 0]) + expect(editor2.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged + + editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([0, 1]) + editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([1, 1]) + editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([2, 1]) + editor1.redo(); expect(editor1.getCursorBufferPosition()).toEqual([3, 1]) + expect(editor2.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged + + editor1.setCursorBufferPosition([4, 0]) + editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([3, 0]) + editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([2, 0]) + editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([1, 0]) + editor2.undo(); expect(editor2.getCursorBufferPosition()).toEqual([0, 0]) + expect(editor1.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged + + editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([0, 1]) + editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([1, 1]) + editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([2, 1]) + editor2.redo(); expect(editor2.getCursorBufferPosition()).toEqual([3, 1]) + expect(editor1.getCursorBufferPosition()).toEqual([4, 0]) // remain unchanged + }) + }) + describe('when the buffer is changed (via its direct api, rather than via than edit session)', () => { it('moves the cursor so it is in the same relative position of the buffer', () => { expect(editor.getCursorScreenPosition()).toEqual([0, 0]) @@ -5383,6 +5497,195 @@ describe('TextEditor', () => { }) }) }) + + describe('when readonly', () => { + beforeEach(() => { + editor.setReadOnly(true) + }) + + const modifications = [ + { + name: 'moveLineUp', + op: (opts = {}) => { + editor.setCursorBufferPosition([1, 0]) + editor.moveLineUp(opts) + } + }, + { + name: 'moveLineDown', + op: (opts = {}) => { + editor.setCursorBufferPosition([0, 0]) + editor.moveLineDown(opts) + } + }, + { + name: 'insertText', + op: (opts = {}) => { + editor.setSelectedBufferRange([[1, 0], [1, 2]]) + editor.insertText('xxx', opts) + } + }, + { + name: 'insertNewline', + op: (opts = {}) => { + editor.setCursorScreenPosition({row: 1, column: 0}) + editor.insertNewline(opts) + } + }, + { + name: 'insertNewlineBelow', + op: (opts = {}) => { + editor.setCursorBufferPosition([0, 2]) + editor.insertNewlineBelow(opts) + } + }, + { + name: 'insertNewlineAbove', + op: (opts = {}) => { + editor.setCursorBufferPosition([0]) + editor.insertNewlineAbove(opts) + } + }, + { + name: 'backspace', + op: (opts = {}) => { + editor.setCursorScreenPosition({row: 1, column: 7}) + editor.backspace(opts) + } + }, + { + name: 'deleteToPreviousWordBoundary', + op: (opts = {}) => { + editor.setCursorBufferPosition([0, 16]) + editor.deleteToPreviousWordBoundary(opts) + } + }, + { + name: 'deleteToNextWordBoundary', + op: (opts = {}) => { + editor.setCursorBufferPosition([0, 15]) + editor.deleteToNextWordBoundary(opts) + } + }, + { + name: 'deleteToBeginningOfWord', + op: (opts = {}) => { + editor.setCursorBufferPosition([1, 24]) + editor.deleteToBeginningOfWord(opts) + } + }, + { + name: 'deleteToEndOfLine', + op: (opts = {}) => { + editor.setCursorBufferPosition([1, 24]) + editor.deleteToEndOfLine(opts) + } + }, + { + name: 'deleteToBeginningOfLine', + op: (opts = {}) => { + editor.setCursorBufferPosition([1, 24]) + editor.deleteToBeginningOfLine(opts) + } + }, + { + name: 'delete', + op: (opts = {}) => { + editor.setCursorScreenPosition([1, 6]) + editor.delete(opts) + } + }, + { + name: 'deleteToEndOfWord', + op: (opts = {}) => { + editor.setCursorBufferPosition([1, 24]) + editor.deleteToEndOfWord(opts) + } + }, + { + name: 'indent', + op: (opts = {}) => { + editor.indent(opts) + } + }, + { + name: 'cutSelectedText', + op: (opts = {}) => { + editor.setSelectedBufferRanges([[[0, 4], [0, 13]], [[1, 6], [1, 10]]]) + editor.cutSelectedText(opts) + } + }, + { + name: 'cutToEndOfLine', + op: (opts = {}) => { + editor.setCursorBufferPosition([2, 20]) + editor.cutToEndOfLine(opts) + } + }, + { + name: 'cutToEndOfBufferLine', + op: (opts = {}) => { + editor.setCursorBufferPosition([2, 20]) + editor.cutToEndOfBufferLine(opts) + } + }, + { + name: 'pasteText', + op: (opts = {}) => { + editor.setSelectedBufferRanges([[[0, 4], [0, 13]], [[1, 6], [1, 10]]]) + atom.clipboard.write('first') + editor.pasteText(opts) + } + }, + { + name: 'indentSelectedRows', + op: (opts = {}) => { + editor.setSelectedBufferRange([[0, 3], [0, 3]]) + editor.indentSelectedRows(opts) + } + }, + { + name: 'outdentSelectedRows', + op: (opts = {}) => { + editor.setSelectedBufferRange([[1, 3], [1, 3]]) + editor.outdentSelectedRows(opts) + } + }, + { + name: 'autoIndentSelectedRows', + op: (opts = {}) => { + editor.setCursorBufferPosition([2, 0]) + editor.insertText('function() {\ninside=true\n}\n i=1\n', opts) + editor.getLastSelection().setBufferRange([[2, 0], [6, 0]]) + editor.autoIndentSelectedRows(opts) + } + }, + { + name: 'undo/redo', + op: (opts = {}) => { + editor.insertText('foo', opts) + editor.undo(opts) + editor.redo(opts) + } + } + ] + + describe('without bypassReadOnly', () => { + for (const {name, op} of modifications) { + it(`throws an error on ${name}`, () => { + expect(op).toThrow() + }) + } + }) + + describe('with bypassReadOnly', () => { + for (const {name, op} of modifications) { + it(`permits ${name}`, () => { + op({bypassReadOnly: true}) + }) + } + }) + }) }) describe('reading text', () => { @@ -6413,6 +6716,20 @@ describe('TextEditor', () => { const gutter = editor.addGutter(options) expect(editor.getGutters().length).toBe(2) expect(editor.getGutters()[1]).toBe(gutter) + expect(gutter.type).toBe('decorated') + }) + + it('can add a custom line-number gutter', () => { + expect(editor.getGutters().length).toBe(1) + const options = { + name: 'another-gutter', + priority: 2, + type: 'line-number' + } + const gutter = editor.addGutter(options) + expect(editor.getGutters().length).toBe(2) + expect(editor.getGutters()[1]).toBe(gutter) + expect(gutter.type).toBe('line-number') }) it("does not allow a custom gutter with the 'line-number' name.", () => expect(editor.addGutter.bind(editor, {name: 'line-number'})).toThrow()) diff --git a/spec/tooltip-manager-spec.js b/spec/tooltip-manager-spec.js index 3a6b56a1b..0cf3c3e64 100644 --- a/spec/tooltip-manager-spec.js +++ b/spec/tooltip-manager-spec.js @@ -213,6 +213,18 @@ describe('TooltipManager', () => { }) ) + describe('when a user types', () => + it('hides the tooltips', () => { + const disposable = manager.add(element, { title: 'Title' }) + hover(element, function () { + expect(document.body.querySelector('.tooltip')).not.toBeNull() + window.dispatchEvent(new CustomEvent('keydown')) + expect(document.body.querySelector('.tooltip')).toBeNull() + disposable.dispose() + }) + }) + ) + describe('findTooltips', () => { it('adds and remove tooltips correctly', () => { expect(manager.findTooltips(element).length).toBe(0) diff --git a/spec/tree-sitter-language-mode-spec.js b/spec/tree-sitter-language-mode-spec.js index a788fac47..6bcd23ead 100644 --- a/spec/tree-sitter-language-mode-spec.js +++ b/spec/tree-sitter-language-mode-spec.js @@ -10,6 +10,9 @@ const TreeSitterLanguageMode = require('../src/tree-sitter-language-mode') const cGrammarPath = require.resolve('language-c/grammars/tree-sitter-c.cson') const pythonGrammarPath = require.resolve('language-python/grammars/tree-sitter-python.cson') const jsGrammarPath = require.resolve('language-javascript/grammars/tree-sitter-javascript.cson') +const htmlGrammarPath = require.resolve('language-html/grammars/tree-sitter-html.cson') +const ejsGrammarPath = require.resolve('language-html/grammars/tree-sitter-ejs.cson') +const rubyGrammarPath = require.resolve('language-ruby/grammars/tree-sitter-ruby.cson') describe('TreeSitterLanguageMode', () => { let editor, buffer @@ -17,10 +20,11 @@ describe('TreeSitterLanguageMode', () => { beforeEach(async () => { editor = await atom.workspace.open('') buffer = editor.getBuffer() + editor.displayLayer.reset({foldCharacter: '…'}) }) describe('highlighting', () => { - it('applies the most specific scope mapping to each node in the syntax tree', () => { + it('applies the most specific scope mapping to each node in the syntax tree', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', scopes: { @@ -31,8 +35,11 @@ describe('TreeSitterLanguageMode', () => { } }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) buffer.setText('aa.bbb = cc(d.eee());') + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + expectTokensToEqual(editor, [[ {text: 'aa.', scopes: ['source']}, {text: 'bbb', scopes: ['source', 'property']}, @@ -44,7 +51,7 @@ describe('TreeSitterLanguageMode', () => { ]]) }) - it('can start or end multiple scopes at the same position', () => { + it('can start or end multiple scopes at the same position', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', scopes: { @@ -57,8 +64,11 @@ describe('TreeSitterLanguageMode', () => { } }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) buffer.setText('a = bb.ccc();') + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + expectTokensToEqual(editor, [[ {text: 'a', scopes: ['source', 'variable']}, {text: ' = ', scopes: ['source']}, @@ -70,7 +80,7 @@ describe('TreeSitterLanguageMode', () => { ]]) }) - it('can resume highlighting on a line that starts with whitespace', () => { + it('can resume highlighting on a line that starts with whitespace', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', scopes: { @@ -80,14 +90,17 @@ describe('TreeSitterLanguageMode', () => { } }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) buffer.setText('a\n .b();') + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + expectTokensToEqual(editor, [ [ {text: 'a', scopes: ['variable']}, ], [ - {text: ' ', scopes: ['whitespace']}, + {text: ' ', scopes: ['leading-whitespace']}, {text: '.', scopes: []}, {text: 'b', scopes: ['function']}, {text: '();', scopes: []} @@ -95,8 +108,8 @@ describe('TreeSitterLanguageMode', () => { ]) }) - it('correctly skips over tokens with zero size', () => { - const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + it('correctly skips over tokens with zero size', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, cGrammarPath, { parser: 'tree-sitter-c', scopes: { 'primitive_type': 'type', @@ -104,13 +117,13 @@ describe('TreeSitterLanguageMode', () => { } }) - const languageMode = new TreeSitterLanguageMode({buffer, grammar}) - buffer.setLanguageMode(languageMode) buffer.setText('int main() {\n int a\n int b;\n}'); - editor.screenLineForScreenRow(0) + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + expect( - languageMode.document.rootNode.descendantForPosition(Point(1, 2), Point(1, 6)).toString() + languageMode.tree.rootNode.descendantForPosition(Point(1, 2), Point(1, 6)).toString() ).toBe('(declaration (primitive_type) (identifier) (MISSING))') expectTokensToEqual(editor, [ @@ -121,13 +134,13 @@ describe('TreeSitterLanguageMode', () => { {text: '() {', scopes: []} ], [ - {text: ' ', scopes: ['whitespace']}, + {text: ' ', scopes: ['leading-whitespace']}, {text: 'int', scopes: ['type']}, {text: ' ', scopes: []}, {text: 'a', scopes: ['variable']} ], [ - {text: ' ', scopes: ['whitespace']}, + {text: ' ', scopes: ['leading-whitespace']}, {text: 'int', scopes: ['type']}, {text: ' ', scopes: []}, {text: 'b', scopes: ['variable']}, @@ -139,7 +152,7 @@ describe('TreeSitterLanguageMode', () => { ]) }) - it('updates lines\' highlighting when they are affected by distant changes', () => { + it('updates lines\' highlighting when they are affected by distant changes', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', scopes: { @@ -148,10 +161,12 @@ describe('TreeSitterLanguageMode', () => { } }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) + buffer.setText('a(\nb,\nc\n') + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) // missing closing paren - buffer.setText('a(\nb,\nc\n') expectTokensToEqual(editor, [ [{text: 'a(', scopes: []}], [{text: 'b,', scopes: []}], @@ -171,7 +186,36 @@ describe('TreeSitterLanguageMode', () => { ]) }) - it('handles edits after tokens that end between CR and LF characters (regression)', () => { + it('allows comma-separated selectors as scope mapping keys', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + parser: 'tree-sitter-javascript', + scopes: { + 'identifier, call_expression > identifier': [ + {match: '^[A-Z]', scopes: 'constructor'} + ], + + 'call_expression > identifier': 'function' + } + }) + + buffer.setText(`a(B(new C))`) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: 'a', scopes: ['function']}, + {text: '(', scopes: []}, + {text: 'B', scopes: ['constructor']}, + {text: '(new ', scopes: []}, + {text: 'C', scopes: ['constructor']}, + {text: '))', scopes: []}, + ] + ]) + }) + + it('handles edits after tokens that end between CR and LF characters (regression)', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', scopes: { @@ -181,14 +225,15 @@ describe('TreeSitterLanguageMode', () => { } }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) - buffer.setText([ '// abc', '', 'a("b").c' ].join('\r\n')) + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + expectTokensToEqual(editor, [ [{text: '// abc', scopes: ['comment']}], [{text: '', scopes: []}], @@ -205,7 +250,7 @@ describe('TreeSitterLanguageMode', () => { [{text: '// abc', scopes: ['comment']}], [{text: '', scopes: []}], [ - {text: ' ', scopes: ['whitespace']}, + {text: ' ', scopes: ['leading-whitespace']}, {text: 'a(', scopes: []}, {text: '"b"', scopes: ['string']}, {text: ').', scopes: []}, @@ -213,14 +258,539 @@ describe('TreeSitterLanguageMode', () => { ] ]) }) + + it('handles multi-line nodes with children on different lines (regression)', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + parser: 'tree-sitter-javascript', + scopes: { + 'template_string': 'string', + '"${"': 'interpolation', + '"}"': 'interpolation' + } + }); + + buffer.setText('`\na${1}\nb${2}\n`;') + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: '`', scopes: ['string']} + ], [ + {text: 'a', scopes: ['string']}, + {text: '${', scopes: ['string', 'interpolation']}, + {text: '1', scopes: ['string']}, + {text: '}', scopes: ['string', 'interpolation']} + ], [ + {text: 'b', scopes: ['string']}, + {text: '${', scopes: ['string', 'interpolation']}, + {text: '2', scopes: ['string']}, + {text: '}', scopes: ['string', 'interpolation']} + ], + [ + {text: '`', scopes: ['string']}, + {text: ';', scopes: []} + ] + ]) + }) + + it('handles folds inside of highlighted tokens', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + parser: 'tree-sitter-javascript', + scopes: { + 'comment': 'comment', + 'call_expression > identifier': 'function', + } + }) + + buffer.setText(dedent ` + /* + * Hello + */ + + hello(); + `) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + + editor.foldBufferRange([[0, 2], [2, 0]]) + + expectTokensToEqual(editor, [ + [ + {text: '/*', scopes: ['comment']}, + {text: '…', scopes: ['fold-marker']}, + {text: ' */', scopes: ['comment']} + ], + [ + {text: '', scopes: []} + ], + [ + {text: 'hello', scopes: ['function']}, + {text: '();', scopes: []}, + ] + ]) + }) + + it('applies regex match rules when specified', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + parser: 'tree-sitter-javascript', + scopes: { + 'identifier': [ + {match: '^(exports|document|window|global)$', scopes: 'global'}, + {match: '^[A-Z_]+$', scopes: 'constant'}, + {match: '^[A-Z]', scopes: 'constructor'}, + 'variable' + ], + } + }) + + buffer.setText(`exports.object = Class(SOME_CONSTANT, x)`) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: 'exports', scopes: ['global']}, + {text: '.object = ', scopes: []}, + {text: 'Class', scopes: ['constructor']}, + {text: '(', scopes: []}, + {text: 'SOME_CONSTANT', scopes: ['constant']}, + {text: ', ', scopes: []}, + {text: 'x', scopes: ['variable']}, + {text: ')', scopes: []}, + ] + ]) + }) + + it('handles nodes that start before their first child and end after their last child', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, rubyGrammarPath, { + parser: 'tree-sitter-ruby', + scopes: { + 'bare_string': 'string', + 'interpolation': 'embedded', + '"#{"': 'punctuation', + '"}"': 'punctuation', + } + }) + + // The bare string node `bc#{d}ef` has one child: the interpolation, and that child + // starts later and ends earlier than the bare string. + buffer.setText('a = %W( bc#{d}ef )') + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: 'a = %W( ', scopes: []}, + {text: 'bc', scopes: ['string']}, + {text: '#{', scopes: ['string', 'embedded', 'punctuation']}, + {text: 'd', scopes: ['string', 'embedded']}, + {text: '}', scopes: ['string', 'embedded', 'punctuation']}, + {text: 'ef', scopes: ['string']}, + {text: ' )', scopes: []}, + ] + ]) + }) + + describe('when the buffer changes during a parse', () => { + it('immediately parses again when the current parse completes', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + parser: 'tree-sitter-javascript', + scopes: { + 'identifier': 'variable', + 'call_expression > identifier': 'function', + 'new_expression > call_expression > identifier': 'constructor' + } + }) + + buffer.setText('abc;'); + + const languageMode = new TreeSitterLanguageMode({buffer, grammar, syncOperationLimit: 0}) + buffer.setLanguageMode(languageMode) + await nextHighlightingUpdate(languageMode) + await new Promise(process.nextTick) + + expectTokensToEqual(editor, [ + [ + {text: 'abc', scopes: ['variable']}, + {text: ';', scopes: []} + ], + ]) + + buffer.setTextInRange([[0, 3], [0, 3]], '()'); + expectTokensToEqual(editor, [ + [ + {text: 'abc()', scopes: ['variable']}, + {text: ';', scopes: []} + ], + ]) + + buffer.setTextInRange([[0, 0], [0, 0]], 'new '); + expectTokensToEqual(editor, [ + [ + {text: 'new ', scopes: []}, + {text: 'abc()', scopes: ['variable']}, + {text: ';', scopes: []} + ], + ]) + + await nextHighlightingUpdate(languageMode) + expectTokensToEqual(editor, [ + [ + {text: 'new ', scopes: []}, + {text: 'abc', scopes: ['function']}, + {text: '();', scopes: []} + ], + ]) + + await nextHighlightingUpdate(languageMode) + expectTokensToEqual(editor, [ + [ + {text: 'new ', scopes: []}, + {text: 'abc', scopes: ['constructor']}, + {text: '();', scopes: []} + ], + ]) + }) + }) + + describe('when changes are small enough to be re-parsed synchronously', () => { + it('can incorporate multiple consecutive synchronous updates', () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + parser: 'tree-sitter-javascript', + scopes: { + 'property_identifier': 'property', + 'call_expression > identifier': 'function', + 'call_expression > member_expression > property_identifier': 'method', + } + }) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + buffer.setText('a'); + expectTokensToEqual(editor, [[ + {text: 'a', scopes: []}, + ]]) + + buffer.append('.') + expectTokensToEqual(editor, [[ + {text: 'a.', scopes: []}, + ]]) + + buffer.append('b') + expectTokensToEqual(editor, [[ + {text: 'a.', scopes: []}, + {text: 'b', scopes: ['property']}, + ]]) + + buffer.append('()') + expectTokensToEqual(editor, [[ + {text: 'a.', scopes: []}, + {text: 'b', scopes: ['method']}, + {text: '()', scopes: []}, + ]]) + + buffer.delete([[0, 1], [0, 2]]) + expectTokensToEqual(editor, [[ + {text: 'ab', scopes: ['function']}, + {text: '()', scopes: []}, + ]]) + }) + }) + + describe('injectionPoints and injectionPatterns', () => { + let jsGrammar, htmlGrammar + + beforeEach(() => { + jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript', + scopes: { + 'property_identifier': 'property', + 'call_expression > identifier': 'function', + 'template_string': 'string', + 'template_substitution > "${"': 'interpolation', + 'template_substitution > "}"': 'interpolation' + }, + injectionRegExp: 'javascript', + injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT] + }) + + htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, { + scopeName: 'html', + parser: 'tree-sitter-html', + scopes: { + fragment: 'html', + tag_name: 'tag', + attribute_name: 'attr' + }, + injectionRegExp: 'html', + injectionPoints: [SCRIPT_TAG_INJECTION_POINT] + }) + }) + + it('highlights code inside of injection points', async () => { + atom.grammars.addGrammar(jsGrammar) + atom.grammars.addGrammar(htmlGrammar) + buffer.setText('node.innerHTML = html `\na ${b}\n`;') + + const languageMode = new TreeSitterLanguageMode({buffer, grammar: jsGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: 'node.', scopes: []}, + {text: 'innerHTML', scopes: ['property']}, + {text: ' = ', scopes: []}, + {text: 'html', scopes: ['function']}, + {text: ' ', scopes: []}, + {text: '`', scopes: ['string']}, + {text: '', scopes: ['string', 'html']} + ], [ + {text: 'a ', scopes: ['string', 'html']}, + {text: '${', scopes: ['string', 'html', 'interpolation']}, + {text: 'b', scopes: ['string', 'html']}, + {text: '}', scopes: ['string', 'html', 'interpolation']}, + {text: '<', scopes: ['string', 'html']}, + {text: 'img', scopes: ['string', 'html', 'tag']}, + {text: ' ', scopes: ['string', 'html']}, + {text: 'src', scopes: ['string', 'html', 'attr']}, + {text: '="d">', scopes: ['string', 'html']} + ], [ + {text: '`', scopes: ['string']}, + {text: ';', scopes: []}, + ], + ]) + + const range = buffer.findSync('html') + buffer.setTextInRange(range, 'xml') + await nextHighlightingUpdate(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: 'node.', scopes: []}, + {text: 'innerHTML', scopes: ['property']}, + {text: ' = ', scopes: []}, + {text: 'xml', scopes: ['function']}, + {text: ' ', scopes: []}, + {text: '`', scopes: ['string']} + ], [ + {text: 'a ', scopes: ['string']}, + {text: '${', scopes: ['string', 'interpolation']}, + {text: 'b', scopes: ['string']}, + {text: '}', scopes: ['string', 'interpolation']}, + {text: '', scopes: ['string']}, + ], [ + {text: '`', scopes: ['string']}, + {text: ';', scopes: []}, + ], + ]) + }) + + it('highlights the content after injections', async () => { + atom.grammars.addGrammar(jsGrammar) + atom.grammars.addGrammar(htmlGrammar) + buffer.setText('\n
\n
') + + const languageMode = new TreeSitterLanguageMode({buffer, grammar: htmlGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: '<', scopes: ['html']}, + {text: 'script', scopes: ['html', 'tag']}, + {text: '>', scopes: ['html']}, + ], + [ + {text: 'hello', scopes: ['html', 'function']}, + {text: '();', scopes: ['html']}, + ], + [ + {text: '', scopes: ['html']}, + ], + [ + {text: '<', scopes: ['html']}, + {text: 'div', scopes: ['html', 'tag']}, + {text: '>', scopes: ['html']}, + ], + [ + {text: '', scopes: ['html']}, + ] + ]) + }) + + it('updates buffers highlighting when a grammar with injectionRegExp is added', async () => { + atom.grammars.addGrammar(jsGrammar) + + buffer.setText('node.innerHTML = html `\na ${b}\n`;') + const languageMode = new TreeSitterLanguageMode({buffer, grammar: jsGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: 'node.', scopes: []}, + {text: 'innerHTML', scopes: ['property']}, + {text: ' = ', scopes: []}, + {text: 'html', scopes: ['function']}, + {text: ' ', scopes: []}, + {text: '`', scopes: ['string']} + ], [ + {text: 'a ', scopes: ['string']}, + {text: '${', scopes: ['string', 'interpolation']}, + {text: 'b', scopes: ['string']}, + {text: '}', scopes: ['string', 'interpolation']}, + {text: '', scopes: ['string']}, + ], [ + {text: '`', scopes: ['string']}, + {text: ';', scopes: []}, + ], + ]) + + atom.grammars.addGrammar(htmlGrammar) + await nextHighlightingUpdate(languageMode) + expectTokensToEqual(editor, [ + [ + {text: 'node.', scopes: []}, + {text: 'innerHTML', scopes: ['property']}, + {text: ' = ', scopes: []}, + {text: 'html', scopes: ['function']}, + {text: ' ', scopes: []}, + {text: '`', scopes: ['string']}, + {text: '', scopes: ['string', 'html']} + ], [ + {text: 'a ', scopes: ['string', 'html']}, + {text: '${', scopes: ['string', 'html', 'interpolation']}, + {text: 'b', scopes: ['string', 'html']}, + {text: '}', scopes: ['string', 'html', 'interpolation']}, + {text: '<', scopes: ['string', 'html']}, + {text: 'img', scopes: ['string', 'html', 'tag']}, + {text: ' ', scopes: ['string', 'html']}, + {text: 'src', scopes: ['string', 'html', 'attr']}, + {text: '="d">', scopes: ['string', 'html']} + ], [ + {text: '`', scopes: ['string']}, + {text: ';', scopes: []}, + ], + ]) + }) + + it('handles injections that intersect', async () => { + const ejsGrammar = new TreeSitterGrammar(atom.grammars, ejsGrammarPath, { + id: 'ejs', + parser: 'tree-sitter-embedded-template', + scopes: { + '"<%="': 'directive', + '"%>"': 'directive', + }, + injectionPoints: [ + { + type: 'template', + language (node) { return 'javascript' }, + content (node) { return node.descendantsOfType('code') } + }, + { + type: 'template', + language (node) { return 'html' }, + content (node) { return node.descendantsOfType('content') } + } + ] + }) + + atom.grammars.addGrammar(jsGrammar) + atom.grammars.addGrammar(htmlGrammar) + + buffer.setText('\n\n') + const languageMode = new TreeSitterLanguageMode({ + buffer, + grammar: ejsGrammar, + grammars: atom.grammars, + }) + buffer.setLanguageMode(languageMode) + + expectTokensToEqual(editor, [ + [ + {text: '<', scopes: ['html']}, + {text: 'body', scopes: ['html', 'tag']}, + {text: '>', scopes: ['html']} + ], + [ + {text: '<', scopes: ['html']}, + {text: 'script', scopes: ['html', 'tag']}, + {text: '>', scopes: ['html']} + ], + [ + {text: 'b', scopes: ['html', 'function']}, + {text: '(', scopes: ['html']}, + {text: '<%=', scopes: ['html', 'directive']}, + {text: ' c.', scopes: ['html']}, + {text: 'd', scopes: ['html', 'property']}, + {text: ' ', scopes: ['html']}, + {text: '%>', scopes: ['html', 'directive']}, + {text: ')', scopes: ['html']}, + ], + [ + {text: '', scopes: ['html']} + ], + [ + {text: '', scopes: ['html']} + ], + ]) + }) + + it('notifies onDidTokenize listeners the first time all syntax highlighting is done', async () => { + const promise = new Promise(resolve => { + editor.onDidTokenize(event => { + expectTokensToEqual(editor, [ + [ + {text: '<', scopes: ['html']}, + {text: 'script', scopes: ['html', 'tag']}, + {text: '>', scopes: ['html']}, + ], + [ + {text: 'hello', scopes: ['html', 'function']}, + {text: '();', scopes: ['html']}, + ], + [ + {text: '', scopes: ['html']}, + ] + ]) + resolve() + }) + }) + + atom.grammars.addGrammar(jsGrammar) + atom.grammars.addGrammar(htmlGrammar) + buffer.setText('') + + const languageMode = new TreeSitterLanguageMode({ + buffer, + grammar: htmlGrammar, + grammars: atom.grammars, + syncOperationLimit: 0 + }) + buffer.setLanguageMode(languageMode) + + await promise + }) + }) }) describe('folding', () => { - beforeEach(() => { - editor.displayLayer.reset({foldCharacter: '…'}) - }) - - it('can fold nodes that start and end with specified tokens', () => { + it('can fold nodes that start and end with specified tokens', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', folds: [ @@ -235,7 +805,6 @@ describe('TreeSitterLanguageMode', () => { ] }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) buffer.setText(dedent ` module.exports = class A { @@ -247,7 +816,8 @@ describe('TreeSitterLanguageMode', () => { } `) - editor.screenLineForScreenRow(0) + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) expect(editor.isFoldableAtBufferRow(0)).toBe(false) expect(editor.isFoldableAtBufferRow(1)).toBe(true) @@ -260,7 +830,7 @@ describe('TreeSitterLanguageMode', () => { expect(getDisplayText(editor)).toBe(dedent ` module.exports = class A { - getB (…) { + getB (c,…) { return this.f(g) } } @@ -270,12 +840,60 @@ describe('TreeSitterLanguageMode', () => { expect(getDisplayText(editor)).toBe(dedent ` module.exports = class A { - getB (…) {…} + getB (c,…) {…} } `) }) - it('can fold nodes of specified types', () => { + it('folds entire buffer rows when necessary to keep words on separate lines', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + parser: 'tree-sitter-javascript', + folds: [ + { + start: {type: '{', index: 0}, + end: {type: '}', index: -1} + }, + { + start: {type: '(', index: 0}, + end: {type: ')', index: -1} + } + ] + }) + + buffer.setText(dedent ` + if (a) { + b + } else if (c) { + d + } else { + e + } + `) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + + // Avoid bringing the `else if...` up onto the same screen line as the preceding `if`. + editor.foldBufferRow(1) + editor.foldBufferRow(3) + expect(getDisplayText(editor)).toBe(dedent ` + if (a) {… + } else if (c) {… + } else { + e + } + `) + + // It's ok to bring the final `}` onto the same screen line as the preceding `else`. + editor.foldBufferRow(5) + expect(getDisplayText(editor)).toBe(dedent ` + if (a) {… + } else if (c) {… + } else {…} + `) + }) + + it('can fold nodes of specified types', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', folds: [ @@ -296,7 +914,6 @@ describe('TreeSitterLanguageMode', () => { ] }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) buffer.setText(dedent ` const element1 = { `) - editor.screenLineForScreenRow(0) + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) expect(editor.isFoldableAtBufferRow(0)).toBe(true) expect(editor.isFoldableAtBufferRow(1)).toBe(false) @@ -336,7 +954,7 @@ describe('TreeSitterLanguageMode', () => { `) }) - it('can fold entire nodes when no start or end parameters are specified', () => { + it('can fold entire nodes when no start or end parameters are specified', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', folds: [ @@ -346,7 +964,6 @@ describe('TreeSitterLanguageMode', () => { ] }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) buffer.setText(dedent ` /** * Important @@ -356,7 +973,8 @@ describe('TreeSitterLanguageMode', () => { */ `) - editor.screenLineForScreenRow(0) + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) expect(editor.isFoldableAtBufferRow(0)).toBe(true) expect(editor.isFoldableAtBufferRow(1)).toBe(false) @@ -379,7 +997,7 @@ describe('TreeSitterLanguageMode', () => { `) }) - it('tries each folding strategy for a given node in the order specified', () => { + it('tries each folding strategy for a given node in the order specified', async () => { const grammar = new TreeSitterGrammar(atom.grammars, cGrammarPath, { parser: 'tree-sitter-c', folds: [ @@ -405,8 +1023,6 @@ describe('TreeSitterLanguageMode', () => { ] }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) - buffer.setText(dedent ` #ifndef FOO_H_ #define FOO_H_ @@ -431,7 +1047,8 @@ describe('TreeSitterLanguageMode', () => { #endif `) - editor.screenLineForScreenRow(0) + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) editor.foldBufferRow(3) expect(getDisplayText(editor)).toBe(dedent ` @@ -492,8 +1109,127 @@ describe('TreeSitterLanguageMode', () => { `) }) + it('does not fold when the start and end parameters match the same child', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, { + parser: 'tree-sitter-html', + folds: [ + { + type: 'element', + start: {index: 0}, + end: {index: -1} + } + ] + }) + + buffer.setText(dedent ` + + + + + `) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + + // Void elements have only one child + expect(editor.isFoldableAtBufferRow(1)).toBe(false) + expect(editor.isFoldableAtBufferRow(2)).toBe(false) + + editor.foldBufferRow(0) + expect(getDisplayText(editor)).toBe(dedent ` + … + + `) + }) + + it('can target named vs anonymous nodes as fold boundaries', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, rubyGrammarPath, { + parser: 'tree-sitter-ruby', + folds: [ + { + type: 'elsif', + start: {index: 1}, + + // There are no double quotes around the `elsif` type. This indicates + // that we're targeting a *named* node in the syntax tree. The fold + // should end at the nested `elsif` node, not at the token that represents + // the literal string "elsif". + end: {type: ['else', 'elsif']} + }, + { + type: 'else', + + // There are double quotes around the `else` type. This indicates that + // we're targetting an *anonymous* node in the syntax tree. The fold + // should start at the token representing the literal string "else", + // not at an `else` node. + start: {type: '"else"'} + } + ] + }) + + buffer.setText(dedent ` + if a + b + elsif c + d + elsif e + f + else + g + end + `) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + + expect(languageMode.tree.rootNode.toString()).toBe( + "(program (if (identifier) " + + "(identifier) " + + "(elsif (identifier) " + + "(identifier) " + + "(elsif (identifier) " + + "(identifier) " + + "(else " + + "(identifier))))))" + ) + + editor.foldBufferRow(2) + expect(getDisplayText(editor)).toBe(dedent ` + if a + b + elsif c… + elsif e + f + else + g + end + `) + + editor.foldBufferRow(4) + expect(getDisplayText(editor)).toBe(dedent ` + if a + b + elsif c… + elsif e… + else + g + end + `) + + editor.foldBufferRow(6) + expect(getDisplayText(editor)).toBe(dedent ` + if a + b + elsif c… + elsif e… + else… + end + `) + }) + describe('when folding a node that ends with a line break', () => { - it('ends the fold at the end of the previous line', () => { + it('ends the fold at the end of the previous line', async () => { const grammar = new TreeSitterGrammar(atom.grammars, pythonGrammarPath, { parser: 'tree-sitter-python', folds: [ @@ -504,8 +1240,6 @@ describe('TreeSitterLanguageMode', () => { ] }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) - buffer.setText(dedent ` def ab(): print 'a' @@ -516,7 +1250,7 @@ describe('TreeSitterLanguageMode', () => { print 'd' `) - editor.screenLineForScreenRow(0) + buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) editor.foldBufferRow(0) expect(getDisplayText(editor)).toBe(dedent ` @@ -528,41 +1262,371 @@ describe('TreeSitterLanguageMode', () => { `) }) }) + + it('folds code in injected languages', async () => { + const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, { + scopeName: 'html', + parser: 'tree-sitter-html', + scopes: {}, + folds: [{ + type: ['element', 'raw_element'], + start: {index: 0}, + end: {index: -1} + }], + injectionRegExp: 'html' + }) + + const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript', + scopes: {}, + folds: [{ + type: ['template_string'], + start: {index: 0}, + end: {index: -1}, + }, + { + start: {index: 0, type: '('}, + end: {index: -1, type: ')'} + }], + injectionRegExp: 'javascript', + injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT] + }) + + atom.grammars.addGrammar(htmlGrammar) + + buffer.setText( + `a = html \` +
+ c\${def( + 1, + 2, + 3, + )}e\${f}g +
+ \` + ` + ) + const languageMode = new TreeSitterLanguageMode({buffer, grammar: jsGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + editor.foldBufferRow(2) + expect(getDisplayText(editor)).toBe( + `a = html \` +
+ c\${def(… + )}e\${f}g +
+ \` + ` + ) + + editor.foldBufferRow(1) + expect(getDisplayText(editor)).toBe( + `a = html \` +
… +
+ \` + ` + ) + + editor.foldBufferRow(0) + expect(getDisplayText(editor)).toBe( + `a = html \`…\` + ` + ) + }) }) describe('.scopeDescriptorForPosition', () => { - it('returns a scope descriptor representing the given position in the syntax tree', () => { + it('returns a scope descriptor representing the given position in the syntax tree', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { - id: 'javascript', - parser: 'tree-sitter-javascript' + scopeName: 'source.js', + parser: 'tree-sitter-javascript', + scopes: { + program: 'source.js', + property_identifier: 'property.name' + } }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) - buffer.setText('foo({bar: baz});') - editor.screenLineForScreenRow(0) - expect(editor.scopeDescriptorForBufferPosition([0, 6]).getScopesArray()).toEqual([ - 'javascript', - 'program', - 'expression_statement', - 'call_expression', - 'arguments', - 'object', - 'pair', - 'property_identifier' + buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) + expect(editor.scopeDescriptorForBufferPosition([0, 'foo({b'.length]).getScopesArray()).toEqual([ + 'source.js', + 'property.name' + ]) + expect(editor.scopeDescriptorForBufferPosition([0, 'foo({'.length]).getScopesArray()).toEqual([ + 'source.js', + 'property.name' + ]) + }) + + it('includes nodes in injected syntax trees', async () => { + const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'source.js', + parser: 'tree-sitter-javascript', + scopes: { + program: 'source.js', + template_string: 'string.quoted', + interpolation: 'meta.embedded', + property_identifier: 'property.name' + }, + injectionRegExp: 'javascript', + injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT] + }) + + const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, { + scopeName: 'text.html', + parser: 'tree-sitter-html', + scopes: { + fragment: 'text.html', + raw_element: 'script.tag' + }, + injectionRegExp: 'html', + injectionPoints: [SCRIPT_TAG_INJECTION_POINT] + }) + + atom.grammars.addGrammar(jsGrammar) + atom.grammars.addGrammar(htmlGrammar) + + buffer.setText(` +
+ +
+ `) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar: htmlGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + const position = buffer.findSync('name').start + expect(languageMode.scopeDescriptorForPosition(position).getScopesArray()).toEqual([ + 'text.html', + 'script.tag', + 'source.js', + 'string.quoted', + 'text.html', + 'property.name' + ]) + }) + + it('includes the root scope name even when the given position is in trailing whitespace at EOF', () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'source.js', + parser: 'tree-sitter-javascript', + scopes: { + program: 'source.js', + property_identifier: 'property.name' + } + }) + + buffer.setText('a; ') + buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) + expect(editor.scopeDescriptorForBufferPosition([0, 3]).getScopesArray()).toEqual([ + 'source.js' ]) }) }) + describe('.bufferRangeForScopeAtPosition(selector?, position)', () => { + describe('when selector = null', () => { + it('returns the range of the smallest node at position', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript' + }) + + buffer.setText('foo({bar: baz});') + + buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) + expect(editor.bufferRangeForScopeAtPosition(null, [0, 6])).toEqual( + [[0, 5], [0, 8]] + ) + expect(editor.bufferRangeForScopeAtPosition(null, [0, 9])).toEqual( + [[0, 8], [0, 9]] + ) + }) + + it('includes nodes in injected syntax trees', async () => { + const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript', + scopes: {}, + injectionRegExp: 'javascript', + injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT] + }) + + const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, { + scopeName: 'html', + parser: 'tree-sitter-html', + scopes: {}, + injectionRegExp: 'html', + injectionPoints: [SCRIPT_TAG_INJECTION_POINT] + }) + + atom.grammars.addGrammar(jsGrammar) + atom.grammars.addGrammar(htmlGrammar) + + buffer.setText(` +
+ +
+ `) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar: htmlGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + const nameProperty = buffer.findSync('name') + const {start} = nameProperty + const position = Object.assign({}, start, {column: start.column + 2}) + expect(languageMode.bufferRangeForScopeAtPosition(null, position)) + .toEqual(nameProperty) + }) + }) + + describe('with a selector', () => { + it('returns the range of the smallest matching node at position', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript' + }) + + buffer.setText('foo({bar: baz});') + + buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) + expect(editor.bufferRangeForScopeAtPosition('.property_identifier', [0, 6])).toEqual( + buffer.findSync('bar') + ) + expect(editor.bufferRangeForScopeAtPosition('.call_expression', [0, 6])).toEqual( + [[0, 0], [0, buffer.getText().length - 1]] + ) + expect(editor.bufferRangeForScopeAtPosition('.object', [0, 9])).toEqual( + buffer.findSync('{bar: baz}') + ) + }) + + it('includes nodes in injected syntax trees', async () => { + const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript', + scopes: {}, + injectionRegExp: 'javascript', + injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT] + }) + + const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, { + scopeName: 'html', + parser: 'tree-sitter-html', + scopes: {}, + injectionRegExp: 'html', + injectionPoints: [SCRIPT_TAG_INJECTION_POINT] + }) + + atom.grammars.addGrammar(jsGrammar) + atom.grammars.addGrammar(htmlGrammar) + + buffer.setText(` +
+ +
+ `) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar: htmlGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + const nameProperty = buffer.findSync('name') + const {start} = nameProperty + const position = Object.assign({}, start, {column: start.column + 2}) + expect(languageMode.bufferRangeForScopeAtPosition('.property_identifier', position)) + .toEqual(nameProperty) + expect(languageMode.bufferRangeForScopeAtPosition('.element', position)) + .toEqual(buffer.findSync('\\${person\\.name}')) + }) + + it('accepts node-matching functions as selectors', async () => { + const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript', + scopes: {}, + injectionRegExp: 'javascript', + injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT] + }) + + const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, { + scopeName: 'html', + parser: 'tree-sitter-html', + scopes: {}, + injectionRegExp: 'html', + injectionPoints: [SCRIPT_TAG_INJECTION_POINT] + }) + + atom.grammars.addGrammar(jsGrammar) + atom.grammars.addGrammar(htmlGrammar) + + buffer.setText(` +
+ +
+ `) + + const languageMode = new TreeSitterLanguageMode({buffer, grammar: htmlGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + const nameProperty = buffer.findSync('name') + const {start} = nameProperty + const position = Object.assign({}, start, {column: start.column + 2}) + const templateStringInCallExpression = node => + node.type === 'template_string' && node.parent.type === 'call_expression' + expect(languageMode.bufferRangeForScopeAtPosition(templateStringInCallExpression, position)) + .toEqual([[3, 19], [5, 15]]) + }) + }) + }) + + describe('.getSyntaxNodeAtPosition(position, where?)', () => { + it('returns the range of the smallest matching node at position', async () => { + const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript' + }) + + buffer.setText('foo(bar({x: 2}));') + const languageMode = new TreeSitterLanguageMode({buffer, grammar}) + buffer.setLanguageMode(languageMode) + expect(languageMode.getSyntaxNodeAtPosition([0, 6]).range).toEqual( + buffer.findSync('bar') + ) + const findFoo = node => + node.type === 'call_expression' && node.firstChild.text === 'foo' + expect(languageMode.getSyntaxNodeAtPosition([0, 6], findFoo).range).toEqual( + [[0, 0], [0, buffer.getText().length - 1]] + ) + }) + }) + describe('TextEditor.selectLargerSyntaxNode and .selectSmallerSyntaxNode', () => { - it('expands and contract the selection based on the syntax tree', () => { + it('expands and contracts the selection based on the syntax tree', async () => { const grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { parser: 'tree-sitter-javascript', scopes: {'program': 'source'} }) - buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) buffer.setText(dedent ` function a (b, c, d) { eee.f() @@ -570,7 +1634,7 @@ describe('TreeSitterLanguageMode', () => { } `) - editor.screenLineForScreenRow(0) + buffer.setLanguageMode(new TreeSitterLanguageMode({buffer, grammar})) editor.setCursorBufferPosition([1, 3]) editor.selectLargerSyntaxNode() @@ -595,9 +1659,69 @@ describe('TreeSitterLanguageMode', () => { editor.selectSmallerSyntaxNode() expect(editor.getSelectedBufferRange()).toEqual([[1, 3], [1, 3]]) }) + + it('handles injected languages', async () => { + const jsGrammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, { + scopeName: 'javascript', + parser: 'tree-sitter-javascript', + scopes: { + 'property_identifier': 'property', + 'call_expression > identifier': 'function', + 'template_string': 'string', + 'template_substitution > "${"': 'interpolation', + 'template_substitution > "}"': 'interpolation' + }, + injectionRegExp: 'javascript', + injectionPoints: [HTML_TEMPLATE_LITERAL_INJECTION_POINT] + }) + + const htmlGrammar = new TreeSitterGrammar(atom.grammars, htmlGrammarPath, { + scopeName: 'html', + parser: 'tree-sitter-html', + scopes: { + fragment: 'html', + tag_name: 'tag', + attribute_name: 'attr' + }, + injectionRegExp: 'html' + }) + + atom.grammars.addGrammar(htmlGrammar) + + buffer.setText('a = html ` c${def()}e${f}g `') + const languageMode = new TreeSitterLanguageMode({buffer, grammar: jsGrammar, grammars: atom.grammars}) + buffer.setLanguageMode(languageMode) + + editor.setCursorBufferPosition({row: 0, column: buffer.getText().indexOf('ef()')}) + editor.selectLargerSyntaxNode() + expect(editor.getSelectedText()).toBe('def') + editor.selectLargerSyntaxNode() + expect(editor.getSelectedText()).toBe('def()') + editor.selectLargerSyntaxNode() + expect(editor.getSelectedText()).toBe('${def()}') + editor.selectLargerSyntaxNode() + expect(editor.getSelectedText()).toBe('c${def()}e${f}g') + editor.selectLargerSyntaxNode() + expect(editor.getSelectedText()).toBe('c${def()}e${f}g') + editor.selectLargerSyntaxNode() + expect(editor.getSelectedText()).toBe(' c${def()}e${f}g ') + editor.selectLargerSyntaxNode() + expect(editor.getSelectedText()).toBe('` c${def()}e${f}g `') + editor.selectLargerSyntaxNode() + expect(editor.getSelectedText()).toBe('html ` c${def()}e${f}g `') + }) }) }) +function nextHighlightingUpdate (languageMode) { + return new Promise(resolve => { + const subscription = languageMode.onDidChangeHighlighting(() => { + subscription.dispose() + resolve() + }) + }) +} + function getDisplayText (editor) { return editor.displayLayer.getText() } @@ -624,7 +1748,7 @@ function expectTokensToEqual (editor, expectedTokenLines) { text, scopes: scopes.map(scope => scope .split(' ') - .map(className => className.slice('syntax--'.length)) + .map(className => className.replace('syntax--', '')) .join(' ')) })) } @@ -644,3 +1768,21 @@ function expectTokensToEqual (editor, expectedTokenLines) { // due to subsequent edits can be tested. editor.displayLayer.getScreenLines(0, Infinity) } + +const HTML_TEMPLATE_LITERAL_INJECTION_POINT = { + type: 'call_expression', + language (node) { + if (node.lastChild.type === 'template_string' && node.firstChild.type === 'identifier') { + return node.firstChild.text + } + }, + content (node) { + return node.lastChild + } +} + +const SCRIPT_TAG_INJECTION_POINT = { + type: 'raw_element', + language () { return 'javascript' }, + content (node) { return node.child(1) } +} diff --git a/spec/update-process-env-spec.js b/spec/update-process-env-spec.js index e5a1cfd9c..f7948d998 100644 --- a/spec/update-process-env-spec.js +++ b/spec/update-process-env-spec.js @@ -36,7 +36,7 @@ describe('updateProcessEnv(launchEnv)', function () { }) describe('when the launch environment appears to come from a shell', function () { - it('updates process.env to match the launch environment', async function () { + it('updates process.env to match the launch environment because PWD is set', async function () { process.env = { WILL_BE_DELETED: 'hi', NODE_ENV: 'the-node-env', @@ -64,6 +64,65 @@ describe('updateProcessEnv(launchEnv)', function () { expect(process.env).toBe(initialProcessEnv) }) + it('updates process.env to match the launch environment because PROMPT is set', async function () { + process.env = { + WILL_BE_DELETED: 'hi', + NODE_ENV: 'the-node-env', + NODE_PATH: '/the/node/path', + ATOM_HOME: '/the/atom/home' + } + + const initialProcessEnv = process.env + + await updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PROMPT: '$P$G', KEY1: 'value1', KEY2: 'value2'}) + expect(process.env).toEqual({ + ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', + PROMPT: '$P$G', + KEY1: 'value1', + KEY2: 'value2', + NODE_ENV: 'the-node-env', + NODE_PATH: '/the/node/path', + ATOM_HOME: '/the/atom/home' + }) + + // See #11302. On Windows, `process.env` is a magic object that offers + // case-insensitive environment variable matching, so we cannot replace it + // with another object. + expect(process.env).toBe(initialProcessEnv) + }) + + it('updates process.env to match the launch environment because PSModulePath is set', async function () { + process.env = { + WILL_BE_DELETED: 'hi', + NODE_ENV: 'the-node-env', + NODE_PATH: '/the/node/path', + ATOM_HOME: '/the/atom/home' + } + + const initialProcessEnv = process.env + + await updateProcessEnv({ + ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', + PSModulePath: 'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules\\', + KEY1: 'value1', + KEY2: 'value2' + }) + expect(process.env).toEqual({ + ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', + PSModulePath: 'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules\\', + KEY1: 'value1', + KEY2: 'value2', + NODE_ENV: 'the-node-env', + NODE_PATH: '/the/node/path', + ATOM_HOME: '/the/atom/home' + }) + + // See #11302. On Windows, `process.env` is a magic object that offers + // case-insensitive environment variable matching, so we cannot replace it + // with another object. + expect(process.env).toBe(initialProcessEnv) + }) + it('allows ATOM_HOME to be overwritten only if the new value is a valid path', async function () { let newAtomHomePath = temp.mkdirSync('atom-home') diff --git a/spec/workspace-element-spec.js b/spec/workspace-element-spec.js index 90d973773..7564f6931 100644 --- a/spec/workspace-element-spec.js +++ b/spec/workspace-element-spec.js @@ -1,11 +1,14 @@ /** @babel */ const {ipcRenderer} = require('electron') +const etch = require('etch') const path = require('path') const temp = require('temp').track() const {Disposable} = require('event-kit') const {it, fit, ffit, fffit, beforeEach, afterEach} = require('./async-spec-helpers') +const getNextUpdatePromise = () => etch.getScheduler().nextUpdatePromise + describe('WorkspaceElement', () => { afterEach(() => { try { @@ -565,35 +568,42 @@ describe('WorkspaceElement', () => { // Mouse over where the toggle button would be if the dock were hovered moveMouse({clientX: 440, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) expectToggleButtonHidden(rightDock) expectToggleButtonHidden(bottomDock) // Mouse over the dock moveMouse({clientX: 460, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) expectToggleButtonVisible(rightDock, 'icon-chevron-right') expectToggleButtonHidden(bottomDock) // Mouse over the toggle button moveMouse({clientX: 440, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) expectToggleButtonVisible(rightDock, 'icon-chevron-right') expectToggleButtonHidden(bottomDock) // Click the toggle button - rightDock.toggleButton.innerElement.click() + rightDock.refs.toggleButton.refs.innerElement.click() + await getNextUpdatePromise() expect(rightDock.isVisible()).toBe(false) expectToggleButtonHidden(rightDock) // Mouse to edge of the window moveMouse({clientX: 575, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonHidden(rightDock) moveMouse({clientX: 598, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonVisible(rightDock, 'icon-chevron-left') // Click the toggle button again - rightDock.toggleButton.innerElement.click() + rightDock.refs.toggleButton.refs.innerElement.click() + await getNextUpdatePromise() expect(rightDock.isVisible()).toBe(true) expectToggleButtonVisible(rightDock, 'icon-chevron-right') @@ -601,35 +611,42 @@ describe('WorkspaceElement', () => { // Mouse over where the toggle button would be if the dock were hovered moveMouse({clientX: 160, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) expectToggleButtonHidden(rightDock) expectToggleButtonHidden(bottomDock) // Mouse over the dock moveMouse({clientX: 140, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonVisible(leftDock, 'icon-chevron-left') expectToggleButtonHidden(rightDock) expectToggleButtonHidden(bottomDock) // Mouse over the toggle button moveMouse({clientX: 160, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonVisible(leftDock, 'icon-chevron-left') expectToggleButtonHidden(rightDock) expectToggleButtonHidden(bottomDock) // Click the toggle button - leftDock.toggleButton.innerElement.click() + leftDock.refs.toggleButton.refs.innerElement.click() + await getNextUpdatePromise() expect(leftDock.isVisible()).toBe(false) expectToggleButtonHidden(leftDock) // Mouse to edge of the window moveMouse({clientX: 25, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) moveMouse({clientX: 2, clientY: 150}) + await getNextUpdatePromise() expectToggleButtonVisible(leftDock, 'icon-chevron-right') // Click the toggle button again - leftDock.toggleButton.innerElement.click() + leftDock.refs.toggleButton.refs.innerElement.click() + await getNextUpdatePromise() expect(leftDock.isVisible()).toBe(true) expectToggleButtonVisible(leftDock, 'icon-chevron-left') @@ -637,51 +654,58 @@ describe('WorkspaceElement', () => { // Mouse over where the toggle button would be if the dock were hovered moveMouse({clientX: 300, clientY: 190}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) expectToggleButtonHidden(rightDock) expectToggleButtonHidden(bottomDock) // Mouse over the dock moveMouse({clientX: 300, clientY: 210}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) expectToggleButtonHidden(rightDock) expectToggleButtonVisible(bottomDock, 'icon-chevron-down') // Mouse over the toggle button moveMouse({clientX: 300, clientY: 195}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) expectToggleButtonHidden(rightDock) expectToggleButtonVisible(bottomDock, 'icon-chevron-down') // Click the toggle button - bottomDock.toggleButton.innerElement.click() + bottomDock.refs.toggleButton.refs.innerElement.click() + await getNextUpdatePromise() expect(bottomDock.isVisible()).toBe(false) expectToggleButtonHidden(bottomDock) // Mouse to edge of the window moveMouse({clientX: 300, clientY: 290}) + await getNextUpdatePromise() expectToggleButtonHidden(leftDock) moveMouse({clientX: 300, clientY: 299}) + await getNextUpdatePromise() expectToggleButtonVisible(bottomDock, 'icon-chevron-up') // Click the toggle button again - bottomDock.toggleButton.innerElement.click() + bottomDock.refs.toggleButton.refs.innerElement.click() + await getNextUpdatePromise() expect(bottomDock.isVisible()).toBe(true) expectToggleButtonVisible(bottomDock, 'icon-chevron-down') }) - function moveMouse(coordinates) { + function moveMouse (coordinates) { window.dispatchEvent(new MouseEvent('mousemove', coordinates)) advanceClock(100) } function expectToggleButtonHidden(dock) { - expect(dock.toggleButton.element).not.toHaveClass('atom-dock-toggle-button-visible') + expect(dock.refs.toggleButton.element).not.toHaveClass('atom-dock-toggle-button-visible') } function expectToggleButtonVisible(dock, iconClass) { - expect(dock.toggleButton.element).toHaveClass('atom-dock-toggle-button-visible') - expect(dock.toggleButton.iconElement).toHaveClass(iconClass) + expect(dock.refs.toggleButton.element).toHaveClass('atom-dock-toggle-button-visible') + expect(dock.refs.toggleButton.refs.iconElement).toHaveClass(iconClass) } }) @@ -871,27 +895,39 @@ describe('WorkspaceElement', () => { // No active item. Use first project directory. atom.commands.dispatch(workspaceElement, 'window:run-package-specs') - expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec')) + expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec'), {}) ipcRenderer.send.reset() // Active item doesn't implement ::getPath(). Use first project directory. const item = document.createElement('div') atom.workspace.getActivePane().activateItem(item) atom.commands.dispatch(workspaceElement, 'window:run-package-specs') - expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec')) + expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec'), {}) ipcRenderer.send.reset() // Active item has no path. Use first project directory. item.getPath = () => null atom.commands.dispatch(workspaceElement, 'window:run-package-specs') - expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec')) + expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[0], 'spec'), {}) ipcRenderer.send.reset() // Active item has path. Use project path for item path. item.getPath = () => path.join(projectPaths[1], 'a-file.txt') atom.commands.dispatch(workspaceElement, 'window:run-package-specs') - expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[1], 'spec')) + expect(ipcRenderer.send).toHaveBeenCalledWith('run-package-specs', path.join(projectPaths[1], 'spec'), {}) ipcRenderer.send.reset() }) + + it("passes additional options to the spec window", () => { + const workspaceElement = atom.workspace.getElement() + spyOn(ipcRenderer, 'send') + + const projectPath = temp.mkdirSync('dir1-') + atom.project.setPaths([projectPath]) + workspaceElement.runPackageSpecs({env: {ATOM_GITHUB_BABEL_ENV: 'coverage'}}) + + expect(ipcRenderer.send).toHaveBeenCalledWith( + 'run-package-specs', path.join(projectPath, 'spec'), {env: {ATOM_GITHUB_BABEL_ENV: 'coverage'}}) + }) }) }) diff --git a/spec/workspace-spec.js b/spec/workspace-spec.js index 4b115e594..091588a70 100644 --- a/spec/workspace-spec.js +++ b/spec/workspace-spec.js @@ -274,6 +274,21 @@ describe('Workspace', () => { }) }) + it('discovers existing editors that are still opening', () => { + let editor0 = null + let editor1 = null + + waitsForPromise(() => Promise.all([ + workspace.open('spartacus.txt').then(o0 => { editor0 = o0 }), + workspace.open('spartacus.txt').then(o1 => { editor1 = o1 }), + ])) + + runs(() => { + expect(editor0).toEqual(editor1) + expect(workspace.getActivePane().items).toEqual([editor0]) + }) + }) + it("uses the location specified by the model's `getDefaultLocation()` method", () => { const item = { getDefaultLocation: jasmine.createSpy().andReturn('right'), @@ -361,6 +376,28 @@ describe('Workspace', () => { }) }) + it('discovers existing editors that are still opening in an inactive pane', () => { + let editor0 = null + let editor1 = null + const pane0 = workspace.getActivePane() + const pane1 = workspace.getActivePane().splitRight() + + pane0.activate() + const promise0 = workspace.open('spartacus.txt', {searchAllPanes: true}).then(o0 => { editor0 = o0 }) + pane1.activate() + const promise1 = workspace.open('spartacus.txt', {searchAllPanes: true}).then(o1 => { editor1 = o1 }) + + waitsForPromise(() => Promise.all([promise0, promise1])) + + runs(() => { + expect(editor0).toBeDefined() + expect(editor1).toBeDefined() + + expect(editor0).toEqual(editor1) + expect(workspace.getActivePane().items).toEqual([editor0]) + }) + }) + it('activates the pane in the dock with the matching item', () => { const dock = atom.workspace.getRightDock() const ITEM_URI = 'atom://test' @@ -1236,21 +1273,57 @@ describe('Workspace', () => { describe('the grammar-used hook', () => { it('fires when opening a file or changing the grammar of an open file', async () => { - let resolveJavascriptGrammarUsed, resolveCoffeeScriptGrammarUsed - const javascriptGrammarUsed = new Promise(resolve => { resolveJavascriptGrammarUsed = resolve }) - const coffeescriptGrammarUsed = new Promise(resolve => { resolveCoffeeScriptGrammarUsed = resolve }) + await atom.packages.activatePackage('language-javascript') + await atom.packages.activatePackage('language-coffee-script') + + const observeTextEditorsSpy = jasmine.createSpy('observeTextEditors') + const javascriptGrammarUsed = jasmine.createSpy('javascript') + const coffeeScriptGrammarUsed = jasmine.createSpy('coffeescript') atom.packages.triggerDeferredActivationHooks() - atom.packages.onDidTriggerActivationHook('language-javascript:grammar-used', resolveJavascriptGrammarUsed) - atom.packages.onDidTriggerActivationHook('language-coffee-script:grammar-used', resolveCoffeeScriptGrammarUsed) + atom.packages.onDidTriggerActivationHook('language-javascript:grammar-used', () => { + atom.workspace.observeTextEditors(observeTextEditorsSpy) + javascriptGrammarUsed() + }) + atom.packages.onDidTriggerActivationHook('language-coffee-script:grammar-used', coffeeScriptGrammarUsed) + expect(javascriptGrammarUsed).not.toHaveBeenCalled() + expect(observeTextEditorsSpy).not.toHaveBeenCalled() const editor = await atom.workspace.open('sample.js', {autoIndent: false}) - await atom.packages.activatePackage('language-javascript') - await javascriptGrammarUsed + expect(javascriptGrammarUsed).toHaveBeenCalled() + expect(observeTextEditorsSpy.callCount).toBe(1) - await atom.packages.activatePackage('language-coffee-script') + expect(coffeeScriptGrammarUsed).not.toHaveBeenCalled() atom.grammars.assignLanguageMode(editor, 'source.coffee') - await coffeescriptGrammarUsed + expect(coffeeScriptGrammarUsed).toHaveBeenCalled() + }) + }) + + describe('the root-scope-used hook', () => { + it('fires when opening a file or changing the grammar of an open file', async () => { + await atom.packages.activatePackage('language-javascript') + await atom.packages.activatePackage('language-coffee-script') + + const observeTextEditorsSpy = jasmine.createSpy('observeTextEditors') + const javascriptGrammarUsed = jasmine.createSpy('javascript') + const coffeeScriptGrammarUsed = jasmine.createSpy('coffeescript') + + atom.packages.triggerDeferredActivationHooks() + atom.packages.onDidTriggerActivationHook('source.js:root-scope-used', () => { + atom.workspace.observeTextEditors(observeTextEditorsSpy) + javascriptGrammarUsed() + }) + atom.packages.onDidTriggerActivationHook('source.coffee:root-scope-used', coffeeScriptGrammarUsed) + + expect(javascriptGrammarUsed).not.toHaveBeenCalled() + expect(observeTextEditorsSpy).not.toHaveBeenCalled() + const editor = await atom.workspace.open('sample.js', {autoIndent: false}) + expect(javascriptGrammarUsed).toHaveBeenCalled() + expect(observeTextEditorsSpy.callCount).toBe(1) + + expect(coffeeScriptGrammarUsed).not.toHaveBeenCalled() + atom.grammars.assignLanguageMode(editor, 'source.coffee') + expect(coffeeScriptGrammarUsed).toHaveBeenCalled() }) }) diff --git a/src/application-delegate.js b/src/application-delegate.js index fcf8441b6..8d7981edb 100644 --- a/src/application-delegate.js +++ b/src/application-delegate.js @@ -1,12 +1,23 @@ const {ipcRenderer, remote, shell} = require('electron') const ipcHelpers = require('./ipc-helpers') -const {Disposable} = require('event-kit') +const {Emitter, Disposable} = require('event-kit') const getWindowLoadSettings = require('./get-window-load-settings') module.exports = class ApplicationDelegate { constructor () { this.pendingSettingsUpdateCount = 0 + this._ipcMessageEmitter = null + } + + ipcMessageEmitter () { + if (!this._ipcMessageEmitter) { + this._ipcMessageEmitter = new Emitter() + ipcRenderer.on('message', (event, message, detail) => { + this._ipcMessageEmitter.emit(message, detail) + }) + } + return this._ipcMessageEmitter } getWindowLoadSettings () { return getWindowLoadSettings() } @@ -179,31 +190,23 @@ class ApplicationDelegate { return remote.systemPreferences.getUserDefault(key, type) } - async setUserSettings (config) { + async setUserSettings (config, configFilePath) { this.pendingSettingsUpdateCount++ try { - await ipcHelpers.call('set-user-settings', JSON.stringify(config)) + await ipcHelpers.call('set-user-settings', JSON.stringify(config), configFilePath) } finally { this.pendingSettingsUpdateCount-- } } onDidChangeUserSettings (callback) { - const outerCallback = (event, message, detail) => { - if (message === 'did-change-user-settings') { - if (this.pendingSettingsUpdateCount === 0) callback(detail) - } - } - ipcRenderer.on('message', outerCallback) - return new Disposable(() => ipcRenderer.removeListener('message', outerCallback)) + return this.ipcMessageEmitter().on('did-change-user-settings', detail => { + if (this.pendingSettingsUpdateCount === 0) callback(detail) + }) } onDidFailToReadUserSettings (callback) { - const outerCallback = (event, message, detail) => { - if (message === 'did-fail-to-read-user-settings') callback(detail) - } - ipcRenderer.on('message', outerCallback) - return new Disposable(() => ipcRenderer.removeListener('message', outerCallback)) + return this.ipcMessageEmitter().on('did-fail-to-read-user-setting', callback) } confirm (options, callback) { @@ -261,24 +264,14 @@ class ApplicationDelegate { } onDidOpenLocations (callback) { - const outerCallback = (event, message, detail) => { - if (message === 'open-locations') callback(detail) - } - - ipcRenderer.on('message', outerCallback) - return new Disposable(() => ipcRenderer.removeListener('message', outerCallback)) + return this.ipcMessageEmitter().on('open-locations', callback) } onUpdateAvailable (callback) { - const outerCallback = (event, message, detail) => { - // TODO: Yes, this is strange that `onUpdateAvailable` is listening for - // `did-begin-downloading-update`. We currently have no mechanism to know - // if there is an update, so begin of downloading is a good proxy. - if (message === 'did-begin-downloading-update') callback(detail) - } - - ipcRenderer.on('message', outerCallback) - return new Disposable(() => ipcRenderer.removeListener('message', outerCallback)) + // TODO: Yes, this is strange that `onUpdateAvailable` is listening for + // `did-begin-downloading-update`. We currently have no mechanism to know + // if there is an update, so begin of downloading is a good proxy. + return this.ipcMessageEmitter().on('did-begin-downloading-update', callback) } onDidBeginDownloadingUpdate (callback) { @@ -286,40 +279,19 @@ class ApplicationDelegate { } onDidBeginCheckingForUpdate (callback) { - const outerCallback = (event, message, detail) => { - if (message === 'checking-for-update') callback(detail) - } - - ipcRenderer.on('message', outerCallback) - return new Disposable(() => ipcRenderer.removeListener('message', outerCallback)) + return this.ipcMessageEmitter().on('checking-for-update', callback) } onDidCompleteDownloadingUpdate (callback) { - const outerCallback = (event, message, detail) => { - // TODO: We could rename this event to `did-complete-downloading-update` - if (message === 'update-available') callback(detail) - } - - ipcRenderer.on('message', outerCallback) - return new Disposable(() => ipcRenderer.removeListener('message', outerCallback)) + return this.ipcMessageEmitter().on('update-available', callback) } onUpdateNotAvailable (callback) { - const outerCallback = (event, message, detail) => { - if (message === 'update-not-available') callback(detail) - } - - ipcRenderer.on('message', outerCallback) - return new Disposable(() => ipcRenderer.removeListener('message', outerCallback)) + return this.ipcMessageEmitter().on('update-not-available', callback) } onUpdateError (callback) { - const outerCallback = (event, message, detail) => { - if (message === 'update-error') callback(detail) - } - - ipcRenderer.on('message', outerCallback) - return new Disposable(() => ipcRenderer.removeListener('message', outerCallback)) + return this.ipcMessageEmitter().on('update-error', callback) } onApplicationMenuCommand (handler) { diff --git a/src/atom-environment.js b/src/atom-environment.js index 5a5264637..915ff78f1 100644 --- a/src/atom-environment.js +++ b/src/atom-environment.js @@ -64,7 +64,7 @@ class AtomEnvironment { this.applicationDelegate = params.applicationDelegate this.nextProxyRequestId = 0 - this.unloaded = false + this.unloading = false this.loadTime = null this.emitter = new Emitter() this.disposables = new CompositeDisposable() @@ -86,7 +86,7 @@ class AtomEnvironment { this.config = new Config({ saveCallback: settings => { if (this.enablePersistence) { - this.applicationDelegate.setUserSettings(settings) + this.applicationDelegate.setUserSettings(settings, this.config.getUserConfigPath()) } } }) @@ -280,7 +280,7 @@ class AtomEnvironment { attachSaveStateListeners () { const saveState = _.debounce(() => { this.window.requestIdleCallback(() => { - if (!this.unloaded) this.saveState({isUnloading: false}) + if (!this.unloading) this.saveState({isUnloading: false}) }) }, this.saveStateDebounceInterval) this.document.addEventListener('mousedown', saveState, true) @@ -487,21 +487,25 @@ class AtomEnvironment { // Public: Gets the release channel of the Atom application. // - // Returns the release channel as a {String}. Will return one of `dev`, `beta`, or `stable`. + // Returns the release channel as a {String}. Will return a specific release channel + // name like 'beta' or 'nightly' if one is found in the Atom version or 'stable' + // otherwise. getReleaseChannel () { - const version = this.getVersion() - if (version.includes('beta')) { - return 'beta' - } else if (version.includes('dev')) { - return 'dev' - } else { - return 'stable' + // This matches stable, dev (with or without commit hash) and any other + // release channel following the pattern '1.00.0-channel0' + const match = this.getVersion().match(/\d+\.\d+\.\d+(-([a-z]+)(\d+|-\w{4,})?)?$/) + if (!match) { + return 'unrecognized' + } else if (match[2]) { + return match[2] } + + return 'stable' } // Public: Returns a {Boolean} that is `true` if the current version is an official release. isReleasedVersion () { - return !/\w{7}/.test(this.getVersion()) // Check if the release is a 7-character SHA prefix + return this.getReleaseChannel().match(/stable|beta|nightly/) != null } // Public: Get the time taken to completely load the current window. @@ -771,7 +775,7 @@ class AtomEnvironment { await this.stateStore.clear() } - this.unloaded = false + this.unloading = false const updateProcessEnvPromise = this.updateProcessEnvAndTriggerHooks() @@ -796,21 +800,7 @@ class AtomEnvironment { this.disposables.add(this.applicationDelegate.onApplicationMenuCommand(this.dispatchApplicationMenuCommand.bind(this))) this.disposables.add(this.applicationDelegate.onContextMenuCommand(this.dispatchContextMenuCommand.bind(this))) this.disposables.add(this.applicationDelegate.onURIMessage(this.dispatchURIMessage.bind(this))) - this.disposables.add(this.applicationDelegate.onDidRequestUnload(async () => { - try { - await this.saveState({isUnloading: true}) - } catch (error) { - console.error(error) - } - - const closing = !this.workspace || await this.workspace.confirmClose({ - windowCloseRequested: true, - projectHasPaths: this.project.getPaths().length > 0 - }) - - if (closing) await this.packages.deactivatePackages() - return closing - })) + this.disposables.add(this.applicationDelegate.onDidRequestUnload(this.prepareToUnloadEditorWindow.bind(this))) this.listenForUpdates() @@ -889,12 +879,30 @@ class AtomEnvironment { } } + async prepareToUnloadEditorWindow () { + try { + await this.saveState({isUnloading: true}) + } catch (error) { + console.error(error) + } + + const closing = !this.workspace || await this.workspace.confirmClose({ + windowCloseRequested: true, + projectHasPaths: this.project.getPaths().length > 0 + }) + + if (closing) { + this.unloading = true + await this.packages.deactivatePackages() + } + return closing + } + unloadEditorWindow () { if (!this.project) return this.storeWindowBackground() this.saveBlobStoreSync() - this.unloaded = true } saveBlobStoreSync () { diff --git a/src/babel.js b/src/babel.js index a944f2e8c..8476a33c0 100644 --- a/src/babel.js +++ b/src/babel.js @@ -11,7 +11,8 @@ var PREFIXES = [ '/** @babel */', '"use babel"', '\'use babel\'', - '/* @flow */' + '/* @flow */', + '// @flow' ] var PREFIX_LENGTH = Math.max.apply(Math, PREFIXES.map(function (prefix) { diff --git a/src/clipboard.js b/src/clipboard.js index d36bb1018..eafc04d6f 100644 --- a/src/clipboard.js +++ b/src/clipboard.js @@ -1,5 +1,5 @@ const crypto = require('crypto') -const clipboard = require('./safe-clipboard') +const {clipboard} = require('electron') // Extended: Represents the clipboard used for copying and pasting in Atom. // @@ -7,10 +7,10 @@ const clipboard = require('./safe-clipboard') // // ## Examples // -// ```coffee +// ```js // atom.clipboard.write('hello') // -// console.log(atom.clipboard.read()) # 'hello' +// console.log(atom.clipboard.read()) // 'hello' // ``` module.exports = class Clipboard { @@ -59,7 +59,7 @@ class Clipboard { // * `text` The {String} clipboard text. // * `metadata` The metadata stored by an earlier call to {::write}. readWithMetadata () { - let text = this.read() + const text = this.read() if (this.signatureForMetadata === this.md5(text)) { return {text, metadata: this.metadata} } else { diff --git a/src/command-installer.js b/src/command-installer.js index 85360da17..b432023ba 100644 --- a/src/command-installer.js +++ b/src/command-installer.js @@ -27,22 +27,36 @@ class CommandInstaller { }, () => {}) } - this.installAtomCommand(true, error => { + this.installAtomCommand(true, (error, atomCommandName) => { if (error) return showErrorDialog(error) - this.installApmCommand(true, error => { + this.installApmCommand(true, (error, apmCommandName) => { if (error) return showErrorDialog(error) this.applicationDelegate.confirm({ message: 'Commands installed.', - detail: 'The shell commands `atom` and `apm` are installed.' + detail: `The shell commands \`${atomCommandName}\` and \`${apmCommandName}\` are installed.` }, () => {}) }) }) } + getCommandNameForChannel (commandName) { + let channelMatch = this.appVersion.match(/beta|nightly/) + let channel = channelMatch ? channelMatch[0] : '' + + switch (channel) { + case 'beta': + return `${commandName}-beta` + case 'nightly': + return `${commandName}-nightly` + default: + return commandName + } + } + installAtomCommand (askForPrivilege, callback) { this.installCommand( path.join(this.getResourcesDirectory(), 'app', 'atom.sh'), - this.appVersion.includes('beta') ? 'atom-beta' : 'atom', + this.getCommandNameForChannel('atom'), askForPrivilege, callback ) @@ -51,7 +65,7 @@ class CommandInstaller { installApmCommand (askForPrivilege, callback) { this.installCommand( path.join(this.getResourcesDirectory(), 'app', 'apm', 'node_modules', '.bin', 'apm'), - this.appVersion.includes('beta') ? 'apm-beta' : 'apm', + this.getCommandNameForChannel('apm'), askForPrivilege, callback ) @@ -64,11 +78,11 @@ class CommandInstaller { fs.readlink(destinationPath, (error, realpath) => { if (error && error.code !== 'ENOENT') return callback(error) - if (realpath === commandPath) return callback() + if (realpath === commandPath) return callback(null, commandName) this.createSymlink(fs, commandPath, destinationPath, error => { if (error && error.code === 'EACCES' && askForPrivilege) { const fsAdmin = require('fs-admin') - this.createSymlink(fsAdmin, commandPath, destinationPath, callback) + this.createSymlink(fsAdmin, commandPath, destinationPath, (error) => { callback(error, commandName) }) } else { callback(error) } diff --git a/src/compile-cache.js b/src/compile-cache.js index a4f9ded1e..ea387a631 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -17,6 +17,7 @@ var packageTranspilationRegistry = new PackageTranspilationRegistry() var COMPILERS = { '.js': packageTranspilationRegistry.wrapTranspiler(require('./babel')), '.ts': packageTranspilationRegistry.wrapTranspiler(require('./typescript')), + '.tsx': packageTranspilationRegistry.wrapTranspiler(require('./typescript')), '.coffee': packageTranspilationRegistry.wrapTranspiler(require('./coffee-script')) } diff --git a/src/config-file.js b/src/config-file.js index 38912beb1..f8cba37ef 100644 --- a/src/config-file.js +++ b/src/config-file.js @@ -6,6 +6,7 @@ const {watchPath} = require('./path-watcher') const CSON = require('season') const Path = require('path') const async = require('async') +const temp = require('temp') const EVENT_TYPES = new Set([ 'created', @@ -15,6 +16,21 @@ const EVENT_TYPES = new Set([ module.exports = class ConfigFile { + static at (path) { + if (!this._known) { + this._known = new Map() + } + + const existing = this._known.get(path) + if (existing) { + return existing + } + + const created = new ConfigFile(path) + this._known.set(path, created) + return created + } + constructor (path) { this.path = path this.emitter = new Emitter() @@ -22,9 +38,11 @@ class ConfigFile { this.reloadCallbacks = [] // Use a queue to prevent multiple concurrent write to the same file. - const writeQueue = async.queue((data, callback) => - CSON.writeFile(this.path, data, error => { - if (error) { + const writeQueue = async.queue((data, callback) => { + (async () => { + try { + await writeCSONFileAtomically(this.path, data) + } catch (error) { this.emitter.emit('did-error', dedent ` Failed to write \`${Path.basename(this.path)}\`. @@ -32,8 +50,8 @@ class ConfigFile { `) } callback() - }) - ) + })() + }) this.requestLoad = _.debounce(() => this.reload(), 200) this.requestSave = _.debounce((data) => writeQueue.push(data), 200) @@ -101,3 +119,27 @@ class ConfigFile { }) } } + +function writeCSONFile (path, data) { + return new Promise((resolve, reject) => { + CSON.writeFile(path, data, error => { + if (error) reject(error) + else resolve() + }) + }) +} + +async function writeCSONFileAtomically (path, data) { + const tempPath = temp.path() + await writeCSONFile(tempPath, data) + await rename(tempPath, path) +} + +function rename (oldPath, newPath) { + return new Promise((resolve, reject) => { + fs.rename(oldPath, newPath, error => { + if (error) reject(error) + else resolve() + }) + }) +} diff --git a/src/config-schema.js b/src/config-schema.js index 97a6d16f3..343726d2c 100644 --- a/src/config-schema.js +++ b/src/config-schema.js @@ -355,6 +355,21 @@ const configSchema = { type: 'boolean', default: false, description: 'Experimental: Use the new Tree-sitter parsing system for supported languages.' + }, + colorProfile: { + description: "Specify whether Atom should use the operating system's color profile (recommended) or an alternative color profile.
Changing this setting will require a relaunch of Atom to take effect.", + type: 'string', + default: 'default', + enum: [ + { + value: 'default', + description: 'Use color profile configured in the operating system' + }, + { + value: 'srgb', + description: 'Use sRGB color profile' + } + ] } } }, diff --git a/src/config.js b/src/config.js index b3636aa10..ce20db30c 100644 --- a/src/config.js +++ b/src/config.js @@ -8,6 +8,8 @@ const Color = require('./color') const ScopedPropertyStore = require('scoped-property-store') const ScopeDescriptor = require('./scope-descriptor') +const schemaEnforcers = {} + // Essential: Used to access all of Atom's configuration details. // // An instance of this class is always available as the `atom.config` global. @@ -41,7 +43,7 @@ const ScopeDescriptor = require('./scope-descriptor') // ### Value Coercion // // Config settings each have a type specified by way of a -// [schema](json-schema.org). For example we might an integer setting that only +// [schema](json-schema.org). For example we might want an integer setting that only // allows integers greater than `0`: // // ```coffee @@ -359,8 +361,6 @@ const ScopeDescriptor = require('./scope-descriptor') // // * Don't depend on (or write to) configuration keys outside of your keypath. // -const schemaEnforcers = {} - class Config { static addSchemaEnforcer (typeName, enforcerFunction) { if (schemaEnforcers[typeName] == null) { schemaEnforcers[typeName] = [] } @@ -823,21 +823,7 @@ class Config { } getLegacyScopeDescriptorForNewScopeDescriptor (scopeDescriptor) { - scopeDescriptor = ScopeDescriptor.fromObject(scopeDescriptor) - const legacyAlias = this.legacyScopeAliases.get(scopeDescriptor.scopes[0]) - if (legacyAlias) { - const scopes = scopeDescriptor.scopes.slice() - scopes[0] = legacyAlias - return new ScopeDescriptor({scopes}) - } - } - - setLegacyScopeAliasForNewScope (languageId, legacyScopeName) { - this.legacyScopeAliases.set(languageId, legacyScopeName) - } - - removeLegacyScopeAliasForNewScope (languageId) { - this.legacyScopeAliases.delete(languageId) + return null } /* diff --git a/src/cursor.js b/src/cursor.js index 929dc741f..f75f94709 100644 --- a/src/cursor.js +++ b/src/cursor.js @@ -326,7 +326,9 @@ class Cursor extends Model { // Public: Moves the cursor to the bottom of the buffer. moveToBottom () { + const column = this.goalColumn this.setBufferPosition(this.editor.getEofBufferPosition()) + this.goalColumn = column } // Public: Moves the cursor to the beginning of the line. @@ -664,7 +666,7 @@ class Cursor extends Model { // Returns a {RegExp}. wordRegExp (options) { const nonWordCharacters = _.escapeRegExp(this.getNonWordCharacters()) - let source = `^[\t\r ]*$|[^\\s${nonWordCharacters}]+` + let source = `^[\t ]*$|[^\\s${nonWordCharacters}]+` if (!options || options.includeNonWordCharacters !== false) { source += `|${`[${nonWordCharacters}]+`}` } @@ -711,6 +713,7 @@ class Cursor extends Model { changePosition (options, fn) { this.clearSelection({autoscroll: false}) fn() + this.goalColumn = null const autoscroll = (options && options.autoscroll != null) ? options.autoscroll : this.isLastCursor() diff --git a/src/decoration.js b/src/decoration.js index f1126f7a9..69bbcaa19 100644 --- a/src/decoration.js +++ b/src/decoration.js @@ -157,7 +157,7 @@ class Decoration { // ## Examples // // ```coffee - // decoration.update({type: 'line-number', class: 'my-new-class'}) + // decoration.setProperties({type: 'line-number', class: 'my-new-class'}) // ``` // // * `newProperties` {Object} eg. `{type: 'line-number', class: 'my-new-class'}` diff --git a/src/deprecated-packages.coffee b/src/deprecated-packages.coffee deleted file mode 100644 index 2eeea435c..000000000 --- a/src/deprecated-packages.coffee +++ /dev/null @@ -1,43 +0,0 @@ -semver = require 'semver' - -deprecatedPackages = require('../package.json')?._deprecatedPackages ? {} -ranges = {} - -exports.getDeprecatedPackageMetadata = (name) -> - metadata = null - if deprecatedPackages.hasOwnProperty(name) - metadata = deprecatedPackages[name] - Object.freeze(metadata) if metadata - metadata - -exports.isDeprecatedPackage = (name, version) -> - return false unless deprecatedPackages.hasOwnProperty(name) - - deprecatedVersionRange = deprecatedPackages[name].version - return true unless deprecatedVersionRange - - semver.valid(version) and satisfies(version, deprecatedVersionRange) - -satisfies = (version, rawRange) -> - unless parsedRange = ranges[rawRange] - parsedRange = new Range(rawRange) - ranges[rawRange] = parsedRange - parsedRange.test(version) - -# Extend semver.Range to memoize matched versions for speed -class Range extends semver.Range - constructor: -> - super - @matchedVersions = new Set() - @unmatchedVersions = new Set() - - test: (version) -> - return true if @matchedVersions.has(version) - return false if @unmatchedVersions.has(version) - - matches = super - if matches - @matchedVersions.add(version) - else - @unmatchedVersions.add(version) - matches diff --git a/src/dock.js b/src/dock.js index a9a97b43d..dc77365fb 100644 --- a/src/dock.js +++ b/src/dock.js @@ -1,11 +1,11 @@ -'use strict' - +const etch = require('etch') const _ = require('underscore-plus') const {CompositeDisposable, Emitter} = require('event-kit') const PaneContainer = require('./pane-container') const TextEditor = require('./text-editor') const Grim = require('grim') +const $ = etch.dom const MINIMUM_SIZE = 100 const DEFAULT_INITIAL_SIZE = 300 const SHOULD_ANIMATE_CLASS = 'atom-dock-should-animate' @@ -26,6 +26,8 @@ module.exports = class Dock { this.handleMouseUp = this.handleMouseUp.bind(this) this.handleDrag = _.throttle(this.handleDrag.bind(this), 30) this.handleDragEnd = this.handleDragEnd.bind(this) + this.handleToggleButtonDragEnter = this.handleToggleButtonDragEnter.bind(this) + this.toggle = this.toggle.bind(this) this.location = params.location this.widthOrHeight = getWidthOrHeight(this.location) @@ -72,11 +74,16 @@ module.exports = class Dock { // This method is called explicitly by the object which adds the Dock to the document. elementAttached () { // Re-render when the dock is attached to make sure we remeasure sizes defined in CSS. - this.render(this.state) + etch.updateSync(this) } getElement () { - if (!this.element) this.render(this.state) + // Because this code is included in the snapshot, we have to make sure we don't touch the DOM + // during initialization. Therefore, we defer initialization of the component (which creates a + // DOM element) until somebody asks for the element. + if (this.element == null) { + etch.initialize(this) + } return this.element } @@ -151,9 +158,16 @@ module.exports = class Dock { } this.state = nextState - this.render(this.state) const {hovered, visible} = this.state + + // Render immediately if the dock becomes visible or the size changes in case people are + // measuring after opening, for example. + if (this.element != null) { + if ((visible && !prevState.visible) || (this.state.size !== prevState.size)) etch.updateSync(this) + else etch.update(this) + } + if (hovered !== prevState.hovered) { this.emitter.emit('did-change-hovered', hovered) } @@ -162,80 +176,76 @@ module.exports = class Dock { } } - render (state) { - if (this.element == null) { - this.element = document.createElement('atom-dock') - this.element.classList.add(this.location) - this.innerElement = document.createElement('div') - this.innerElement.classList.add('atom-dock-inner', this.location) - this.maskElement = document.createElement('div') - this.maskElement.classList.add('atom-dock-mask') - this.wrapperElement = document.createElement('div') - this.wrapperElement.classList.add('atom-dock-content-wrapper', this.location) - this.resizeHandle = new DockResizeHandle({ - location: this.location, - onResizeStart: this.handleResizeHandleDragStart, - onResizeToFit: this.handleResizeToFit - }) - this.toggleButton = new DockToggleButton({ - onDragEnter: this.handleToggleButtonDragEnter.bind(this), - location: this.location, - toggle: this.toggle.bind(this) - }) - this.cursorOverlayElement = document.createElement('div') - this.cursorOverlayElement.classList.add('atom-dock-cursor-overlay', this.location) + render () { + const innerElementClassList = ['atom-dock-inner', this.location] + if (this.state.visible) innerElementClassList.push(VISIBLE_CLASS) - // Add the children to the DOM tree - this.element.appendChild(this.innerElement) - this.innerElement.appendChild(this.maskElement) - this.maskElement.appendChild(this.wrapperElement) - this.wrapperElement.appendChild(this.resizeHandle.getElement()) - this.wrapperElement.appendChild(this.paneContainer.getElement()) - this.wrapperElement.appendChild(this.cursorOverlayElement) - // The toggle button must be rendered outside the mask because (1) it shouldn't be masked and - // (2) if we made the mask larger to avoid masking it, the mask would block mouse events. - this.innerElement.appendChild(this.toggleButton.getElement()) - } + const maskElementClassList = ['atom-dock-mask'] + if (this.state.shouldAnimate) maskElementClassList.push(SHOULD_ANIMATE_CLASS) - if (state.visible) { - this.innerElement.classList.add(VISIBLE_CLASS) - } else { - this.innerElement.classList.remove(VISIBLE_CLASS) - } + const cursorOverlayElementClassList = ['atom-dock-cursor-overlay', this.location] + if (this.state.resizing) cursorOverlayElementClassList.push(CURSOR_OVERLAY_VISIBLE_CLASS) - if (state.shouldAnimate) { - this.maskElement.classList.add(SHOULD_ANIMATE_CLASS) - } else { - this.maskElement.classList.remove(SHOULD_ANIMATE_CLASS) - } - - if (state.resizing) { - this.cursorOverlayElement.classList.add(CURSOR_OVERLAY_VISIBLE_CLASS) - } else { - this.cursorOverlayElement.classList.remove(CURSOR_OVERLAY_VISIBLE_CLASS) - } - - const shouldBeVisible = state.visible || state.showDropTarget + const shouldBeVisible = this.state.visible || this.state.showDropTarget const size = Math.max(MINIMUM_SIZE, - state.size || - (state.draggingItem && getPreferredSize(state.draggingItem, this.location)) || + this.state.size || + (this.state.draggingItem && getPreferredSize(this.state.draggingItem, this.location)) || DEFAULT_INITIAL_SIZE ) // We need to change the size of the mask... - this.maskElement.style[this.widthOrHeight] = `${shouldBeVisible ? size : 0}px` + const maskStyle = {[this.widthOrHeight]: `${shouldBeVisible ? size : 0}px`} // ...but the content needs to maintain a constant size. - this.wrapperElement.style[this.widthOrHeight] = `${size}px` + const wrapperStyle = {[this.widthOrHeight]: `${size}px`} - this.resizeHandle.update({dockIsVisible: this.state.visible}) - this.toggleButton.update({ - dockIsVisible: shouldBeVisible, - visible: - // Don't show the toggle button if the dock is closed and empty... - (state.hovered && (this.state.visible || this.getPaneItems().length > 0)) || - // ...or if the item can't be dropped in that dock. - (!shouldBeVisible && state.draggingItem && isItemAllowed(state.draggingItem, this.location)) - }) + return $( + 'atom-dock', + {className: this.location}, + $.div( + {ref: 'innerElement', className: innerElementClassList.join(' ')}, + $.div( + { + className: maskElementClassList.join(' '), + style: maskStyle + }, + $.div( + { + ref: 'wrapperElement', + className: `atom-dock-content-wrapper ${this.location}`, + style: wrapperStyle + }, + $(DockResizeHandle, { + location: this.location, + onResizeStart: this.handleResizeHandleDragStart, + onResizeToFit: this.handleResizeToFit, + dockIsVisible: this.state.visible + }), + $(ElementComponent, {element: this.paneContainer.getElement()}), + $.div({className: cursorOverlayElementClassList.join(' ')}) + ) + ), + $(DockToggleButton, { + ref: 'toggleButton', + onDragEnter: this.state.draggingItem ? this.handleToggleButtonDragEnter : null, + location: this.location, + toggle: this.toggle, + dockIsVisible: shouldBeVisible, + visible: + // Don't show the toggle button if the dock is closed and empty... + (this.state.hovered && + (this.state.visible || this.getPaneItems().length > 0)) || + // ...or if the item can't be dropped in that dock. + (!shouldBeVisible && + this.state.draggingItem && + isItemAllowed(this.state.draggingItem, this.location)) + }) + ) + ) + } + + update (props) { + // Since we're interopping with non-etch stuff, this method's actually never called. + return etch.update(this) } handleDidAddPaneItem () { @@ -321,7 +331,7 @@ module.exports = class Dock { // area considered when detecting exit MUST fully encompass the area considered when detecting // entry. pointWithinHoverArea (point, detectingExit) { - const dockBounds = this.innerElement.getBoundingClientRect() + const dockBounds = this.refs.innerElement.getBoundingClientRect() // Copy the bounds object since we can't mutate it. const bounds = { @@ -370,7 +380,7 @@ module.exports = class Dock { // remove it as an argument and determine whether we're inside the toggle button using // mouseenter/leave events on it. This class would still need to keep track of the mouse // position (via a mousemove listener) for the other measurements, though. - const toggleButtonBounds = this.toggleButton.getBounds() + const toggleButtonBounds = this.refs.toggleButton.getBounds() if (rectContainsPoint(toggleButtonBounds, point)) return true // The area used when detecting exit is actually larger than when detecting entrances. Expand @@ -707,13 +717,18 @@ module.exports = class Dock { class DockResizeHandle { constructor (props) { - this.handleMouseDown = this.handleMouseDown.bind(this) - - this.element = document.createElement('div') - this.element.classList.add('atom-dock-resize-handle', props.location) - this.element.addEventListener('mousedown', this.handleMouseDown) this.props = props - this.update(props) + etch.initialize(this) + } + + render () { + const classList = ['atom-dock-resize-handle', this.props.location] + if (this.props.dockIsVisible) classList.push(RESIZE_HANDLE_RESIZABLE_CLASS) + + return $.div({ + className: classList.join(' '), + on: {mousedown: this.handleMouseDown} + }) } getElement () { @@ -729,12 +744,7 @@ class DockResizeHandle { update (newProps) { this.props = Object.assign({}, this.props, newProps) - - if (this.props.dockIsVisible) { - this.element.classList.add(RESIZE_HANDLE_RESIZABLE_CLASS) - } else { - this.element.classList.remove(RESIZE_HANDLE_RESIZABLE_CLASS) - } + return etch.update(this) } handleMouseDown (event) { @@ -748,22 +758,34 @@ class DockResizeHandle { class DockToggleButton { constructor (props) { - this.handleClick = this.handleClick.bind(this) - this.handleDragEnter = this.handleDragEnter.bind(this) - - this.element = document.createElement('div') - this.element.classList.add('atom-dock-toggle-button', props.location) - this.element.classList.add(props.location) - this.innerElement = document.createElement('div') - this.innerElement.classList.add('atom-dock-toggle-button-inner', props.location) - this.innerElement.addEventListener('click', this.handleClick) - this.innerElement.addEventListener('dragenter', this.handleDragEnter) - this.iconElement = document.createElement('span') - this.innerElement.appendChild(this.iconElement) - this.element.appendChild(this.innerElement) - this.props = props - this.update(props) + etch.initialize(this) + } + + render () { + const classList = ['atom-dock-toggle-button', this.props.location] + if (this.props.visible) classList.push(TOGGLE_BUTTON_VISIBLE_CLASS) + + return $.div( + {className: classList.join(' ')}, + $.div( + { + ref: 'innerElement', + className: `atom-dock-toggle-button-inner ${this.props.location}`, + on: { + click: this.handleClick, + dragenter: this.props.onDragEnter + } + }, + $.span({ + ref: 'iconElement', + className: `icon ${getIconName( + this.props.location, + this.props.dockIsVisible + )}` + }) + ) + ) } getElement () { @@ -771,27 +793,28 @@ class DockToggleButton { } getBounds () { - return this.innerElement.getBoundingClientRect() + return this.refs.innerElement.getBoundingClientRect() } update (newProps) { this.props = Object.assign({}, this.props, newProps) - - if (this.props.visible) { - this.element.classList.add(TOGGLE_BUTTON_VISIBLE_CLASS) - } else { - this.element.classList.remove(TOGGLE_BUTTON_VISIBLE_CLASS) - } - - this.iconElement.className = 'icon ' + getIconName(this.props.location, this.props.dockIsVisible) + return etch.update(this) } handleClick () { this.props.toggle() } +} - handleDragEnter () { - this.props.onDragEnter() +// An etch component that doesn't use etch, this component provides a gateway from JSX back into +// the mutable DOM world. +class ElementComponent { + constructor (props) { + this.element = props.element + } + + update (props) { + this.element = props.element } } diff --git a/src/git-repository.js b/src/git-repository.js index 55d70c12c..80f76e40a 100644 --- a/src/git-repository.js +++ b/src/git-repository.js @@ -163,7 +163,7 @@ class GitRepository { // Public: Invoke the given callback when a multiple files' statuses have // changed. For example, on window focus, the status of all the paths in the // repo is checked. If any of them have changed, this will be fired. Call - // {::getPathStatus(path)} to get the status for your path of choice. + // {::getPathStatus} to get the status for your path of choice. // // * `callback` {Function} // diff --git a/src/grammar-registry.js b/src/grammar-registry.js index 20757fb0b..0c79d5b1e 100644 --- a/src/grammar-registry.js +++ b/src/grammar-registry.js @@ -10,7 +10,6 @@ const Token = require('./token') const fs = require('fs-plus') const {Point, Range} = require('text-buffer') -const GRAMMAR_TYPE_BONUS = 1000 const PATH_SPLIT_REGEX = new RegExp('[/.]') // Extended: This class holds the grammars used for tokenizing. @@ -38,6 +37,14 @@ class GrammarRegistry { const grammarAddedOrUpdated = this.grammarAddedOrUpdated.bind(this) this.textmateRegistry.onDidAddGrammar(grammarAddedOrUpdated) this.textmateRegistry.onDidUpdateGrammar(grammarAddedOrUpdated) + + this.subscriptions.add(this.config.onDidChange('core.useTreeSitterParsers', () => { + this.grammarScoresByBuffer.forEach((score, buffer) => { + if (!this.languageOverridesByBufferId.has(buffer.id)) { + this.autoAssignLanguageMode(buffer) + } + }) + })) } serialize () { @@ -115,7 +122,6 @@ class GrammarRegistry { // found. assignLanguageMode (buffer, languageId) { if (buffer.getBuffer) buffer = buffer.getBuffer() - languageId = this.normalizeLanguageId(languageId) let grammar = null if (languageId != null) { @@ -128,7 +134,7 @@ class GrammarRegistry { } this.grammarScoresByBuffer.set(buffer, null) - if (grammar.scopeName !== buffer.getLanguageMode().getLanguageId()) { + if (grammar !== buffer.getLanguageMode().grammar) { buffer.setLanguageMode(this.languageModeForGrammarAndBuffer(grammar, buffer)) } @@ -155,14 +161,14 @@ class GrammarRegistry { ) this.languageOverridesByBufferId.delete(buffer.id) this.grammarScoresByBuffer.set(buffer, result.score) - if (result.grammar.scopeName !== buffer.getLanguageMode().getLanguageId()) { + if (result.grammar !== buffer.getLanguageMode().grammar) { buffer.setLanguageMode(this.languageModeForGrammarAndBuffer(result.grammar, buffer)) } } languageModeForGrammarAndBuffer (grammar, buffer) { if (grammar instanceof TreeSitterGrammar) { - return new TreeSitterLanguageMode({grammar, buffer, config: this.config}) + return new TreeSitterLanguageMode({grammar, buffer, config: this.config, grammars: this}) } else { return new TextMateLanguageMode({grammar, buffer, config: this.config}) } @@ -201,16 +207,34 @@ class GrammarRegistry { contents = fs.readFileSync(filePath, 'utf8') } + // Initially identify matching grammars based on the filename and the first + // line of the file. let score = this.getGrammarPathScore(grammar, filePath) - if (score > 0 && !grammar.bundledPackage) { - score += 0.125 - } - if (this.grammarMatchesContents(grammar, contents)) { - score += 0.25 - } + if (this.grammarMatchesPrefix(grammar, contents)) score += 0.5 - if (score > 0 && this.isGrammarPreferredType(grammar)) { - score += GRAMMAR_TYPE_BONUS + // If multiple grammars match by one of the above criteria, break ties. + if (score > 0) { + // Prefer either TextMate or Tree-sitter grammars based on the user's settings. + if (grammar instanceof TreeSitterGrammar) { + if (this.config.get('core.useTreeSitterParsers')) { + score += 0.1 + } else { + return -Infinity + } + } + + // Prefer grammars with matching content regexes. Prefer a grammar with no content regex + // over one with a non-matching content regex. + if (grammar.contentRegex) { + if (grammar.contentRegex.test(contents)) { + score += 0.05 + } else { + score -= 0.05 + } + } + + // Prefer grammars that the user has manually installed over bundled grammars. + if (!grammar.bundledPackage) score += 0.01 } return score @@ -248,12 +272,8 @@ class GrammarRegistry { return pathScore } - grammarMatchesContents (grammar, contents) { - if (contents == null) return false - - if (grammar.contentRegExp) { // TreeSitter grammars - return grammar.contentRegExp.test(contents) - } else if (grammar.firstLineRegex) { // FirstMate grammars + grammarMatchesPrefix (grammar, contents) { + if (contents && grammar.firstLineRegex) { let escaped = false let numberOfNewlinesInRegex = 0 for (let character of grammar.firstLineRegex.source) { @@ -270,8 +290,12 @@ class GrammarRegistry { } } - const lines = contents.split('\n') - return grammar.firstLineRegex.testSync(lines.slice(0, numberOfNewlinesInRegex + 1).join('\n')) + const prefix = contents.split('\n').slice(0, numberOfNewlinesInRegex + 1).join('\n') + if (grammar.firstLineRegex.testSync) { + return grammar.firstLineRegex.testSync(prefix) + } else { + return grammar.firstLineRegex.test(prefix) + } } else { return false } @@ -279,18 +303,25 @@ class GrammarRegistry { forEachGrammar (callback) { this.textmateRegistry.grammars.forEach(callback) - for (let grammarId in this.treeSitterGrammarsById) { - callback(this.treeSitterGrammarsById[grammarId]) + for (const grammarId in this.treeSitterGrammarsById) { + const grammar = this.treeSitterGrammarsById[grammarId] + if (grammar.scopeName) callback(grammar) } } grammarForId (languageId) { - languageId = this.normalizeLanguageId(languageId) - - return ( - this.textmateRegistry.grammarForScopeName(languageId) || - this.treeSitterGrammarsById[languageId] - ) + if (!languageId) return null + if (this.config.get('core.useTreeSitterParsers')) { + return ( + this.treeSitterGrammarsById[languageId] || + this.textmateRegistry.grammarForScopeName(languageId) + ) + } else { + return ( + this.textmateRegistry.grammarForScopeName(languageId) || + this.treeSitterGrammarsById[languageId] + ) + } } // Deprecated: Get the grammar override for the given file path. @@ -335,26 +366,23 @@ class GrammarRegistry { this.grammarScoresByBuffer.forEach((score, buffer) => { const languageMode = buffer.getLanguageMode() - if (grammar.injectionSelector) { - if (languageMode.hasTokenForSelector(grammar.injectionSelector)) { - languageMode.retokenizeLines() - } - return - } - const languageOverride = this.languageOverridesByBufferId.get(buffer.id) - if ((grammar.id === buffer.getLanguageMode().getLanguageId() || - grammar.id === languageOverride)) { + if (grammar === buffer.getLanguageMode().grammar || + grammar === this.grammarForId(languageOverride)) { buffer.setLanguageMode(this.languageModeForGrammarAndBuffer(grammar, buffer)) + return } else if (!languageOverride) { const score = this.getGrammarScore(grammar, buffer.getPath(), getGrammarSelectionContent(buffer)) const currentScore = this.grammarScoresByBuffer.get(buffer) if (currentScore == null || score > currentScore) { buffer.setLanguageMode(this.languageModeForGrammarAndBuffer(grammar, buffer)) this.grammarScoresByBuffer.set(buffer, score) + return } } + + languageMode.updateForInjection(grammar) }) } @@ -379,6 +407,32 @@ class GrammarRegistry { return this.textmateRegistry.onDidUpdateGrammar(callback) } + // Experimental: Specify a type of syntax node that may embed other languages. + // + // * `grammarId` The {String} id of the parent language + // * `injectionPoint` An {Object} with the following keys: + // * `type` The {String} type of syntax node that may embed other languages + // * `language` A {Function} that is called with syntax nodes of the specified `type` and + // returns a {String} that will be tested against other grammars' `injectionRegex` in + // order to determine what language should be embedded. + // * `content` A {Function} that is called with syntax nodes of the specified `type` and + // returns another syntax node or array of syntax nodes that contain the embedded source code. + addInjectionPoint (grammarId, injectionPoint) { + const grammar = this.treeSitterGrammarsById[grammarId] + if (grammar) { + grammar.injectionPoints.push(injectionPoint) + } else { + this.treeSitterGrammarsById[grammarId] = { + injectionPoints: [injectionPoint] + } + } + return new Disposable(() => { + const grammar = this.treeSitterGrammarsById[grammarId] + const index = grammar.injectionPoints.indexOf(injectionPoint) + if (index !== -1) grammar.injectionPoints.splice(index, 1) + }) + } + get nullGrammar () { return this.textmateRegistry.nullGrammar } @@ -397,12 +451,9 @@ class GrammarRegistry { addGrammar (grammar) { if (grammar instanceof TreeSitterGrammar) { - this.treeSitterGrammarsById[grammar.id] = grammar - if (grammar.legacyScopeName) { - this.config.setLegacyScopeAliasForNewScope(grammar.id, grammar.legacyScopeName) - this.textMateScopeNamesByTreeSitterLanguageId.set(grammar.id, grammar.legacyScopeName) - this.treeSitterLanguageIdsByTextMateScopeName.set(grammar.legacyScopeName, grammar.id) - } + const existingParams = this.treeSitterGrammarsById[grammar.scopeName] || {} + if (grammar.scopeName) this.treeSitterGrammarsById[grammar.scopeName] = grammar + if (existingParams.injectionPoints) grammar.injectionPoints.push(...existingParams.injectionPoints) this.grammarAddedOrUpdated(grammar) return new Disposable(() => this.removeGrammar(grammar)) } else { @@ -412,12 +463,7 @@ class GrammarRegistry { removeGrammar (grammar) { if (grammar instanceof TreeSitterGrammar) { - delete this.treeSitterGrammarsById[grammar.id] - if (grammar.legacyScopeName) { - this.config.removeLegacyScopeAliasForNewScope(grammar.id) - this.textMateScopeNamesByTreeSitterLanguageId.delete(grammar.id) - this.treeSitterLanguageIdsByTextMateScopeName.delete(grammar.legacyScopeName) - } + delete this.treeSitterGrammarsById[grammar.scopeName] } else { return this.textmateRegistry.removeGrammar(grammar) } @@ -503,10 +549,23 @@ class GrammarRegistry { return this.textmateRegistry.scopeForId(id) } - isGrammarPreferredType (grammar) { - return this.config.get('core.useTreeSitterParsers') - ? grammar instanceof TreeSitterGrammar - : grammar instanceof FirstMate.Grammar + treeSitterGrammarForLanguageString (languageString) { + let longestMatchLength = 0 + let grammarWithLongestMatch = null + for (const id in this.treeSitterGrammarsById) { + const grammar = this.treeSitterGrammarsById[id] + if (grammar.injectionRegex) { + const match = languageString.match(grammar.injectionRegex) + if (match) { + const {length} = match[0] + if (length > longestMatchLength) { + grammarWithLongestMatch = grammar + longestMatchLength = length + } + } + } + } + return grammarWithLongestMatch } normalizeLanguageId (languageId) { diff --git a/src/gutter-container.js b/src/gutter-container.js index 3faece073..cd0c796b2 100644 --- a/src/gutter-container.js +++ b/src/gutter-container.js @@ -97,7 +97,7 @@ module.exports = class GutterContainer { // The public interface is Gutter::decorateMarker or TextEditor::decorateMarker. addGutterDecoration (gutter, marker, options) { - if (gutter.name === 'line-number') { + if (gutter.type === 'line-number') { options.type = 'line-number' } else { options.type = 'gutter' diff --git a/src/gutter.js b/src/gutter.js index 3bf7a72ea..bd5955b78 100644 --- a/src/gutter.js +++ b/src/gutter.js @@ -11,6 +11,12 @@ module.exports = class Gutter { this.name = options && options.name this.priority = (options && options.priority != null) ? options.priority : DefaultPriority this.visible = (options && options.visible != null) ? options.visible : true + this.type = (options && options.type != null) ? options.type : 'decorated' + this.labelFn = options && options.labelFn + this.className = options && options.class + + this.onMouseDown = options && options.onMouseDown + this.onMouseMove = options && options.onMouseMove this.emitter = new Emitter() } diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index f8f670cf5..913c83977 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -36,6 +36,9 @@ if global.isGeneratingSnapshot require('image-view') require('incompatible-packages') require('keybinding-resolver') + require('language-html') + require('language-javascript') + require('language-ruby') require('line-ending-selector') require('link') require('markdown-preview') diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index c6aaada0e..4cbd02bfd 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -24,9 +24,13 @@ module.exports = ({blobStore}) -> ApplicationDelegate = require '../src/application-delegate' Clipboard = require '../src/clipboard' TextEditor = require '../src/text-editor' + {updateProcessEnv} = require('./update-process-env') require './electron-shims' - {testRunnerPath, legacyTestRunnerPath, headless, logFile, testPaths} = getWindowLoadSettings() + ipcRenderer.on 'environment', (event, env) -> + updateProcessEnv(env) + + {testRunnerPath, legacyTestRunnerPath, headless, logFile, testPaths, env} = getWindowLoadSettings() unless headless # Show window synchronously so a focusout doesn't fire on input elements @@ -59,6 +63,8 @@ module.exports = ({blobStore}) -> require('module').globalPaths.push(exportsPath) process.env.NODE_PATH = exportsPath # Set NODE_PATH env variable since tasks may need it. + updateProcessEnv(env) + # Set up optional transpilation for packages under test if any FindParentDir = require 'find-parent-dir' if packageRoot = FindParentDir.sync(testPaths[0], 'package.json') diff --git a/src/main-process/atom-application.js b/src/main-process/atom-application.js index 10b791761..c10895650 100644 --- a/src/main-process/atom-application.js +++ b/src/main-process/atom-application.js @@ -7,7 +7,7 @@ const Config = require('../config') const ConfigFile = require('../config-file') const FileRecoveryService = require('./file-recovery-service') const ipcHelpers = require('../ipc-helpers') -const {BrowserWindow, Menu, app, dialog, ipcMain, shell, screen} = require('electron') +const {BrowserWindow, Menu, app, clipboard, dialog, ipcMain, shell, screen} = require('electron') const {CompositeDisposable, Disposable} = require('event-kit') const crypto = require('crypto') const fs = require('fs-plus') @@ -113,10 +113,12 @@ class AtomApplication extends EventEmitter { ? path.join(process.env.ATOM_HOME, 'config.json') : path.join(process.env.ATOM_HOME, 'config.cson') - this.configFile = new ConfigFile(configFilePath) + this.configFile = ConfigFile.at(configFilePath) this.config = new Config({ saveCallback: settings => { - if (!this.quitting) return this.configFile.update(settings) + if (!this.quitting) { + return this.configFile.update(settings) + } } }) this.config.setSchema(null, {type: 'object', properties: _.clone(ConfigSchema)}) @@ -137,7 +139,7 @@ class AtomApplication extends EventEmitter { // for testing purposes without booting up the world. As you add tests, feel free to move instantiation // of these various sub-objects into the constructor, but you'll need to remove the side-effects they // perform during their construction, adding an initialize method that you call here. - initialize (options) { + async initialize (options) { global.atomApplication = this // DEPRECATED: This can be removed at some point (added in 1.13) @@ -147,14 +149,15 @@ class AtomApplication extends EventEmitter { this.config.set('core.titleBar', 'custom') } - process.nextTick(() => this.autoUpdateManager.initialize()) this.applicationMenu = new ApplicationMenu(this.version, this.autoUpdateManager) this.atomProtocolHandler = new AtomProtocolHandler(this.resourcePath, this.safeMode) this.listenForArgumentsFromNewProcess() this.setupDockMenu() - return this.launch(options) + const result = await this.launch(options) + this.autoUpdateManager.initialize() + return result } async destroy () { @@ -170,7 +173,8 @@ class AtomApplication extends EventEmitter { if (!this.configFilePromise) { this.configFilePromise = this.configFile.watch() this.disposable.add(await this.configFilePromise) - this.config.onDidChange('core.titleBar', this.promptForRestart.bind(this)) + this.config.onDidChange('core.titleBar', () => this.promptForRestart()) + this.config.onDidChange('core.colorProfile', () => this.promptForRestart()) } const optionsForWindowsToOpen = [] @@ -202,7 +206,6 @@ class AtomApplication extends EventEmitter { openWithOptions (options) { const { - projectSpecification, initialPaths, pathsToOpen, executedFrom, @@ -257,7 +260,6 @@ class AtomApplication extends EventEmitter { profileStartup, clearWindowState, addToLastWindow, - projectSpecification, env }) } else if (urlsToOpen.length > 0) { @@ -435,9 +437,20 @@ class AtomApplication extends EventEmitter { if (!this.quitting) { this.quitting = true event.preventDefault() - const windowUnloadPromises = this.getAllWindows().map(window => window.prepareToUnload()) + const windowUnloadPromises = this.getAllWindows().map(async window => { + const unloaded = await window.prepareToUnload() + if (unloaded) { + window.close() + await window.closedPromise + } + return unloaded + }) const windowUnloadedResults = await Promise.all(windowUnloadPromises) - if (windowUnloadedResults.every(Boolean)) app.quit() + if (windowUnloadedResults.every(Boolean)) { + app.quit() + } else { + this.quitting = false + } } resolveBeforeQuitPromise() @@ -505,12 +518,12 @@ class AtomApplication extends EventEmitter { if (this.applicationMenu) this.applicationMenu.update(window, template, menu) })) - this.disposable.add(ipcHelpers.on(ipcMain, 'run-package-specs', (event, packageSpecPath) => { - this.runTests({ + this.disposable.add(ipcHelpers.on(ipcMain, 'run-package-specs', (event, packageSpecPath, options = {}) => { + this.runTests(Object.assign({ resourcePath: this.devResourcePath, pathsToOpen: [packageSpecPath], headless: false - }) + }, options)) })) this.disposable.add(ipcHelpers.on(ipcMain, 'run-benchmarks', (event, benchmarksPath) => { @@ -561,9 +574,11 @@ class AtomApplication extends EventEmitter { window.setPosition(x, y) })) - this.disposable.add(ipcHelpers.respondTo('set-user-settings', (window, settings) => - this.configFile.update(JSON.parse(settings)) - )) + this.disposable.add(ipcHelpers.respondTo('set-user-settings', (window, settings, filePath) => { + if (!this.quitting) { + ConfigFile.at(filePath || this.configFilePath).update(JSON.parse(settings)) + } + })) this.disposable.add(ipcHelpers.respondTo('center-window', window => window.center())) this.disposable.add(ipcHelpers.respondTo('focus-window', window => window.focus())) @@ -575,7 +590,6 @@ class AtomApplication extends EventEmitter { win.temporaryState = state })) - const clipboard = require('../safe-clipboard') this.disposable.add(ipcHelpers.on(ipcMain, 'write-text-to-selection-clipboard', (event, text) => clipboard.writeText(text, 'selection') )) @@ -821,7 +835,6 @@ class AtomApplication extends EventEmitter { window, clearWindowState, addToLastWindow, - projectSpecification, env } = {}) { if (!pathsToOpen || pathsToOpen.length === 0) return @@ -855,7 +868,7 @@ class AtomApplication extends EventEmitter { } let openedWindow - if (existingWindow && (projectSpecification == null || projectSpecification.config == null)) { + if (existingWindow) { openedWindow = existingWindow openedWindow.openLocations(locationsToOpen) if (openedWindow.isMinimized()) { @@ -891,7 +904,6 @@ class AtomApplication extends EventEmitter { windowDimensions, profileStartup, clearWindowState, - projectSpecification, env }) this.addWindow(openedWindow) @@ -1162,6 +1174,7 @@ class AtomApplication extends EventEmitter { env }) this.addWindow(window) + if (env) window.replaceEnvironment(env) return window } diff --git a/src/main-process/atom-protocol-handler.js b/src/main-process/atom-protocol-handler.js index 1affba02a..47c3da14f 100644 --- a/src/main-process/atom-protocol-handler.js +++ b/src/main-process/atom-protocol-handler.js @@ -20,6 +20,7 @@ class AtomProtocolHandler { if (!safeMode) { this.loadPaths.push(path.join(process.env.ATOM_HOME, 'dev', 'packages')) + this.loadPaths.push(path.join(resourcePath, 'packages')) } this.loadPaths.push(path.join(process.env.ATOM_HOME, 'packages')) diff --git a/src/main-process/atom-window.js b/src/main-process/atom-window.js index 7c4151403..a56679143 100644 --- a/src/main-process/atom-window.js +++ b/src/main-process/atom-window.js @@ -22,7 +22,6 @@ class AtomWindow extends EventEmitter { this.safeMode = settings.safeMode this.devMode = settings.devMode this.resourcePath = settings.resourcePath - this.projectSpecification = settings.projectSpecification let {pathToOpen, locationsToOpen} = settings if (!locationsToOpen && pathToOpen) locationsToOpen = [{pathToOpen}] @@ -52,7 +51,7 @@ class AtomWindow extends EventEmitter { // taskbar's icon. See https://github.com/atom/atom/issues/4811 for more. if (process.platform === 'linux') options.icon = ICON_PATH if (this.shouldAddCustomTitleBar()) options.titleBarStyle = 'hidden' - if (this.shouldAddCustomInsetTitleBar()) options.titleBarStyle = 'hidden-inset' + if (this.shouldAddCustomInsetTitleBar()) options.titleBarStyle = 'hiddenInset' if (this.shouldHideTitleBar()) options.frame = false this.browserWindow = new BrowserWindow(options) @@ -60,8 +59,7 @@ class AtomWindow extends EventEmitter { get: () => JSON.stringify(Object.assign({ userSettings: !this.isSpec ? this.atomApplication.configFile.get() - : null, - projectSpecification: this.projectSpecification + : null }, this.loadSettings)) }) @@ -187,6 +185,7 @@ class AtomWindow extends EventEmitter { dialog.showMessageBox(this.browserWindow, { type: 'warning', buttons: ['Force Close', 'Keep Waiting'], + cancelId: 1, // Canceling should be the least destructive action message: 'Editor is not responding', detail: 'The editor is not responding. Would you like to force close it or just keep waiting?' @@ -204,6 +203,7 @@ class AtomWindow extends EventEmitter { dialog.showMessageBox(this.browserWindow, { type: 'warning', buttons: ['Close Window', 'Reload', 'Keep It Open'], + cancelId: 2, // Canceling should be the least destructive action message: 'The editor has crashed', detail: 'Please report this issue to https://github.com/atom/atom' }, response => { diff --git a/src/main-process/auto-update-manager.coffee b/src/main-process/auto-update-manager.coffee deleted file mode 100644 index bc81d425d..000000000 --- a/src/main-process/auto-update-manager.coffee +++ /dev/null @@ -1,143 +0,0 @@ -autoUpdater = null -{EventEmitter} = require 'events' -path = require 'path' - -IdleState = 'idle' -CheckingState = 'checking' -DownloadingState = 'downloading' -UpdateAvailableState = 'update-available' -NoUpdateAvailableState = 'no-update-available' -UnsupportedState = 'unsupported' -ErrorState = 'error' - -module.exports = -class AutoUpdateManager - Object.assign @prototype, EventEmitter.prototype - - constructor: (@version, @testMode, @config) -> - @state = IdleState - @iconPath = path.resolve(__dirname, '..', '..', 'resources', 'atom.png') - - initialize: -> - if process.platform is 'win32' - archSuffix = if process.arch is 'ia32' then '' else '-' + process.arch - @feedUrl = "https://atom.io/api/updates#{archSuffix}?version=#{@version}" - autoUpdater = require './auto-updater-win32' - else - @feedUrl = "https://atom.io/api/updates?version=#{@version}" - {autoUpdater} = require 'electron' - - autoUpdater.on 'error', (event, message) => - @setState(ErrorState, message) - @emitWindowEvent('update-error') - console.error "Error Downloading Update: #{message}" - - autoUpdater.setFeedURL @feedUrl - - autoUpdater.on 'checking-for-update', => - @setState(CheckingState) - @emitWindowEvent('checking-for-update') - - autoUpdater.on 'update-not-available', => - @setState(NoUpdateAvailableState) - @emitWindowEvent('update-not-available') - - autoUpdater.on 'update-available', => - @setState(DownloadingState) - # We use sendMessage to send an event called 'update-available' in 'update-downloaded' - # once the update download is complete. This mismatch between the electron - # autoUpdater events is unfortunate but in the interest of not changing the - # one existing event handled by applicationDelegate - @emitWindowEvent('did-begin-downloading-update') - @emit('did-begin-download') - - autoUpdater.on 'update-downloaded', (event, releaseNotes, @releaseVersion) => - @setState(UpdateAvailableState) - @emitUpdateAvailableEvent() - - @config.onDidChange 'core.automaticallyUpdate', ({newValue}) => - if newValue - @scheduleUpdateCheck() - else - @cancelScheduledUpdateCheck() - - @scheduleUpdateCheck() if @config.get 'core.automaticallyUpdate' - - switch process.platform - when 'win32' - @setState(UnsupportedState) unless autoUpdater.supportsUpdates() - when 'linux' - @setState(UnsupportedState) - - emitUpdateAvailableEvent: -> - return unless @releaseVersion? - @emitWindowEvent('update-available', {@releaseVersion}) - return - - emitWindowEvent: (eventName, payload) -> - for atomWindow in @getWindows() - atomWindow.sendMessage(eventName, payload) - return - - setState: (state, errorMessage) -> - return if @state is state - @state = state - @errorMessage = errorMessage - @emit 'state-changed', @state - - getState: -> - @state - - getErrorMessage: -> - @errorMessage - - scheduleUpdateCheck: -> - # Only schedule update check periodically if running in release version and - # and there is no existing scheduled update check. - unless /\w{7}/.test(@version) or @checkForUpdatesIntervalID - checkForUpdates = => @check(hidePopups: true) - fourHours = 1000 * 60 * 60 * 4 - @checkForUpdatesIntervalID = setInterval(checkForUpdates, fourHours) - checkForUpdates() - - cancelScheduledUpdateCheck: -> - if @checkForUpdatesIntervalID - clearInterval(@checkForUpdatesIntervalID) - @checkForUpdatesIntervalID = null - - check: ({hidePopups}={}) -> - unless hidePopups - autoUpdater.once 'update-not-available', @onUpdateNotAvailable - autoUpdater.once 'error', @onUpdateError - - autoUpdater.checkForUpdates() unless @testMode - - install: -> - autoUpdater.quitAndInstall() unless @testMode - - onUpdateNotAvailable: => - autoUpdater.removeListener 'error', @onUpdateError - {dialog} = require 'electron' - dialog.showMessageBox { - type: 'info' - buttons: ['OK'] - icon: @iconPath - message: 'No update available.' - title: 'No Update Available' - detail: "Version #{@version} is the latest version." - }, -> # noop callback to get async behavior - - onUpdateError: (event, message) => - autoUpdater.removeListener 'update-not-available', @onUpdateNotAvailable - {dialog} = require 'electron' - dialog.showMessageBox { - type: 'warning' - buttons: ['OK'] - icon: @iconPath - message: 'There was an error checking for updates.' - title: 'Update Error' - detail: message - }, -> # noop callback to get async behavior - - getWindows: -> - global.atomApplication.getAllWindows() diff --git a/src/main-process/auto-update-manager.js b/src/main-process/auto-update-manager.js new file mode 100644 index 000000000..d9082b6c5 --- /dev/null +++ b/src/main-process/auto-update-manager.js @@ -0,0 +1,178 @@ +const {EventEmitter} = require('events') +const path = require('path') + +const IdleState = 'idle' +const CheckingState = 'checking' +const DownloadingState = 'downloading' +const UpdateAvailableState = 'update-available' +const NoUpdateAvailableState = 'no-update-available' +const UnsupportedState = 'unsupported' +const ErrorState = 'error' + +let autoUpdater = null + +module.exports = +class AutoUpdateManager extends EventEmitter { + constructor (version, testMode, config) { + super() + this.onUpdateNotAvailable = this.onUpdateNotAvailable.bind(this) + this.onUpdateError = this.onUpdateError.bind(this) + this.version = version + this.testMode = testMode + this.config = config + this.state = IdleState + this.iconPath = path.resolve(__dirname, '..', '..', 'resources', 'atom.png') + } + + initialize () { + if (process.platform === 'win32') { + const archSuffix = process.arch === 'ia32' ? '' : `-${process.arch}` + this.feedUrl = `https://atom.io/api/updates${archSuffix}?version=${this.version}` + autoUpdater = require('./auto-updater-win32') + } else { + this.feedUrl = `https://atom.io/api/updates?version=${this.version}`; + ({autoUpdater} = require('electron')) + } + + autoUpdater.on('error', (event, message) => { + this.setState(ErrorState, message) + this.emitWindowEvent('update-error') + console.error(`Error Downloading Update: ${message}`) + }) + + autoUpdater.setFeedURL(this.feedUrl) + + autoUpdater.on('checking-for-update', () => { + this.setState(CheckingState) + this.emitWindowEvent('checking-for-update') + }) + + autoUpdater.on('update-not-available', () => { + this.setState(NoUpdateAvailableState) + this.emitWindowEvent('update-not-available') + }) + + autoUpdater.on('update-available', () => { + this.setState(DownloadingState) + // We use sendMessage to send an event called 'update-available' in 'update-downloaded' + // once the update download is complete. This mismatch between the electron + // autoUpdater events is unfortunate but in the interest of not changing the + // one existing event handled by applicationDelegate + this.emitWindowEvent('did-begin-downloading-update') + this.emit('did-begin-download') + }) + + autoUpdater.on('update-downloaded', (event, releaseNotes, releaseVersion) => { + this.releaseVersion = releaseVersion + this.setState(UpdateAvailableState) + this.emitUpdateAvailableEvent() + }) + + this.config.onDidChange('core.automaticallyUpdate', ({newValue}) => { + if (newValue) { + this.scheduleUpdateCheck() + } else { + this.cancelScheduledUpdateCheck() + } + }) + + if (this.config.get('core.automaticallyUpdate')) this.scheduleUpdateCheck() + + switch (process.platform) { + case 'win32': + if (!autoUpdater.supportsUpdates()) { + this.setState(UnsupportedState) + } + break + case 'linux': + this.setState(UnsupportedState) + } + } + + emitUpdateAvailableEvent () { + if (this.releaseVersion == null) return + this.emitWindowEvent('update-available', {releaseVersion: this.releaseVersion}) + } + + emitWindowEvent (eventName, payload) { + for (let atomWindow of this.getWindows()) { + atomWindow.sendMessage(eventName, payload) + } + } + + setState (state, errorMessage) { + if (this.state === state) return + this.state = state + this.errorMessage = errorMessage + this.emit('state-changed', this.state) + } + + getState () { + return this.state + } + + getErrorMessage () { + return this.errorMessage + } + + scheduleUpdateCheck () { + // Only schedule update check periodically if running in release version and + // and there is no existing scheduled update check. + if (!/-dev/.test(this.version) && !this.checkForUpdatesIntervalID) { + const checkForUpdates = () => this.check({hidePopups: true}) + const fourHours = 1000 * 60 * 60 * 4 + this.checkForUpdatesIntervalID = setInterval(checkForUpdates, fourHours) + checkForUpdates() + } + } + + cancelScheduledUpdateCheck () { + if (this.checkForUpdatesIntervalID) { + clearInterval(this.checkForUpdatesIntervalID) + this.checkForUpdatesIntervalID = null + } + } + + check ({hidePopups} = {}) { + if (!hidePopups) { + autoUpdater.once('update-not-available', this.onUpdateNotAvailable) + autoUpdater.once('error', this.onUpdateError) + } + + if (!this.testMode) autoUpdater.checkForUpdates() + } + + install () { + if (!this.testMode) autoUpdater.quitAndInstall() + } + + onUpdateNotAvailable () { + autoUpdater.removeListener('error', this.onUpdateError) + const {dialog} = require('electron') + dialog.showMessageBox({ + type: 'info', + buttons: ['OK'], + icon: this.iconPath, + message: 'No update available.', + title: 'No Update Available', + detail: `Version ${this.version} is the latest version.` + }, () => {}) // noop callback to get async behavior + } + + onUpdateError (event, message) { + autoUpdater.removeListener('update-not-available', this.onUpdateNotAvailable) + const {dialog} = require('electron') + dialog.showMessageBox({ + type: 'warning', + buttons: ['OK'], + icon: this.iconPath, + message: 'There was an error checking for updates.', + title: 'Update Error', + detail: message + }, () => {}) // noop callback to get async behavior + } + + getWindows () { + return global.atomApplication.getAllWindows() + } +} diff --git a/src/main-process/auto-updater-win32.coffee b/src/main-process/auto-updater-win32.coffee deleted file mode 100644 index ee49e5096..000000000 --- a/src/main-process/auto-updater-win32.coffee +++ /dev/null @@ -1,62 +0,0 @@ -{EventEmitter} = require 'events' -SquirrelUpdate = require './squirrel-update' - -class AutoUpdater - Object.assign @prototype, EventEmitter.prototype - - setFeedURL: (@updateUrl) -> - - quitAndInstall: -> - if SquirrelUpdate.existsSync() - SquirrelUpdate.restartAtom(require('electron').app) - else - require('electron').autoUpdater.quitAndInstall() - - downloadUpdate: (callback) -> - SquirrelUpdate.spawn ['--download', @updateUrl], (error, stdout) -> - return callback(error) if error? - - try - # Last line of output is the JSON details about the releases - json = stdout.trim().split('\n').pop() - update = JSON.parse(json)?.releasesToApply?.pop?() - catch error - error.stdout = stdout - return callback(error) - - callback(null, update) - - installUpdate: (callback) -> - SquirrelUpdate.spawn(['--update', @updateUrl], callback) - - supportsUpdates: -> - SquirrelUpdate.existsSync() - - checkForUpdates: -> - throw new Error('Update URL is not set') unless @updateUrl - - @emit 'checking-for-update' - - unless SquirrelUpdate.existsSync() - @emit 'update-not-available' - return - - @downloadUpdate (error, update) => - if error? - @emit 'update-not-available' - return - - unless update? - @emit 'update-not-available' - return - - @emit 'update-available' - - @installUpdate (error) => - if error? - @emit 'update-not-available' - return - - @emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), 'https://atom.io', => @quitAndInstall() - -module.exports = new AutoUpdater() diff --git a/src/main-process/auto-updater-win32.js b/src/main-process/auto-updater-win32.js new file mode 100644 index 000000000..062d290b9 --- /dev/null +++ b/src/main-process/auto-updater-win32.js @@ -0,0 +1,88 @@ +const {EventEmitter} = require('events') +const SquirrelUpdate = require('./squirrel-update') + +class AutoUpdater extends EventEmitter { + setFeedURL (updateUrl) { + this.updateUrl = updateUrl + } + + quitAndInstall () { + if (SquirrelUpdate.existsSync()) { + SquirrelUpdate.restartAtom(require('electron').app) + } else { + require('electron').autoUpdater.quitAndInstall() + } + } + + downloadUpdate (callback) { + SquirrelUpdate.spawn(['--download', this.updateUrl], function (error, stdout) { + let update + if (error != null) return callback(error) + + try { + // Last line of output is the JSON details about the releases + const json = stdout.trim().split('\n').pop() + const data = JSON.parse(json) + const releasesToApply = data && data.releasesToApply + if (releasesToApply.pop) update = releasesToApply.pop() + } catch (error) { + error.stdout = stdout + return callback(error) + } + + callback(null, update) + }) + } + + installUpdate (callback) { + SquirrelUpdate.spawn(['--update', this.updateUrl], callback) + } + + supportsUpdates () { + SquirrelUpdate.existsSync() + } + + checkForUpdates () { + if (!this.updateUrl) throw new Error('Update URL is not set') + + this.emit('checking-for-update') + + if (!SquirrelUpdate.existsSync()) { + this.emit('update-not-available') + return + } + + this.downloadUpdate((error, update) => { + if (error != null) { + this.emit('update-not-available') + return + } + + if (update == null) { + this.emit('update-not-available') + return + } + + this.emit('update-available') + + this.installUpdate(error => { + if (error != null) { + this.emit('update-not-available') + return + } + + this.emit( + 'update-downloaded', + {}, + update.releaseNotes, + update.version, + new Date(), + 'https://atom.io', + () => this.quitAndInstall() + ) + }) + }) + } +} + +module.exports = new AutoUpdater() diff --git a/src/main-process/context-menu.coffee b/src/main-process/context-menu.coffee deleted file mode 100644 index ce1faf82d..000000000 --- a/src/main-process/context-menu.coffee +++ /dev/null @@ -1,24 +0,0 @@ -{Menu} = require 'electron' - -module.exports = -class ContextMenu - constructor: (template, @atomWindow) -> - template = @createClickHandlers(template) - menu = Menu.buildFromTemplate(template) - menu.popup(@atomWindow.browserWindow, {async: true}) - - # It's necessary to build the event handlers in this process, otherwise - # closures are dragged across processes and failed to be garbage collected - # appropriately. - createClickHandlers: (template) -> - for item in template - if item.command - item.commandDetail ?= {} - item.commandDetail.contextCommand = true - item.commandDetail.atomWindow = @atomWindow - do (item) => - item.click = => - global.atomApplication.sendCommandToWindow(item.command, @atomWindow, item.commandDetail) - else if item.submenu - @createClickHandlers(item.submenu) - item diff --git a/src/main-process/context-menu.js b/src/main-process/context-menu.js new file mode 100644 index 000000000..6726bbe12 --- /dev/null +++ b/src/main-process/context-menu.js @@ -0,0 +1,33 @@ +const {Menu} = require('electron') + +module.exports = +class ContextMenu { + constructor (template, atomWindow) { + this.atomWindow = atomWindow + this.createClickHandlers(template) + const menu = Menu.buildFromTemplate(template) + menu.popup(this.atomWindow.browserWindow, {async: true}) + } + + // It's necessary to build the event handlers in this process, otherwise + // closures are dragged across processes and failed to be garbage collected + // appropriately. + createClickHandlers (template) { + template.forEach(item => { + if (item.command) { + if (!item.commandDetail) item.commandDetail = {} + item.commandDetail.contextCommand = true + item.commandDetail.atomWindow = this.atomWindow + item.click = () => { + global.atomApplication.sendCommandToWindow( + item.command, + this.atomWindow, + item.commandDetail + ) + } + } else if (item.submenu) { + this.createClickHandlers(item.submenu) + } + }) + } +} diff --git a/src/main-process/file-recovery-service.js b/src/main-process/file-recovery-service.js index eef84089d..abe2df84e 100644 --- a/src/main-process/file-recovery-service.js +++ b/src/main-process/file-recovery-service.js @@ -2,6 +2,7 @@ const {dialog} = require('electron') const crypto = require('crypto') const Path = require('path') const fs = require('fs-plus') +const mkdirp = require('mkdirp') module.exports = class FileRecoveryService { @@ -147,15 +148,18 @@ async function tryStatFile (path) { async function copyFile (source, destination, mode) { return new Promise((resolve, reject) => { - const readStream = fs.createReadStream(source) - readStream - .on('error', reject) - .once('open', () => { - const writeStream = fs.createWriteStream(destination, {mode}) - writeStream - .on('error', reject) - .on('open', () => readStream.pipe(writeStream)) - .once('close', () => resolve()) - }) + mkdirp(Path.dirname(destination), (error) => { + if (error) return reject(error) + const readStream = fs.createReadStream(source) + readStream + .on('error', reject) + .once('open', () => { + const writeStream = fs.createWriteStream(destination, {mode}) + writeStream + .on('error', reject) + .on('open', () => readStream.pipe(writeStream)) + .once('close', () => resolve()) + }) + }) }) } diff --git a/src/main-process/main.js b/src/main-process/main.js index ee7b96232..11703bf3f 100644 --- a/src/main-process/main.js +++ b/src/main-process/main.js @@ -4,37 +4,55 @@ if (typeof snapshotResult !== 'undefined') { const startTime = Date.now() -const electron = require('electron') -const fs = require('fs') const path = require('path') +const fs = require('fs-plus') +const CSON = require('season') const yargs = require('yargs') +const electron = require('electron') const args = yargs(process.argv) .alias('d', 'dev') .alias('t', 'test') + .alias('r', 'resource-path') .argv +function isAtomRepoPath (repoPath) { + let packageJsonPath = path.join(repoPath, 'package.json') + if (fs.statSyncNoException(packageJsonPath)) { + let packageJson = CSON.readFileSync(packageJsonPath) + return packageJson.name === 'atom' + } + + return false +} + let resourcePath +let devResourcePath if (args.resourcePath) { resourcePath = args.resourcePath + devResourcePath = resourcePath } else { const stableResourcePath = path.dirname(path.dirname(__dirname)) const defaultRepositoryPath = path.join(electron.app.getPath('home'), 'github', 'atom') + if (process.env.ATOM_DEV_RESOURCE_PATH) { + devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH + } else if (isAtomRepoPath(process.cwd())) { + devResourcePath = process.cwd() + } else if (fs.statSyncNoException(defaultRepositoryPath)) { + devResourcePath = defaultRepositoryPath + } else { + devResourcePath = stableResourcePath + } + if (args.dev || args.test || args.benchmark || args.benchmarkTest) { - if (process.env.ATOM_DEV_RESOURCE_PATH) { - resourcePath = process.env.ATOM_DEV_RESOURCE_PATH - } else if (fs.statSyncNoException(defaultRepositoryPath)) { - resourcePath = defaultRepositoryPath - } else { - resourcePath = stableResourcePath - } + resourcePath = devResourcePath } else { resourcePath = stableResourcePath } } const start = require(path.join(resourcePath, 'src', 'main-process', 'start')) -start(resourcePath, startTime) +start(resourcePath, devResourcePath, startTime) diff --git a/src/main-process/parse-command-line.js b/src/main-process/parse-command-line.js index d844b4033..5d7849eac 100644 --- a/src/main-process/parse-command-line.js +++ b/src/main-process/parse-command-line.js @@ -3,9 +3,6 @@ const dedent = require('dedent') const yargs = require('yargs') const {app} = require('electron') -const path = require('path') -const fs = require('fs-plus') -const CSON = require('season') module.exports = function parseCommandLine (processArgs) { const options = yargs(processArgs).wrap(yargs.terminalWidth()) @@ -13,13 +10,18 @@ module.exports = function parseCommandLine (processArgs) { options.usage( dedent`Atom Editor v${version} - Usage: atom [options] [path ...] + Usage: + atom [options] [path ...] + atom file[:line[:column]] One or more paths to files or folders may be specified. If there is an existing Atom window that contains all of the given folders, the paths will be opened in that window. Otherwise, they will be opened in a new window. + A file may be opened at the desired line (and optionally column) by + appending the numbers right after the file name, e.g. \`atom file:5:8\`. + Paths that start with \`atom://\` will be interpreted as URLs. Environment Variables: @@ -53,7 +55,6 @@ module.exports = function parseCommandLine (processArgs) { 'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).' ) options.alias('v', 'version').boolean('v').describe('v', 'Print the version information.') - options.alias('p', 'project').describe('p', 'Start Atom with a project specification file.') options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.') options.alias('a', 'add').boolean('a').describe('add', 'Open path as a new project in last used window.') options.string('socket-path') @@ -93,7 +94,6 @@ module.exports = function parseCommandLine (processArgs) { const benchmark = args['benchmark'] const benchmarkTest = args['benchmark-test'] const test = args['test'] - const projectSpecificationFile = args['project'] const mainProcess = args['main-process'] const timeout = args['timeout'] const newWindow = args['new-window'] @@ -117,8 +117,6 @@ module.exports = function parseCommandLine (processArgs) { let pathsToOpen = [] let urlsToOpen = [] let devMode = args['dev'] - let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom') - let resourcePath = null for (const path of args._) { if (path.startsWith('atom://')) { @@ -128,44 +126,8 @@ module.exports = function parseCommandLine (processArgs) { } } - // Check to see if project flag is set, then add all paths from the .atomproject. - if (args['resource-path']) { + if (args.resourcePath || test) { devMode = true - devResourcePath = args['resource-path'] - } - - if (test) { - devMode = true - } - - let projectSpecification = {} - if (projectSpecificationFile) { - const readPath = path.isAbsolute(projectSpecificationFile) - ? projectSpecificationFile - : path.join(executedFrom, projectSpecificationFile) - - const contents = Object.assign({}, readProjectSpecificationSync(readPath, executedFrom)) - const pathToProjectFile = path.join(executedFrom, projectSpecificationFile) - - const base = path.dirname(pathToProjectFile) - pathsToOpen.push(path.dirname(projectSpecificationFile)) - const paths = (contents.paths == null) - ? undefined - : contents.paths.map(curPath => path.resolve(base, curPath)) - - projectSpecification = { - originPath: pathToProjectFile, - paths, - config: contents.config - } - } - - if (devMode) { - resourcePath = devResourcePath - } - - if (!fs.statSyncNoException(resourcePath)) { - resourcePath = path.dirname(path.dirname(__dirname)) } if (args['path-environment']) { @@ -174,13 +136,7 @@ module.exports = function parseCommandLine (processArgs) { process.env.PATH = args['path-environment'] } - resourcePath = normalizeDriveLetterName(resourcePath) - devResourcePath = normalizeDriveLetterName(devResourcePath) - return { - projectSpecification, - resourcePath, - devResourcePath, pathsToOpen, urlsToOpen, executedFrom, @@ -203,23 +159,3 @@ module.exports = function parseCommandLine (processArgs) { env: process.env } } - -function readProjectSpecificationSync (filepath, executedFrom) { - let contents - try { - contents = CSON.readFileSync(filepath) - } catch (e) { - throw new Error('Unable to read supplied project specification file.') - } - - contents.config = (contents.config == null) ? {} : contents.config - return contents -} - -function normalizeDriveLetterName (filePath) { - if (process.platform === 'win32') { - return filePath.replace(/^([a-z]):/, ([driveLetter]) => driveLetter.toUpperCase() + ':') - } else { - return filePath - } -} diff --git a/src/main-process/spawner.coffee b/src/main-process/spawner.coffee deleted file mode 100644 index edf93182e..000000000 --- a/src/main-process/spawner.coffee +++ /dev/null @@ -1,36 +0,0 @@ -ChildProcess = require 'child_process' - -# Spawn a command and invoke the callback when it completes with an error -# and the output from standard out. -# -# * `command` The underlying OS command {String} to execute. -# * `args` (optional) The {Array} with arguments to be passed to command. -# * `callback` (optional) The {Function} to call after the command has run. It will be invoked with arguments: -# * `error` (optional) An {Error} object returned by the command, `null` if no error was thrown. -# * `code` Error code returned by the command. -# * `stdout` The {String} output text generated by the command. -# * `stdout` The {String} output text generated by the command. -# -# Returns `undefined`. -exports.spawn = (command, args, callback) -> - stdout = '' - - try - spawnedProcess = ChildProcess.spawn(command, args) - catch error - # Spawn can throw an error - process.nextTick -> callback?(error, stdout) - return - - spawnedProcess.stdout.on 'data', (data) -> stdout += data - - error = null - spawnedProcess.on 'error', (processError) -> error ?= processError - spawnedProcess.on 'close', (code, signal) -> - error ?= new Error("Command failed: #{signal ? code}") if code isnt 0 - error?.code ?= code - error?.stdout ?= stdout - callback?(error, stdout) - # This is necessary if using Powershell 2 on Windows 7 to get the events to raise - # http://stackoverflow.com/questions/9155289/calling-powershell-from-nodejs - spawnedProcess.stdin.end() diff --git a/src/main-process/spawner.js b/src/main-process/spawner.js new file mode 100644 index 000000000..e39e0ff4e --- /dev/null +++ b/src/main-process/spawner.js @@ -0,0 +1,43 @@ +const ChildProcess = require('child_process') + +// Spawn a command and invoke the callback when it completes with an error +// and the output from standard out. +// +// * `command` The underlying OS command {String} to execute. +// * `args` (optional) The {Array} with arguments to be passed to command. +// * `callback` (optional) The {Function} to call after the command has run. It will be invoked with arguments: +// * `error` (optional) An {Error} object returned by the command, `null` if no error was thrown. +// * `code` Error code returned by the command. +// * `stdout` The {String} output text generated by the command. +// * `stdout` The {String} output text generated by the command. +exports.spawn = function (command, args, callback) { + let error + let spawnedProcess + let stdout = '' + + try { + spawnedProcess = ChildProcess.spawn(command, args) + } catch (error) { + process.nextTick(() => callback && callback(error, stdout)) + return + } + + spawnedProcess.stdout.on('data', data => { stdout += data }) + spawnedProcess.on('error', processError => { error = processError }) + spawnedProcess.on('close', (code, signal) => { + if (!error && code !== 0) { + error = new Error(`Command failed: ${signal != null ? signal : code}`) + } + + if (error) { + if (error.code == null) error.code = code + if (error.stdout == null) error.stdout = stdout + } + + callback && callback(error, stdout) + }) + + // This is necessary if using Powershell 2 on Windows 7 to get the events to raise + // http://stackoverflow.com/questions/9155289/calling-powershell-from-nodejs + return spawnedProcess.stdin.end() +} diff --git a/src/main-process/squirrel-update.coffee b/src/main-process/squirrel-update.coffee deleted file mode 100644 index 9bee339a2..000000000 --- a/src/main-process/squirrel-update.coffee +++ /dev/null @@ -1,162 +0,0 @@ -fs = require 'fs-plus' -path = require 'path' -Spawner = require './spawner' -WinShell = require './win-shell' -WinPowerShell = require './win-powershell' - -appFolder = path.resolve(process.execPath, '..') -rootAtomFolder = path.resolve(appFolder, '..') -binFolder = path.join(rootAtomFolder, 'bin') -updateDotExe = path.join(rootAtomFolder, 'Update.exe') -exeName = path.basename(process.execPath) - -if process.env.SystemRoot - system32Path = path.join(process.env.SystemRoot, 'System32') - setxPath = path.join(system32Path, 'setx.exe') -else - setxPath = 'setx.exe' - -# Spawn setx.exe and callback when it completes -spawnSetx = (args, callback) -> - Spawner.spawn(setxPath, args, callback) - -# Spawn the Update.exe with the given arguments and invoke the callback when -# the command completes. -spawnUpdate = (args, callback) -> - Spawner.spawn(updateDotExe, args, callback) - -# Add atom and apm to the PATH -# -# This is done by adding .cmd shims to the root bin folder in the Atom -# install directory that point to the newly installed versions inside -# the versioned app directories. -addCommandsToPath = (callback) -> - installCommands = (callback) -> - atomCommandPath = path.join(binFolder, 'atom.cmd') - relativeAtomPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'atom.cmd')) - atomCommand = "@echo off\r\n\"%~dp0\\#{relativeAtomPath}\" %*" - - atomShCommandPath = path.join(binFolder, 'atom') - relativeAtomShPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'atom.sh')) - atomShCommand = "#!/bin/sh\r\n\"$(dirname \"$0\")/#{relativeAtomShPath.replace(/\\/g, '/')}\" \"$@\"\r\necho" - - apmCommandPath = path.join(binFolder, 'apm.cmd') - relativeApmPath = path.relative(binFolder, path.join(process.resourcesPath, 'app', 'apm', 'bin', 'apm.cmd')) - apmCommand = "@echo off\r\n\"%~dp0\\#{relativeApmPath}\" %*" - - apmShCommandPath = path.join(binFolder, 'apm') - relativeApmShPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'apm.sh')) - apmShCommand = "#!/bin/sh\r\n\"$(dirname \"$0\")/#{relativeApmShPath.replace(/\\/g, '/')}\" \"$@\"" - - fs.writeFile atomCommandPath, atomCommand, -> - fs.writeFile atomShCommandPath, atomShCommand, -> - fs.writeFile apmCommandPath, apmCommand, -> - fs.writeFile apmShCommandPath, apmShCommand, -> - callback() - - addBinToPath = (pathSegments, callback) -> - pathSegments.push(binFolder) - newPathEnv = pathSegments.join(';') - spawnSetx(['Path', newPathEnv], callback) - - installCommands (error) -> - return callback(error) if error? - - WinPowerShell.getPath (error, pathEnv) -> - return callback(error) if error? - - pathSegments = pathEnv.split(/;+/).filter (pathSegment) -> pathSegment - if pathSegments.indexOf(binFolder) is -1 - addBinToPath(pathSegments, callback) - else - callback() - -# Remove atom and apm from the PATH -removeCommandsFromPath = (callback) -> - WinPowerShell.getPath (error, pathEnv) -> - return callback(error) if error? - - pathSegments = pathEnv.split(/;+/).filter (pathSegment) -> - pathSegment and pathSegment isnt binFolder - newPathEnv = pathSegments.join(';') - - if pathEnv isnt newPathEnv - spawnSetx(['Path', newPathEnv], callback) - else - callback() - -# Create a desktop and start menu shortcut by using the command line API -# provided by Squirrel's Update.exe -createShortcuts = (locations, callback) -> - spawnUpdate(['--createShortcut', exeName, '-l', locations.join(',')], callback) - -# Update the desktop and start menu shortcuts by using the command line API -# provided by Squirrel's Update.exe -updateShortcuts = (callback) -> - if homeDirectory = fs.getHomeDirectory() - desktopShortcutPath = path.join(homeDirectory, 'Desktop', 'Atom.lnk') - # Check if the desktop shortcut has been previously deleted and - # and keep it deleted if it was - fs.exists desktopShortcutPath, (desktopShortcutExists) -> - locations = ['StartMenu'] - locations.push 'Desktop' if desktopShortcutExists - - createShortcuts locations, callback - else - createShortcuts ['Desktop', 'StartMenu'], callback - -# Remove the desktop and start menu shortcuts by using the command line API -# provided by Squirrel's Update.exe -removeShortcuts = (callback) -> - spawnUpdate(['--removeShortcut', exeName], callback) - -exports.spawn = spawnUpdate - -# Is the Update.exe installed with Atom? -exports.existsSync = -> - fs.existsSync(updateDotExe) - -# Restart Atom using the version pointed to by the atom.cmd shim -exports.restartAtom = (app) -> - if projectPath = global.atomApplication?.lastFocusedWindow?.projectPath - args = [projectPath] - app.once 'will-quit', -> Spawner.spawn(path.join(binFolder, 'atom.cmd'), args) - app.quit() - -updateContextMenus = (callback) -> - WinShell.fileContextMenu.update -> - WinShell.folderContextMenu.update -> - WinShell.folderBackgroundContextMenu.update -> - callback() - -# Handle squirrel events denoted by --squirrel-* command line arguments. -exports.handleStartupEvent = (app, squirrelCommand) -> - switch squirrelCommand - when '--squirrel-install' - createShortcuts ['Desktop', 'StartMenu'], -> - addCommandsToPath -> - WinShell.fileHandler.register -> - updateContextMenus -> - app.quit() - true - when '--squirrel-updated' - updateShortcuts -> - addCommandsToPath -> - WinShell.fileHandler.update -> - updateContextMenus -> - app.quit() - true - when '--squirrel-uninstall' - removeShortcuts -> - removeCommandsFromPath -> - WinShell.fileHandler.deregister -> - WinShell.fileContextMenu.deregister -> - WinShell.folderContextMenu.deregister -> - WinShell.folderBackgroundContextMenu.deregister -> - app.quit() - true - when '--squirrel-obsolete' - app.quit() - true - else - false diff --git a/src/main-process/squirrel-update.js b/src/main-process/squirrel-update.js new file mode 100644 index 000000000..0d8174f47 --- /dev/null +++ b/src/main-process/squirrel-update.js @@ -0,0 +1,187 @@ +let setxPath +const fs = require('fs-plus') +const path = require('path') +const Spawner = require('./spawner') +const WinShell = require('./win-shell') +const WinPowerShell = require('./win-powershell') + +const appFolder = path.resolve(process.execPath, '..') +const rootAtomFolder = path.resolve(appFolder, '..') +const binFolder = path.join(rootAtomFolder, 'bin') +const updateDotExe = path.join(rootAtomFolder, 'Update.exe') +const exeName = path.basename(process.execPath) + +if (process.env.SystemRoot) { + const system32Path = path.join(process.env.SystemRoot, 'System32') + setxPath = path.join(system32Path, 'setx.exe') +} else { + setxPath = 'setx.exe' +} + +// Spawn setx.exe and callback when it completes +const spawnSetx = (args, callback) => Spawner.spawn(setxPath, args, callback) + +// Spawn the Update.exe with the given arguments and invoke the callback when +// the command completes. +const spawnUpdate = (args, callback) => Spawner.spawn(updateDotExe, args, callback) + +// Add atom and apm to the PATH +// +// This is done by adding .cmd shims to the root bin folder in the Atom +// install directory that point to the newly installed versions inside +// the versioned app directories. +const addCommandsToPath = callback => { + const installCommands = callback => { + const atomCommandPath = path.join(binFolder, 'atom.cmd') + const relativeAtomPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'atom.cmd')) + const atomCommand = `@echo off\r\n\"%~dp0\\${relativeAtomPath}\" %*` + + const atomShCommandPath = path.join(binFolder, 'atom') + const relativeAtomShPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'atom.sh')) + const atomShCommand = `#!/bin/sh\r\n\"$(dirname \"$0\")/${relativeAtomShPath.replace(/\\/g, '/')}\" \"$@\"\r\necho` + + const apmCommandPath = path.join(binFolder, 'apm.cmd') + const relativeApmPath = path.relative(binFolder, path.join(process.resourcesPath, 'app', 'apm', 'bin', 'apm.cmd')) + const apmCommand = `@echo off\r\n\"%~dp0\\${relativeApmPath}\" %*` + + const apmShCommandPath = path.join(binFolder, 'apm') + const relativeApmShPath = path.relative(binFolder, path.join(appFolder, 'resources', 'cli', 'apm.sh')) + const apmShCommand = `#!/bin/sh\r\n\"$(dirname \"$0\")/${relativeApmShPath.replace(/\\/g, '/')}\" \"$@\"` + + fs.writeFile(atomCommandPath, atomCommand, () => + fs.writeFile(atomShCommandPath, atomShCommand, () => + fs.writeFile(apmCommandPath, apmCommand, () => + fs.writeFile(apmShCommandPath, apmShCommand, () => callback()) + ) + ) + ) + } + + const addBinToPath = (pathSegments, callback) => { + pathSegments.push(binFolder) + const newPathEnv = pathSegments.join(';') + spawnSetx(['Path', newPathEnv], callback) + } + + installCommands(error => { + if (error) return callback(error) + + WinPowerShell.getPath((error, pathEnv) => { + if (error) return callback(error) + + const pathSegments = pathEnv.split(/;+/).filter(pathSegment => pathSegment) + if (pathSegments.indexOf(binFolder) === -1) { + addBinToPath(pathSegments, callback) + } else { + callback() + } + }) + }) +} + +// Remove atom and apm from the PATH +const removeCommandsFromPath = callback => + WinPowerShell.getPath((error, pathEnv) => { + if (error != null) { return callback(error) } + + const pathSegments = pathEnv.split(/;+/).filter(pathSegment => pathSegment && (pathSegment !== binFolder)) + const newPathEnv = pathSegments.join(';') + + if (pathEnv !== newPathEnv) { + return spawnSetx(['Path', newPathEnv], callback) + } else { + return callback() + } + }) + +// Create a desktop and start menu shortcut by using the command line API +// provided by Squirrel's Update.exe +const createShortcuts = (locations, callback) => spawnUpdate(['--createShortcut', exeName, '-l', locations.join(',')], callback) + +// Update the desktop and start menu shortcuts by using the command line API +// provided by Squirrel's Update.exe +const updateShortcuts = (callback) => { + const homeDirectory = fs.getHomeDirectory() + if (homeDirectory) { + const desktopShortcutPath = path.join(homeDirectory, 'Desktop', 'Atom.lnk') + // Check if the desktop shortcut has been previously deleted and + // and keep it deleted if it was + fs.exists(desktopShortcutPath, (desktopShortcutExists) => { + const locations = ['StartMenu'] + if (desktopShortcutExists) { locations.push('Desktop') } + + createShortcuts(locations, callback) + }) + } else { + createShortcuts(['Desktop', 'StartMenu'], callback) + } +} + +// Remove the desktop and start menu shortcuts by using the command line API +// provided by Squirrel's Update.exe +const removeShortcuts = callback => spawnUpdate(['--removeShortcut', exeName], callback) + +exports.spawn = spawnUpdate + +// Is the Update.exe installed with Atom? +exports.existsSync = () => fs.existsSync(updateDotExe) + +// Restart Atom using the version pointed to by the atom.cmd shim +exports.restartAtom = (app) => { + let args + if (global.atomApplication && global.atomApplication.lastFocusedWindow) { + const {projectPath} = global.atomApplication.lastFocusedWindow + if (projectPath) args = [projectPath] + } + app.once('will-quit', () => Spawner.spawn(path.join(binFolder, 'atom.cmd'), args)) + app.quit() +} + +const updateContextMenus = callback => + WinShell.fileContextMenu.update(() => + WinShell.folderContextMenu.update(() => + WinShell.folderBackgroundContextMenu.update(() => callback()) + ) + ) + +// Handle squirrel events denoted by --squirrel-* command line arguments. +exports.handleStartupEvent = (app, squirrelCommand) => { + switch (squirrelCommand) { + case '--squirrel-install': + createShortcuts(['Desktop', 'StartMenu'], () => + addCommandsToPath(() => + WinShell.fileHandler.register(() => + updateContextMenus(() => app.quit()) + ) + ) + ) + return true + case '--squirrel-updated': + updateShortcuts(() => + addCommandsToPath(() => + WinShell.fileHandler.update(() => + updateContextMenus(() => app.quit()) + ) + ) + ) + return true + case '--squirrel-uninstall': + removeShortcuts(() => + removeCommandsFromPath(() => + WinShell.fileHandler.deregister(() => + WinShell.fileContextMenu.deregister(() => + WinShell.folderContextMenu.deregister(() => + WinShell.folderBackgroundContextMenu.deregister(() => app.quit()) + ) + ) + ) + ) + ) + return true + case '--squirrel-obsolete': + app.quit() + return true + default: + return false + } +} diff --git a/src/main-process/start.js b/src/main-process/start.js index 23b4df594..7fddf37ec 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -5,8 +5,11 @@ const temp = require('temp').track() const parseCommandLine = require('./parse-command-line') const startCrashReporter = require('../crash-reporter-start') const atomPaths = require('../atom-paths') +const fs = require('fs') +const CSON = require('season') +const Config = require('../config') -module.exports = function start (resourcePath, startTime) { +module.exports = function start (resourcePath, devResourcePath, startTime) { global.shellStartTime = startTime process.on('uncaughtException', function (error = {}) { @@ -35,9 +38,17 @@ module.exports = function start (resourcePath, startTime) { app.commandLine.appendSwitch('enable-experimental-web-platform-features') const args = parseCommandLine(process.argv.slice(1)) + args.resourcePath = normalizeDriveLetterName(resourcePath) + args.devResourcePath = normalizeDriveLetterName(devResourcePath) + atomPaths.setAtomHome(app.getPath('home')) atomPaths.setUserData(app) - setupCompileCache() + + const config = getConfig() + const colorProfile = config.get('core.colorProfile') + if (colorProfile && colorProfile !== 'default') { + app.commandLine.appendSwitch('force-color-profile', colorProfile) + } if (handleStartupEventWithSquirrel()) { return @@ -92,8 +103,28 @@ function handleStartupEventWithSquirrel () { return SquirrelUpdate.handleStartupEvent(app, squirrelCommand) } -function setupCompileCache () { - const CompileCache = require('../compile-cache') - CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) - CompileCache.install(process.resourcesPath, require) +function getConfig () { + const config = new Config() + + let configFilePath + if (fs.existsSync(path.join(process.env.ATOM_HOME, 'config.json'))) { + configFilePath = path.join(process.env.ATOM_HOME, 'config.json') + } else if (fs.existsSync(path.join(process.env.ATOM_HOME, 'config.cson'))) { + configFilePath = path.join(process.env.ATOM_HOME, 'config.cson') + } + + if (configFilePath) { + const configFileData = CSON.readFileSync(configFilePath) + config.resetUserSettings(configFileData) + } + + return config +} + +function normalizeDriveLetterName (filePath) { + if (process.platform === 'win32' && filePath) { + return filePath.replace(/^([a-z]):/, ([driveLetter]) => driveLetter.toUpperCase() + ':') + } else { + return filePath + } } diff --git a/src/main-process/win-powershell.js b/src/main-process/win-powershell.js new file mode 100644 index 000000000..f8e404d07 --- /dev/null +++ b/src/main-process/win-powershell.js @@ -0,0 +1,44 @@ +let powershellPath +const path = require('path') +const Spawner = require('./spawner') + +if (process.env.SystemRoot) { + const system32Path = path.join(process.env.SystemRoot, 'System32') + powershellPath = path.join(system32Path, 'WindowsPowerShell', 'v1.0', 'powershell.exe') +} else { + powershellPath = 'powershell.exe' +} + +// Spawn powershell.exe and callback when it completes +const spawnPowershell = function (args, callback) { + // Set encoding and execute the command, capture the output, and return it + // via .NET's console in order to have consistent UTF-8 encoding. + // See http://stackoverflow.com/questions/22349139/utf-8-output-from-powershell + // to address https://github.com/atom/atom/issues/5063 + args[0] = `\ +[Console]::OutputEncoding=[System.Text.Encoding]::UTF8 +$output=${args[0]} +[Console]::WriteLine($output)\ +` + args.unshift('-command') + args.unshift('RemoteSigned') + args.unshift('-ExecutionPolicy') + args.unshift('-noprofile') + Spawner.spawn(powershellPath, args, callback) +} + +// Get the user's PATH environment variable registry value. +// +// * `callback` The {Function} to call after registry operation is done. +// It will be invoked with the same arguments provided by {Spawner.spawn}. +// +// Returns the user's path {String}. +exports.getPath = callback => + spawnPowershell(['[environment]::GetEnvironmentVariable(\'Path\',\'User\')'], function (error, stdout) { + if (error != null) { + return callback(error) + } + + const pathOutput = stdout.replace(/^\s+|\s+$/g, '') + return callback(null, pathOutput) + }) diff --git a/src/menu-manager.coffee b/src/menu-manager.coffee index dbdcb2f0d..a3d35a1de 100644 --- a/src/menu-manager.coffee +++ b/src/menu-manager.coffee @@ -149,9 +149,9 @@ class MenuManager update: -> return unless @initialized - clearImmediate(@pendingUpdateOperation) if @pendingUpdateOperation? + clearTimeout(@pendingUpdateOperation) if @pendingUpdateOperation? - @pendingUpdateOperation = setImmediate => + @pendingUpdateOperation = setTimeout(=> unsetKeystrokes = new Set for binding in @keymapManager.getKeyBindings() if binding.command is 'unset!' @@ -168,6 +168,7 @@ class MenuManager keystrokesByCommand[binding.command].unshift binding.keystrokes @sendToBrowserProcess(@template, keystrokesByCommand) + , 1) loadPlatformItems: -> if platformMenu? diff --git a/src/module-cache.coffee b/src/module-cache.coffee deleted file mode 100644 index 5bc162ab1..000000000 --- a/src/module-cache.coffee +++ /dev/null @@ -1,285 +0,0 @@ -Module = require 'module' -path = require 'path' -semver = require 'semver' - -# Extend semver.Range to memoize matched versions for speed -class Range extends semver.Range - constructor: -> - super - @matchedVersions = new Set() - @unmatchedVersions = new Set() - - test: (version) -> - return true if @matchedVersions.has(version) - return false if @unmatchedVersions.has(version) - - matches = super - if matches - @matchedVersions.add(version) - else - @unmatchedVersions.add(version) - matches - -nativeModules = null - -cache = - builtins: {} - debug: false - dependencies: {} - extensions: {} - folders: {} - ranges: {} - registered: false - resourcePath: null - resourcePathWithTrailingSlash: null - -# isAbsolute is inlined from fs-plus so that fs-plus itself can be required -# from this cache. -if process.platform is 'win32' - isAbsolute = (pathToCheck) -> - pathToCheck and (pathToCheck[1] is ':' or (pathToCheck[0] is '\\' and pathToCheck[1] is '\\')) -else - isAbsolute = (pathToCheck) -> - pathToCheck and pathToCheck[0] is '/' - -isCorePath = (pathToCheck) -> - pathToCheck.startsWith(cache.resourcePathWithTrailingSlash) - -loadDependencies = (modulePath, rootPath, rootMetadata, moduleCache) -> - fs = require 'fs-plus' - - for childPath in fs.listSync(path.join(modulePath, 'node_modules')) - continue if path.basename(childPath) is '.bin' - continue if rootPath is modulePath and rootMetadata.packageDependencies?.hasOwnProperty(path.basename(childPath)) - - childMetadataPath = path.join(childPath, 'package.json') - continue unless fs.isFileSync(childMetadataPath) - - childMetadata = JSON.parse(fs.readFileSync(childMetadataPath)) - if childMetadata?.version - try - mainPath = require.resolve(childPath) - catch error - mainPath = null - - if mainPath - moduleCache.dependencies.push - name: childMetadata.name - version: childMetadata.version - path: path.relative(rootPath, mainPath) - - loadDependencies(childPath, rootPath, rootMetadata, moduleCache) - - return - -loadFolderCompatibility = (modulePath, rootPath, rootMetadata, moduleCache) -> - fs = require 'fs-plus' - - metadataPath = path.join(modulePath, 'package.json') - return unless fs.isFileSync(metadataPath) - - dependencies = JSON.parse(fs.readFileSync(metadataPath))?.dependencies ? {} - - for name, version of dependencies - try - new Range(version) - catch error - delete dependencies[name] - - onDirectory = (childPath) -> - path.basename(childPath) isnt 'node_modules' - - extensions = ['.js', '.coffee', '.json', '.node'] - paths = {} - onFile = (childPath) -> - if path.extname(childPath) in extensions - relativePath = path.relative(rootPath, path.dirname(childPath)) - paths[relativePath] = true - fs.traverseTreeSync(modulePath, onFile, onDirectory) - - paths = Object.keys(paths) - if paths.length > 0 and Object.keys(dependencies).length > 0 - moduleCache.folders.push({paths, dependencies}) - - for childPath in fs.listSync(path.join(modulePath, 'node_modules')) - continue if path.basename(childPath) is '.bin' - continue if rootPath is modulePath and rootMetadata.packageDependencies?.hasOwnProperty(path.basename(childPath)) - - loadFolderCompatibility(childPath, rootPath, rootMetadata, moduleCache) - - return - -loadExtensions = (modulePath, rootPath, rootMetadata, moduleCache) -> - fs = require 'fs-plus' - extensions = ['.js', '.coffee', '.json', '.node'] - nodeModulesPath = path.join(rootPath, 'node_modules') - - onFile = (filePath) -> - filePath = path.relative(rootPath, filePath) - segments = filePath.split(path.sep) - return if 'test' in segments - return if 'tests' in segments - return if 'spec' in segments - return if 'specs' in segments - return if segments.length > 1 and not (segments[0] in ['exports', 'lib', 'node_modules', 'src', 'static', 'vendor']) - - extension = path.extname(filePath) - if extension in extensions - moduleCache.extensions[extension] ?= [] - moduleCache.extensions[extension].push(filePath) - - onDirectory = (childPath) -> - # Don't include extensions from bundled packages - # These are generated and stored in the package's own metadata cache - if rootMetadata.name is 'atom' - parentPath = path.dirname(childPath) - if parentPath is nodeModulesPath - packageName = path.basename(childPath) - return false if rootMetadata.packageDependencies?.hasOwnProperty(packageName) - - true - - fs.traverseTreeSync(rootPath, onFile, onDirectory) - - return - -satisfies = (version, rawRange) -> - unless parsedRange = cache.ranges[rawRange] - parsedRange = new Range(rawRange) - cache.ranges[rawRange] = parsedRange - parsedRange.test(version) - -resolveFilePath = (relativePath, parentModule) -> - return unless relativePath - return unless parentModule?.filename - return unless relativePath[0] is '.' or isAbsolute(relativePath) - - resolvedPath = path.resolve(path.dirname(parentModule.filename), relativePath) - return unless isCorePath(resolvedPath) - - extension = path.extname(resolvedPath) - if extension - return resolvedPath if cache.extensions[extension]?.has(resolvedPath) - else - for extension, paths of cache.extensions - resolvedPathWithExtension = "#{resolvedPath}#{extension}" - return resolvedPathWithExtension if paths.has(resolvedPathWithExtension) - - return - -resolveModulePath = (relativePath, parentModule) -> - return unless relativePath - return unless parentModule?.filename - - nativeModules ?= process.binding('natives') - return if nativeModules.hasOwnProperty(relativePath) - return if relativePath[0] is '.' - return if isAbsolute(relativePath) - - folderPath = path.dirname(parentModule.filename) - - range = cache.folders[folderPath]?[relativePath] - unless range? - if builtinPath = cache.builtins[relativePath] - return builtinPath - else - return - - candidates = cache.dependencies[relativePath] - return unless candidates? - - for version, resolvedPath of candidates - if Module._cache.hasOwnProperty(resolvedPath) or isCorePath(resolvedPath) - return resolvedPath if satisfies(version, range) - - return - -registerBuiltins = (devMode) -> - if devMode or not cache.resourcePath.startsWith("#{process.resourcesPath}#{path.sep}") - fs = require 'fs-plus' - atomJsPath = path.join(cache.resourcePath, 'exports', 'atom.js') - cache.builtins.atom = atomJsPath if fs.isFileSync(atomJsPath) - cache.builtins.atom ?= path.join(cache.resourcePath, 'exports', 'atom.js') - - electronAsarRoot = path.join(process.resourcesPath, 'electron.asar') - - commonRoot = path.join(electronAsarRoot, 'common', 'api') - commonBuiltins = ['callbacks-registry', 'clipboard', 'crash-reporter', 'shell'] - for builtin in commonBuiltins - cache.builtins[builtin] = path.join(commonRoot, "#{builtin}.js") - - rendererRoot = path.join(electronAsarRoot, 'renderer', 'api') - rendererBuiltins = ['ipc-renderer', 'remote', 'screen'] - for builtin in rendererBuiltins - cache.builtins[builtin] = path.join(rendererRoot, "#{builtin}.js") - -exports.create = (modulePath) -> - fs = require 'fs-plus' - - modulePath = fs.realpathSync(modulePath) - metadataPath = path.join(modulePath, 'package.json') - metadata = JSON.parse(fs.readFileSync(metadataPath)) - - moduleCache = - version: 1 - dependencies: [] - extensions: {} - folders: [] - - loadDependencies(modulePath, modulePath, metadata, moduleCache) - loadFolderCompatibility(modulePath, modulePath, metadata, moduleCache) - loadExtensions(modulePath, modulePath, metadata, moduleCache) - - metadata._atomModuleCache = moduleCache - fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2)) - - return - -exports.register = ({resourcePath, devMode}={}) -> - return if cache.registered - - originalResolveFilename = Module._resolveFilename - Module._resolveFilename = (relativePath, parentModule) -> - resolvedPath = resolveModulePath(relativePath, parentModule) - resolvedPath ?= resolveFilePath(relativePath, parentModule) - resolvedPath ? originalResolveFilename(relativePath, parentModule) - - cache.registered = true - cache.resourcePath = resourcePath - cache.resourcePathWithTrailingSlash = "#{resourcePath}#{path.sep}" - registerBuiltins(devMode) - - return - -exports.add = (directoryPath, metadata) -> - # path.join isn't used in this function for speed since path.join calls - # path.normalize and all the paths are already normalized here. - - unless metadata? - try - metadata = require("#{directoryPath}#{path.sep}package.json") - catch error - return - - cacheToAdd = metadata?._atomModuleCache - return unless cacheToAdd? - - for dependency in cacheToAdd.dependencies ? [] - cache.dependencies[dependency.name] ?= {} - cache.dependencies[dependency.name][dependency.version] ?= "#{directoryPath}#{path.sep}#{dependency.path}" - - for entry in cacheToAdd.folders ? [] - for folderPath in entry.paths - if folderPath - cache.folders["#{directoryPath}#{path.sep}#{folderPath}"] = entry.dependencies - else - cache.folders[directoryPath] = entry.dependencies - - for extension, paths of cacheToAdd.extensions - cache.extensions[extension] ?= new Set() - for filePath in paths - cache.extensions[extension].add("#{directoryPath}#{path.sep}#{filePath}") - - return - -exports.cache = cache diff --git a/src/module-cache.js b/src/module-cache.js new file mode 100644 index 000000000..f83e54a28 --- /dev/null +++ b/src/module-cache.js @@ -0,0 +1,339 @@ +const Module = require('module') +const path = require('path') +const semver = require('semver') + +// Extend semver.Range to memoize matched versions for speed +class Range extends semver.Range { + constructor () { + super(...arguments) + this.matchedVersions = new Set() + this.unmatchedVersions = new Set() + } + + test (version) { + if (this.matchedVersions.has(version)) return true + if (this.unmatchedVersions.has(version)) return false + + const matches = super.test(...arguments) + if (matches) { + this.matchedVersions.add(version) + } else { + this.unmatchedVersions.add(version) + } + return matches + } +} + +let nativeModules = null + +const cache = { + builtins: {}, + debug: false, + dependencies: {}, + extensions: {}, + folders: {}, + ranges: {}, + registered: false, + resourcePath: null, + resourcePathWithTrailingSlash: null +} + +// isAbsolute is inlined from fs-plus so that fs-plus itself can be required +// from this cache. +let isAbsolute +if (process.platform === 'win32') { + isAbsolute = pathToCheck => pathToCheck && ((pathToCheck[1] === ':') || ((pathToCheck[0] === '\\') && (pathToCheck[1] === '\\'))) +} else { + isAbsolute = pathToCheck => pathToCheck && (pathToCheck[0] === '/') +} + +const isCorePath = pathToCheck => pathToCheck.startsWith(cache.resourcePathWithTrailingSlash) + +function loadDependencies (modulePath, rootPath, rootMetadata, moduleCache) { + const fs = require('fs-plus') + + for (let childPath of fs.listSync(path.join(modulePath, 'node_modules'))) { + if (path.basename(childPath) === '.bin') continue + if (rootPath === modulePath && (rootMetadata.packageDependencies && rootMetadata.packageDependencies.hasOwnProperty(path.basename(childPath)))) { + continue + } + + const childMetadataPath = path.join(childPath, 'package.json') + if (!fs.isFileSync(childMetadataPath)) continue + + const childMetadata = JSON.parse(fs.readFileSync(childMetadataPath)) + if (childMetadata && childMetadata.version) { + var mainPath + try { + mainPath = require.resolve(childPath) + } catch (error) { + mainPath = null + } + + if (mainPath) { + moduleCache.dependencies.push({ + name: childMetadata.name, + version: childMetadata.version, + path: path.relative(rootPath, mainPath) + }) + } + + loadDependencies(childPath, rootPath, rootMetadata, moduleCache) + } + } +} + +function loadFolderCompatibility (modulePath, rootPath, rootMetadata, moduleCache) { + const fs = require('fs-plus') + + const metadataPath = path.join(modulePath, 'package.json') + if (!fs.isFileSync(metadataPath)) return + + const metadata = JSON.parse(fs.readFileSync(metadataPath)) + const dependencies = metadata.dependencies || {} + + for (let name in dependencies) { + if (!semver.validRange(dependencies[name])) { + delete dependencies[name] + } + } + + const onDirectory = childPath => path.basename(childPath) !== 'node_modules' + + const extensions = ['.js', '.coffee', '.json', '.node'] + let paths = {} + function onFile (childPath) { + const needle = path.extname(childPath) + if (extensions.includes(needle)) { + const relativePath = path.relative(rootPath, path.dirname(childPath)) + paths[relativePath] = true + } + } + fs.traverseTreeSync(modulePath, onFile, onDirectory) + + paths = Object.keys(paths) + if (paths.length > 0 && Object.keys(dependencies).length > 0) { + moduleCache.folders.push({paths, dependencies}) + } + + for (let childPath of fs.listSync(path.join(modulePath, 'node_modules'))) { + if (path.basename(childPath) === '.bin') continue + if (rootPath === modulePath && (rootMetadata.packageDependencies && rootMetadata.packageDependencies.hasOwnProperty(path.basename(childPath)))) { + continue + } + loadFolderCompatibility(childPath, rootPath, rootMetadata, moduleCache) + } +} + +function loadExtensions (modulePath, rootPath, rootMetadata, moduleCache) { + const fs = require('fs-plus') + const extensions = ['.js', '.coffee', '.json', '.node'] + const nodeModulesPath = path.join(rootPath, 'node_modules') + + function onFile (filePath) { + filePath = path.relative(rootPath, filePath) + const segments = filePath.split(path.sep) + if (segments.includes('test')) return + if (segments.includes('tests')) return + if (segments.includes('spec')) return + if (segments.includes('specs')) return + if (segments.length > 1 && !['exports', 'lib', 'node_modules', 'src', 'static', 'vendor'].includes(segments[0])) return + + const extension = path.extname(filePath) + if (extensions.includes(extension)) { + if (moduleCache.extensions[extension] == null) { moduleCache.extensions[extension] = [] } + moduleCache.extensions[extension].push(filePath) + } + } + + function onDirectory (childPath) { + // Don't include extensions from bundled packages + // These are generated and stored in the package's own metadata cache + if (rootMetadata.name === 'atom') { + const parentPath = path.dirname(childPath) + if (parentPath === nodeModulesPath) { + const packageName = path.basename(childPath) + if (rootMetadata.packageDependencies && rootMetadata.packageDependencies.hasOwnProperty(packageName)) return false + } + } + + return true + } + + fs.traverseTreeSync(rootPath, onFile, onDirectory) +} + +function satisfies (version, rawRange) { + let parsedRange + if (!(parsedRange = cache.ranges[rawRange])) { + parsedRange = new Range(rawRange) + cache.ranges[rawRange] = parsedRange + } + return parsedRange.test(version) +} + +function resolveFilePath (relativePath, parentModule) { + if (!relativePath) return + if (!(parentModule && parentModule.filename)) return + if (relativePath[0] !== '.' && !isAbsolute(relativePath)) return + + const resolvedPath = path.resolve(path.dirname(parentModule.filename), relativePath) + if (!isCorePath(resolvedPath)) return + + let extension = path.extname(resolvedPath) + if (extension) { + if (cache.extensions[extension] && cache.extensions[extension].has(resolvedPath)) return resolvedPath + } else { + for (extension in cache.extensions) { + const paths = cache.extensions[extension] + const resolvedPathWithExtension = `${resolvedPath}${extension}` + if (paths.has(resolvedPathWithExtension)) { + return resolvedPathWithExtension + } + } + } +} + +function resolveModulePath (relativePath, parentModule) { + if (!relativePath) return + if (!(parentModule && parentModule.filename)) return + + if (!nativeModules) nativeModules = process.binding('natives') + if (nativeModules.hasOwnProperty(relativePath)) return + if (relativePath[0] === '.') return + if (isAbsolute(relativePath)) return + + const folderPath = path.dirname(parentModule.filename) + + const range = cache.folders[folderPath] && cache.folders[folderPath][relativePath] + if (!range) { + const builtinPath = cache.builtins[relativePath] + if (builtinPath) { + return builtinPath + } else { + return + } + } + + const candidates = cache.dependencies[relativePath] + if (candidates == null) return + + for (let version in candidates) { + const resolvedPath = candidates[version] + if (Module._cache[resolvedPath] || isCorePath(resolvedPath)) { + if (satisfies(version, range)) return resolvedPath + } + } +} + +function registerBuiltins (devMode) { + if (devMode || !cache.resourcePath.startsWith(`${process.resourcesPath}${path.sep}`)) { + const fs = require('fs-plus') + const atomJsPath = path.join(cache.resourcePath, 'exports', 'atom.js') + if (fs.isFileSync(atomJsPath)) { cache.builtins.atom = atomJsPath } + } + if (cache.builtins.atom == null) { cache.builtins.atom = path.join(cache.resourcePath, 'exports', 'atom.js') } + + const electronAsarRoot = path.join(process.resourcesPath, 'electron.asar') + + const commonRoot = path.join(electronAsarRoot, 'common', 'api') + const commonBuiltins = ['callbacks-registry', 'clipboard', 'crash-reporter', 'shell'] + for (const builtin of commonBuiltins) { + cache.builtins[builtin] = path.join(commonRoot, `${builtin}.js`) + } + + const rendererRoot = path.join(electronAsarRoot, 'renderer', 'api') + const rendererBuiltins = ['ipc-renderer', 'remote', 'screen'] + for (const builtin of rendererBuiltins) { + cache.builtins[builtin] = path.join(rendererRoot, `${builtin}.js`) + } +} + +exports.create = function (modulePath) { + const fs = require('fs-plus') + + modulePath = fs.realpathSync(modulePath) + const metadataPath = path.join(modulePath, 'package.json') + const metadata = JSON.parse(fs.readFileSync(metadataPath)) + + const moduleCache = { + version: 1, + dependencies: [], + extensions: {}, + folders: [] + } + + loadDependencies(modulePath, modulePath, metadata, moduleCache) + loadFolderCompatibility(modulePath, modulePath, metadata, moduleCache) + loadExtensions(modulePath, modulePath, metadata, moduleCache) + + metadata._atomModuleCache = moduleCache + fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2)) +} + +exports.register = function ({resourcePath, devMode} = {}) { + if (cache.registered) return + + const originalResolveFilename = Module._resolveFilename + Module._resolveFilename = function (relativePath, parentModule) { + let resolvedPath = resolveModulePath(relativePath, parentModule) + if (!resolvedPath) { + resolvedPath = resolveFilePath(relativePath, parentModule) + } + return resolvedPath || originalResolveFilename(relativePath, parentModule) + } + + cache.registered = true + cache.resourcePath = resourcePath + cache.resourcePathWithTrailingSlash = `${resourcePath}${path.sep}` + registerBuiltins(devMode) +} + +exports.add = function (directoryPath, metadata) { + // path.join isn't used in this function for speed since path.join calls + // path.normalize and all the paths are already normalized here. + + if (metadata == null) { + try { + metadata = require(`${directoryPath}${path.sep}package.json`) + } catch (error) { + return + } + } + + const cacheToAdd = metadata && metadata._atomModuleCache + if (!cacheToAdd) return + + for (const dependency of cacheToAdd.dependencies || []) { + if (!cache.dependencies[dependency.name]) { + cache.dependencies[dependency.name] = {} + } + if (!cache.dependencies[dependency.name][dependency.version]) { + cache.dependencies[dependency.name][dependency.version] = `${directoryPath}${path.sep}${dependency.path}` + } + } + + for (const entry of cacheToAdd.folders || []) { + for (const folderPath of entry.paths) { + if (folderPath) { + cache.folders[`${directoryPath}${path.sep}${folderPath}`] = entry.dependencies + } else { + cache.folders[directoryPath] = entry.dependencies + } + } + } + + for (const extension in cacheToAdd.extensions) { + const paths = cacheToAdd.extensions[extension] + if (!cache.extensions[extension]) { + cache.extensions[extension] = new Set() + } + for (let filePath of paths) { + cache.extensions[extension].add(`${directoryPath}${path.sep}${filePath}`) + } + } +} + +exports.cache = cache + +exports.Range = Range diff --git a/src/package-manager.js b/src/package-manager.js index 17a5f2214..8171ce19f 100644 --- a/src/package-manager.js +++ b/src/package-manager.js @@ -9,7 +9,7 @@ const CSON = require('season') const ServiceHub = require('service-hub') const Package = require('./package') const ThemePackage = require('./theme-package') -const {isDeprecatedPackage, getDeprecatedPackageMetadata} = require('./deprecated-packages') +const ModuleCache = require('./module-cache') const packageJSON = require('../package.json') // Extended: Package manager for coordinating the lifecycle of Atom packages. @@ -42,6 +42,8 @@ module.exports = class PackageManager { this.triggeredActivationHooks = new Set() this.packagesCache = packageJSON._atomPackages != null ? packageJSON._atomPackages : {} this.packageDependencies = packageJSON.packageDependencies != null ? packageJSON.packageDependencies : {} + this.deprecatedPackages = packageJSON._deprecatedPackages || {} + this.deprecatedPackageRanges = {} this.initialPackagesLoaded = false this.initialPackagesActivated = false this.preloadedPackages = {} @@ -61,6 +63,7 @@ module.exports = class PackageManager { if (params.configDirPath != null && !params.safeMode) { if (this.devMode) { this.packageDirPaths.push(path.join(params.configDirPath, 'dev', 'packages')) + this.packageDirPaths.push(path.join(this.resourcePath, 'packages')) } this.packageDirPaths.push(path.join(params.configDirPath, 'packages')) } @@ -219,11 +222,26 @@ module.exports = class PackageManager { } isDeprecatedPackage (name, version) { - return isDeprecatedPackage(name, version) + const metadata = this.deprecatedPackages[name] + if (!metadata) return false + if (!metadata.version) return true + + let range = this.deprecatedPackageRanges[metadata.version] + if (!range) { + try { + range = new ModuleCache.Range(metadata.version) + } catch (error) { + range = NullVersionRange + } + this.deprecatedPackageRanges[metadata.version] = range + } + return range.test(version) } getDeprecatedPackageMetadata (name) { - return getDeprecatedPackageMetadata(name) + const metadata = this.deprecatedPackages[name] + if (metadata) Object.freeze(metadata) + return metadata } /* @@ -870,3 +888,7 @@ module.exports = class PackageManager { } } } + +const NullVersionRange = { + test () { return false } +} diff --git a/src/package.js b/src/package.js index bbcb0061f..56764a86a 100644 --- a/src/package.js +++ b/src/package.js @@ -7,7 +7,6 @@ const dedent = require('dedent') const CompileCache = require('./compile-cache') const ModuleCache = require('./module-cache') -const ScopedProperties = require('./scoped-properties') const BufferedProcess = require('./buffered-process') // Extended: Loads and activates a package's main module and resources such as @@ -103,7 +102,7 @@ class Package { this.activateKeymaps() this.activateMenus() for (let settings of this.settings) { - settings.activate() + settings.activate(this.config) } this.settingsActivated = true } @@ -318,7 +317,7 @@ class Package { if (!this.settingsActivated) { for (let settings of this.settings) { - settings.activate() + settings.activate(this.config) } this.settingsActivated = true } @@ -636,14 +635,14 @@ class Package { this.settings = [] const loadSettingsFile = (settingsPath, callback) => { - return ScopedProperties.load(settingsPath, this.config, (error, settings) => { + return SettingsFile.load(settingsPath, (error, settingsFile) => { if (error) { const detail = `${error.message} in ${settingsPath}` const stack = `${error.stack}\n at ${settingsPath}:1:1` this.notificationManager.addFatalError(`Failed to load the ${this.name} package settings`, {stack, detail, packageName: this.name, dismissable: true}) } else { - this.settings.push(settings) - if (this.settingsActivated) { settings.activate() } + this.settings.push(settingsFile) + if (this.settingsActivated) settingsFile.activate(this.config) } return callback() }) @@ -652,10 +651,10 @@ class Package { return new Promise(resolve => { if (this.preloadedPackage && this.packageManager.packagesCache[this.name]) { for (let settingsPath in this.packageManager.packagesCache[this.name].settings) { - const scopedProperties = this.packageManager.packagesCache[this.name].settings[settingsPath] - const settings = new ScopedProperties(`core:${settingsPath}`, scopedProperties || {}, this.config) - this.settings.push(settings) - if (this.settingsActivated) { settings.activate() } + const properties = this.packageManager.packagesCache[this.name].settings[settingsPath] + const settingsFile = new SettingsFile(`core:${settingsPath}`, properties || {}) + this.settings.push(settingsFile) + if (this.settingsActivated) settingsFile.activate(this.config) } return resolve() } else { @@ -727,7 +726,7 @@ class Package { grammar.deactivate() } for (let settings of this.settings) { - settings.deactivate() + settings.deactivate(this.config) } if (this.stylesheetDisposables) this.stylesheetDisposables.dispose() @@ -1105,3 +1104,32 @@ class Package { }) } } + +class SettingsFile { + static load (path, callback) { + CSON.readFile(path, (error, properties = {}) => { + if (error) { + callback(error) + } else { + callback(null, new SettingsFile(path, properties)) + } + }) + } + + constructor (path, properties) { + this.path = path + this.properties = properties + } + + activate (config) { + for (let selector in this.properties) { + config.set(null, this.properties[selector], {scopeSelector: selector, source: this.path}) + } + } + + deactivate (config) { + for (let selector in this.properties) { + config.unset(null, {scopeSelector: selector, source: this.path}) + } + } +} diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee deleted file mode 100644 index c8fcc4108..000000000 --- a/src/pane-axis.coffee +++ /dev/null @@ -1,147 +0,0 @@ -{Emitter, CompositeDisposable} = require 'event-kit' -{flatten} = require 'underscore-plus' -Model = require './model' -PaneAxisElement = require './pane-axis-element' - -module.exports = -class PaneAxis extends Model - parent: null - container: null - orientation: null - - @deserialize: (state, {deserializers, views}) -> - state.children = state.children.map (childState) -> - deserializers.deserialize(childState) - new this(state, views) - - constructor: ({@orientation, children, flexScale}, @viewRegistry) -> - @emitter = new Emitter - @subscriptionsByChild = new WeakMap - @subscriptions = new CompositeDisposable - @children = [] - if children? - @addChild(child) for child in children - @flexScale = flexScale ? 1 - - serialize: -> - deserializer: 'PaneAxis' - children: @children.map (child) -> child.serialize() - orientation: @orientation - flexScale: @flexScale - - getElement: -> - @element ?= new PaneAxisElement().initialize(this, @viewRegistry) - - getFlexScale: -> @flexScale - - setFlexScale: (@flexScale) -> - @emitter.emit 'did-change-flex-scale', @flexScale - @flexScale - - getParent: -> @parent - - setParent: (@parent) -> @parent - - getContainer: -> @container - - setContainer: (container) -> - if container and container isnt @container - @container = container - child.setContainer(container) for child in @children - - getOrientation: -> @orientation - - getChildren: -> @children.slice() - - getPanes: -> - flatten(@children.map (child) -> child.getPanes()) - - getItems: -> - flatten(@children.map (child) -> child.getItems()) - - onDidAddChild: (fn) -> - @emitter.on 'did-add-child', fn - - onDidRemoveChild: (fn) -> - @emitter.on 'did-remove-child', fn - - onDidReplaceChild: (fn) -> - @emitter.on 'did-replace-child', fn - - onDidDestroy: (fn) -> - @emitter.once 'did-destroy', fn - - onDidChangeFlexScale: (fn) -> - @emitter.on 'did-change-flex-scale', fn - - observeFlexScale: (fn) -> - fn(@flexScale) - @onDidChangeFlexScale(fn) - - addChild: (child, index=@children.length) -> - @children.splice(index, 0, child) - child.setParent(this) - child.setContainer(@container) - @subscribeToChild(child) - @emitter.emit 'did-add-child', {child, index} - - adjustFlexScale: -> - # get current total flex scale of children - total = 0 - total += child.getFlexScale() for child in @children - - needTotal = @children.length - # set every child's flex scale by the ratio - for child in @children - child.setFlexScale(needTotal * child.getFlexScale() / total) - - removeChild: (child, replacing=false) -> - index = @children.indexOf(child) - throw new Error("Removing non-existent child") if index is -1 - - @unsubscribeFromChild(child) - - @children.splice(index, 1) - @adjustFlexScale() - @emitter.emit 'did-remove-child', {child, index} - @reparentLastChild() if not replacing and @children.length < 2 - - replaceChild: (oldChild, newChild) -> - @unsubscribeFromChild(oldChild) - @subscribeToChild(newChild) - - newChild.setParent(this) - newChild.setContainer(@container) - - index = @children.indexOf(oldChild) - @children.splice(index, 1, newChild) - @emitter.emit 'did-replace-child', {oldChild, newChild, index} - - insertChildBefore: (currentChild, newChild) -> - index = @children.indexOf(currentChild) - @addChild(newChild, index) - - insertChildAfter: (currentChild, newChild) -> - index = @children.indexOf(currentChild) - @addChild(newChild, index + 1) - - reparentLastChild: -> - lastChild = @children[0] - lastChild.setFlexScale(@flexScale) - @parent.replaceChild(this, lastChild) - @destroy() - - subscribeToChild: (child) -> - subscription = child.onDidDestroy => @removeChild(child) - @subscriptionsByChild.set(child, subscription) - @subscriptions.add(subscription) - - unsubscribeFromChild: (child) -> - subscription = @subscriptionsByChild.get(child) - @subscriptions.remove(subscription) - subscription.dispose() - - destroyed: -> - @subscriptions.dispose() - @emitter.emit 'did-destroy' - @emitter.dispose() diff --git a/src/pane-axis.js b/src/pane-axis.js new file mode 100644 index 000000000..23c87f928 --- /dev/null +++ b/src/pane-axis.js @@ -0,0 +1,199 @@ +const {Emitter, CompositeDisposable} = require('event-kit') +const {flatten} = require('underscore-plus') +const Model = require('./model') +const PaneAxisElement = require('./pane-axis-element') + +class PaneAxis extends Model { + static deserialize (state, {deserializers, views}) { + state.children = state.children.map(childState => deserializers.deserialize(childState)) + return new PaneAxis(state, views) + } + + constructor ({orientation, children, flexScale}, viewRegistry) { + super() + this.parent = null + this.container = null + this.orientation = orientation + this.viewRegistry = viewRegistry + this.emitter = new Emitter() + this.subscriptionsByChild = new WeakMap() + this.subscriptions = new CompositeDisposable() + this.flexScale = flexScale != null ? flexScale : 1 + this.children = [] + if (children) { + for (let child of children) { + this.addChild(child) + } + } + } + + serialize () { + return { + deserializer: 'PaneAxis', + children: this.children.map(child => child.serialize()), + orientation: this.orientation, + flexScale: this.flexScale + } + } + + getElement () { + if (!this.element) { + this.element = new PaneAxisElement().initialize(this, this.viewRegistry) + } + return this.element + } + + getFlexScale () { + return this.flexScale + } + + setFlexScale (flexScale) { + this.flexScale = flexScale + this.emitter.emit('did-change-flex-scale', this.flexScale) + return this.flexScale + } + + getParent () { + return this.parent + } + + setParent (parent) { + this.parent = parent + return this.parent + } + + getContainer () { + return this.container + } + + setContainer (container) { + if (container && (container !== this.container)) { + this.container = container + this.children.forEach(child => child.setContainer(container)) + } + } + + getOrientation () { + return this.orientation + } + + getChildren () { + return this.children.slice() + } + + getPanes () { + return flatten(this.children.map(child => child.getPanes())) + } + + getItems () { + return flatten(this.children.map(child => child.getItems())) + } + + onDidAddChild (fn) { + return this.emitter.on('did-add-child', fn) + } + + onDidRemoveChild (fn) { + return this.emitter.on('did-remove-child', fn) + } + + onDidReplaceChild (fn) { + return this.emitter.on('did-replace-child', fn) + } + + onDidDestroy (fn) { + return this.emitter.once('did-destroy', fn) + } + + onDidChangeFlexScale (fn) { + return this.emitter.on('did-change-flex-scale', fn) + } + + observeFlexScale (fn) { + fn(this.flexScale) + return this.onDidChangeFlexScale(fn) + } + + addChild (child, index = this.children.length) { + this.children.splice(index, 0, child) + child.setParent(this) + child.setContainer(this.container) + this.subscribeToChild(child) + return this.emitter.emit('did-add-child', {child, index}) + } + + adjustFlexScale () { + // get current total flex scale of children + let total = 0 + for (var child of this.children) { total += child.getFlexScale() } + + const needTotal = this.children.length + // set every child's flex scale by the ratio + for (child of this.children) { + child.setFlexScale((needTotal * child.getFlexScale()) / total) + } + } + + removeChild (child, replacing = false) { + const index = this.children.indexOf(child) + if (index === -1) { throw new Error('Removing non-existent child') } + + this.unsubscribeFromChild(child) + + this.children.splice(index, 1) + this.adjustFlexScale() + this.emitter.emit('did-remove-child', {child, index}) + if (!replacing && this.children.length < 2) { + this.reparentLastChild() + } + } + + replaceChild (oldChild, newChild) { + this.unsubscribeFromChild(oldChild) + this.subscribeToChild(newChild) + + newChild.setParent(this) + newChild.setContainer(this.container) + + const index = this.children.indexOf(oldChild) + this.children.splice(index, 1, newChild) + this.emitter.emit('did-replace-child', {oldChild, newChild, index}) + } + + insertChildBefore (currentChild, newChild) { + const index = this.children.indexOf(currentChild) + return this.addChild(newChild, index) + } + + insertChildAfter (currentChild, newChild) { + const index = this.children.indexOf(currentChild) + return this.addChild(newChild, index + 1) + } + + reparentLastChild () { + const lastChild = this.children[0] + lastChild.setFlexScale(this.flexScale) + this.parent.replaceChild(this, lastChild) + this.destroy() + } + + subscribeToChild (child) { + const subscription = child.onDidDestroy(() => this.removeChild(child)) + this.subscriptionsByChild.set(child, subscription) + this.subscriptions.add(subscription) + } + + unsubscribeFromChild (child) { + const subscription = this.subscriptionsByChild.get(child) + this.subscriptions.remove(subscription) + subscription.dispose() + } + + destroyed () { + this.subscriptions.dispose() + this.emitter.emit('did-destroy') + this.emitter.dispose() + } +} + +module.exports = PaneAxis diff --git a/src/pane.js b/src/pane.js index 162186572..fca1260c4 100644 --- a/src/pane.js +++ b/src/pane.js @@ -614,15 +614,15 @@ class Pane { if (this.items.includes(item)) return + const itemSubscriptions = new CompositeDisposable() + this.subscriptionsPerItem.set(item, itemSubscriptions) if (typeof item.onDidDestroy === 'function') { - const itemSubscriptions = new CompositeDisposable() itemSubscriptions.add(item.onDidDestroy(() => this.removeItem(item, false))) - if (typeof item.onDidTerminatePendingState === 'function') { - itemSubscriptions.add(item.onDidTerminatePendingState(() => { - if (this.getPendingItem() === item) this.clearPendingItem() - })) - } - this.subscriptionsPerItem.set(item, itemSubscriptions) + } + if (typeof item.onDidTerminatePendingState === 'function') { + itemSubscriptions.add(item.onDidTerminatePendingState(() => { + if (this.getPendingItem() === item) this.clearPendingItem() + })) } this.items.splice(index, 0, item) diff --git a/src/project.js b/src/project.js index 45a26fbb8..8ccf60c0b 100644 --- a/src/project.js +++ b/src/project.js @@ -199,7 +199,7 @@ class Project extends Model { // const disposable = atom.project.onDidChangeFiles(events => { // for (const event of events) { // // "created", "modified", "deleted", or "renamed" - // console.log(`Event action: ${event.type}`) + // console.log(`Event action: ${event.action}`) // // // absolute path to the filesystem entry that was touched // console.log(`Event path: ${event.path}`) @@ -234,6 +234,38 @@ class Project extends Model { return this.emitter.on('did-change-files', callback) } + // Public: Invoke the given callback with all current and future + // repositories in the project. + // + // * `callback` {Function} to be called with current and future + // repositories. + // * `repository` A {GitRepository} that is present at the time of + // subscription or that is added at some later time. + // + // Returns a {Disposable} on which `.dispose()` can be called to + // unsubscribe. + observeRepositories (callback) { + for (const repo of this.repositories) { + if (repo != null) { + callback(repo) + } + } + + return this.onDidAddRepository(callback) + } + + // Public: Invoke the given callback when a repository is added to the + // project. + // + // * `callback` {Function} to be called when a repository is added. + // * `repository` A {GitRepository}. + // + // Returns a {Disposable} on which `.dispose()` can be called to + // unsubscribe. + onDidAddRepository (callback) { + return this.emitter.on('did-add-repository', callback) + } + /* Section: Accessing the git repository */ @@ -400,6 +432,9 @@ class Project extends Model { if (repo) { break } } this.repositories.push(repo != null ? repo : null) + if (repo != null) { + this.emitter.emit('did-add-repository', repo) + } if (options.emitEvent !== false) { this.emitter.emit('did-change-paths', this.getPaths()) @@ -662,27 +697,32 @@ class Project extends Model { // * `text` The {String} text to use as a buffer. // // Returns a {Promise} that resolves to the {TextBuffer}. - buildBuffer (absoluteFilePath) { + async buildBuffer (absoluteFilePath) { const params = {shouldDestroyOnFileDelete: this.shouldDestroyBufferOnFileDelete} - let promise + let buffer if (absoluteFilePath != null) { if (this.loadPromisesByPath[absoluteFilePath] == null) { this.loadPromisesByPath[absoluteFilePath] = - TextBuffer.load(absoluteFilePath, params).catch(error => { - delete this.loadPromisesByPath[absoluteFilePath] - throw error - }) + TextBuffer.load(absoluteFilePath, params) + .then(result => { + delete this.loadPromisesByPath[absoluteFilePath] + return result + }) + .catch(error => { + delete this.loadPromisesByPath[absoluteFilePath] + throw error + }) } - promise = this.loadPromisesByPath[absoluteFilePath] + buffer = await this.loadPromisesByPath[absoluteFilePath] } else { - promise = Promise.resolve(new TextBuffer(params)) + buffer = new TextBuffer(params) } - return promise.then(buffer => { - delete this.loadPromisesByPath[absoluteFilePath] - this.addBuffer(buffer) - return buffer - }) + + this.grammarRegistry.autoAssignLanguageMode(buffer) + + this.addBuffer(buffer) + return buffer } addBuffer (buffer, options = {}) { diff --git a/src/register-default-commands.coffee b/src/register-default-commands.coffee index a367e6188..badae227c 100644 --- a/src/register-default-commands.coffee +++ b/src/register-default-commands.coffee @@ -122,8 +122,6 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage commandRegistry.add( 'atom-text-editor', stopEventPropagation({ - 'core:undo': -> @undo() - 'core:redo': -> @redo() 'core:move-left': -> @moveLeft() 'core:move-right': -> @moveRight() 'core:select-left': -> @selectLeft() @@ -166,15 +164,35 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage false ) + commandRegistry.add( + 'atom-text-editor:not([readonly])', + stopEventPropagation({ + 'core:undo': -> @undo() + 'core:redo': -> @redo() + }), + false + ) + commandRegistry.add( 'atom-text-editor', + stopEventPropagationAndGroupUndo( + config, + { + 'core:copy': -> @copySelectedText() + 'editor:copy-selection': -> @copyOnlySelectedText() + } + ), + false + ) + + commandRegistry.add( + 'atom-text-editor:not([readonly])', stopEventPropagationAndGroupUndo( config, { 'core:backspace': -> @backspace() 'core:delete': -> @delete() 'core:cut': -> @cutSelectedText() - 'core:copy': -> @copySelectedText() 'core:paste': -> @pasteText() 'editor:paste-without-reformatting': -> @pasteText({ normalizeLineEndings: false, @@ -195,7 +213,6 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage 'editor:transpose': -> @transpose() 'editor:upper-case': -> @upperCase() 'editor:lower-case': -> @lowerCase() - 'editor:copy-selection': -> @copyOnlySelectedText() } ), false @@ -266,7 +283,7 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage ) commandRegistry.add( - 'atom-text-editor:not([mini])', + 'atom-text-editor:not([mini]):not([readonly])', stopEventPropagationAndGroupUndo( config, { diff --git a/src/safe-clipboard.coffee b/src/safe-clipboard.coffee deleted file mode 100644 index 1f91803e2..000000000 --- a/src/safe-clipboard.coffee +++ /dev/null @@ -1,6 +0,0 @@ -# Using clipboard in renderer process is not safe on Linux. -module.exports = - if process.platform is 'linux' and process.type is 'renderer' - require('electron').remote.clipboard - else - require('electron').clipboard diff --git a/src/scope-descriptor.coffee b/src/scope-descriptor.coffee deleted file mode 100644 index f1070f277..000000000 --- a/src/scope-descriptor.coffee +++ /dev/null @@ -1,63 +0,0 @@ -# Extended: Wraps an {Array} of `String`s. The Array describes a path from the -# root of the syntax tree to a token including _all_ scope names for the entire -# path. -# -# Methods that take a `ScopeDescriptor` will also accept an {Array} of {String} -# scope names e.g. `['.source.js']`. -# -# You can use `ScopeDescriptor`s to get language-specific config settings via -# {Config::get}. -# -# You should not need to create a `ScopeDescriptor` directly. -# -# * {TextEditor::getRootScopeDescriptor} to get the language's descriptor. -# * {TextEditor::scopeDescriptorForBufferPosition} to get the descriptor at a -# specific position in the buffer. -# * {Cursor::getScopeDescriptor} to get a cursor's descriptor based on position. -# -# See the [scopes and scope descriptor guide](http://flight-manual.atom.io/behind-atom/sections/scoped-settings-scopes-and-scope-descriptors/) -# for more information. -module.exports = -class ScopeDescriptor - @fromObject: (scopes) -> - if scopes instanceof ScopeDescriptor - scopes - else - new ScopeDescriptor({scopes}) - - ### - Section: Construction and Destruction - ### - - # Public: Create a {ScopeDescriptor} object. - # - # * `object` {Object} - # * `scopes` {Array} of {String}s - constructor: ({@scopes}) -> - - # Public: Returns an {Array} of {String}s - getScopesArray: -> @scopes - - getScopeChain: -> - # For backward compatibility, prefix TextMate-style scope names with - # leading dots (e.g. 'source.js' -> '.source.js'). - if @scopes[0]?.includes('.') - result = '' - for scope, i in @scopes - result += ' ' if i > 0 - result += '.' if scope[0] isnt '.' - result += scope - result - else - @scopes.join(' ') - - toString: -> - @getScopeChain() - - isEqual: (other) -> - if @scopes.length isnt other.scopes.length - return false - for scope, i in @scopes - if scope isnt other.scopes[i] - return false - true diff --git a/src/scope-descriptor.js b/src/scope-descriptor.js new file mode 100644 index 000000000..63075e8a1 --- /dev/null +++ b/src/scope-descriptor.js @@ -0,0 +1,80 @@ +// Extended: Wraps an {Array} of `String`s. The Array describes a path from the +// root of the syntax tree to a token including _all_ scope names for the entire +// path. +// +// Methods that take a `ScopeDescriptor` will also accept an {Array} of {String} +// scope names e.g. `['.source.js']`. +// +// You can use `ScopeDescriptor`s to get language-specific config settings via +// {Config::get}. +// +// You should not need to create a `ScopeDescriptor` directly. +// +// * {TextEditor::getRootScopeDescriptor} to get the language's descriptor. +// * {TextEditor::scopeDescriptorForBufferPosition} to get the descriptor at a +// specific position in the buffer. +// * {Cursor::getScopeDescriptor} to get a cursor's descriptor based on position. +// +// See the [scopes and scope descriptor guide](http://flight-manual.atom.io/behind-atom/sections/scoped-settings-scopes-and-scope-descriptors/) +// for more information. +module.exports = +class ScopeDescriptor { + static fromObject (scopes) { + if (scopes instanceof ScopeDescriptor) { + return scopes + } else { + return new ScopeDescriptor({scopes}) + } + } + + /* + Section: Construction and Destruction + */ + + // Public: Create a {ScopeDescriptor} object. + // + // * `object` {Object} + // * `scopes` {Array} of {String}s + constructor ({scopes}) { + this.scopes = scopes + } + + // Public: Returns an {Array} of {String}s + getScopesArray () { + return this.scopes + } + + getScopeChain () { + // For backward compatibility, prefix TextMate-style scope names with + // leading dots (e.g. 'source.js' -> '.source.js'). + if (this.scopes[0] != null && this.scopes[0].includes('.')) { + let result = '' + for (let i = 0; i < this.scopes.length; i++) { + const scope = this.scopes[i] + if (i > 0) { result += ' ' } + if (scope[0] !== '.') { result += '.' } + result += scope + } + return result + } else { + return this.scopes.join(' ') + } + } + + toString () { + return this.getScopeChain() + } + + isEqual (other) { + if (this.scopes.length !== other.scopes.length) { + return false + } + for (let i = 0; i < this.scopes.length; i++) { + const scope = this.scopes[i] + if (scope !== other.scopes[i]) { + return false + } + } + return true + } +} diff --git a/src/scoped-properties.coffee b/src/scoped-properties.coffee deleted file mode 100644 index f8f8b4311..000000000 --- a/src/scoped-properties.coffee +++ /dev/null @@ -1,22 +0,0 @@ -CSON = require 'season' - -module.exports = -class ScopedProperties - @load: (scopedPropertiesPath, config, callback) -> - CSON.readFile scopedPropertiesPath, (error, scopedProperties={}) -> - if error? - callback(error) - else - callback(null, new ScopedProperties(scopedPropertiesPath, scopedProperties, config)) - - constructor: (@path, @scopedProperties, @config) -> - - activate: -> - for selector, properties of @scopedProperties - @config.set(null, properties, scopeSelector: selector, source: @path) - return - - deactivate: -> - for selector of @scopedProperties - @config.unset(null, scopeSelector: selector, source: @path) - return diff --git a/src/selection.js b/src/selection.js index 2c64fa126..70e5e73df 100644 --- a/src/selection.js +++ b/src/selection.js @@ -407,6 +407,25 @@ class Selection { if (autoscroll) this.cursor.autoscroll() } + // Private: Ensure that the {TextEditor} is not marked read-only before allowing a buffer modification to occur. if + // the editor is read-only, require an explicit opt-in option to proceed (`bypassReadOnly`) or throw an Error. + ensureWritable (methodName, opts) { + if (!opts.bypassReadOnly && this.editor.isReadOnly()) { + if (atom.inDevMode() || atom.inSpecMode()) { + const e = new Error('Attempt to mutate a read-only TextEditor through a Selection') + e.detail = + `Your package is attempting to call ${methodName} on a selection within an editor that has been marked ` + + ' read-only. Pass {bypassReadOnly: true} to modify it anyway, or test editors with .isReadOnly() before ' + + ' attempting modifications.' + throw e + } + + return false + } + + return true + } + /* Section: Modifying the selected text */ @@ -427,8 +446,11 @@ class Selection { // behavior is suppressed. // level between the first lines and the trailing lines. // * `normalizeLineEndings` (optional) {Boolean} (default: true) - // * `undo` If `skip`, skips the undo stack for this operation. + // * `undo` *Deprecated* If `skip`, skips the undo stack for this operation. This property is deprecated. Call groupLastChanges() on the {TextBuffer} afterward instead. + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) insertText (text, options = {}) { + if (!this.ensureWritable('insertText', options)) return + let desiredIndentLevel, indentAdjustment const oldBufferRange = this.getBufferRange() const wasReversed = this.isReversed() @@ -492,90 +514,134 @@ class Selection { // Public: Removes the first character before the selection if the selection // is empty otherwise it deletes the selection. - backspace () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + backspace (options = {}) { + if (!this.ensureWritable('backspace', options)) return if (this.isEmpty()) this.selectLeft() - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes the selection or, if nothing is selected, then all // characters from the start of the selection back to the previous word // boundary. - deleteToPreviousWordBoundary () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteToPreviousWordBoundary (options = {}) { + if (!this.ensureWritable('deleteToPreviousWordBoundary', options)) return if (this.isEmpty()) this.selectToPreviousWordBoundary() - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes the selection or, if nothing is selected, then all // characters from the start of the selection up to the next word // boundary. - deleteToNextWordBoundary () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteToNextWordBoundary (options = {}) { + if (!this.ensureWritable('deleteToNextWordBoundary', options)) return if (this.isEmpty()) this.selectToNextWordBoundary() - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes from the start of the selection to the beginning of the // current word if the selection is empty otherwise it deletes the selection. - deleteToBeginningOfWord () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteToBeginningOfWord (options = {}) { + if (!this.ensureWritable('deleteToBeginningOfWord', options)) return if (this.isEmpty()) this.selectToBeginningOfWord() - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes from the beginning of the line which the selection begins on // all the way through to the end of the selection. - deleteToBeginningOfLine () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteToBeginningOfLine (options = {}) { + if (!this.ensureWritable('deleteToBeginningOfLine', options)) return if (this.isEmpty() && this.cursor.isAtBeginningOfLine()) { this.selectLeft() } else { this.selectToBeginningOfLine() } - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes the selection or the next character after the start of the // selection if the selection is empty. - delete () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + delete (options = {}) { + if (!this.ensureWritable('delete', options)) return if (this.isEmpty()) this.selectRight() - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: If the selection is empty, removes all text from the cursor to the // end of the line. If the cursor is already at the end of the line, it // removes the following newline. If the selection isn't empty, only deletes // the contents of the selection. - deleteToEndOfLine () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteToEndOfLine (options = {}) { + if (!this.ensureWritable('deleteToEndOfLine', options)) return if (this.isEmpty()) { if (this.cursor.isAtEndOfLine()) { - this.delete() + this.delete(options) return } this.selectToEndOfLine() } - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes the selection or all characters from the start of the // selection to the end of the current word if nothing is selected. - deleteToEndOfWord () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteToEndOfWord (options = {}) { + if (!this.ensureWritable('deleteToEndOfWord', options)) return if (this.isEmpty()) this.selectToEndOfWord() - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes the selection or all characters from the start of the // selection to the end of the current word if nothing is selected. - deleteToBeginningOfSubword () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteToBeginningOfSubword (options = {}) { + if (!this.ensureWritable('deleteToBeginningOfSubword', options)) return if (this.isEmpty()) this.selectToPreviousSubwordBoundary() - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes the selection or all characters from the start of the // selection to the end of the current word if nothing is selected. - deleteToEndOfSubword () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteToEndOfSubword (options = {}) { + if (!this.ensureWritable('deleteToEndOfSubword', options)) return if (this.isEmpty()) this.selectToNextSubwordBoundary() - this.deleteSelectedText() + this.deleteSelectedText(options) } // Public: Removes only the selected text. - deleteSelectedText () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteSelectedText (options = {}) { + if (!this.ensureWritable('deleteSelectedText', options)) return const bufferRange = this.getBufferRange() if (!bufferRange.isEmpty()) this.editor.buffer.delete(bufferRange) if (this.cursor) this.cursor.setBufferPosition(bufferRange.start) @@ -584,7 +650,11 @@ class Selection { // Public: Removes the line at the beginning of the selection if the selection // is empty unless the selection spans multiple lines in which case all lines // are removed. - deleteLine () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + deleteLine (options = {}) { + if (!this.ensureWritable('deleteLine', options)) return const range = this.getBufferRange() if (range.isEmpty()) { const start = this.cursor.getScreenRow() @@ -607,7 +677,11 @@ class Selection { // be separated by a single space. // // If there selection spans more than one line, all the lines are joined together. - joinLines () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + joinLines (options = {}) { + if (!this.ensureWritable('joinLines', options)) return let joinMarker const selectedRange = this.getBufferRange() if (selectedRange.isEmpty()) { @@ -629,7 +703,7 @@ class Selection { }) if (trailingWhitespaceRange) { this.setBufferRange(trailingWhitespaceRange) - this.deleteSelectedText() + this.deleteSelectedText(options) } const currentRow = selectedRange.start.row @@ -638,7 +712,7 @@ class Selection { (nextRow <= this.editor.buffer.getLastRow()) && (this.editor.buffer.lineLengthForRow(nextRow) > 0) && (this.editor.buffer.lineLengthForRow(currentRow) > 0) - if (insertSpace) this.insertText(' ') + if (insertSpace) this.insertText(' ', options) this.cursor.moveToEndOfLine() @@ -647,7 +721,7 @@ class Selection { this.cursor.moveRight() this.cursor.moveToFirstCharacterOfLine() }) - this.deleteSelectedText() + this.deleteSelectedText(options) if (insertSpace) this.cursor.moveLeft() } @@ -660,7 +734,11 @@ class Selection { } // Public: Removes one level of indent from the currently selected rows. - outdentSelectedRows () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + outdentSelectedRows (options = {}) { + if (!this.ensureWritable('outdentSelectedRows', options)) return const [start, end] = this.getBufferRowRange() const {buffer} = this.editor const leadingTabRegex = new RegExp(`^( {1,${this.editor.getTabLength()}}|\t)`) @@ -674,7 +752,11 @@ class Selection { // Public: Sets the indentation level of all selected rows to values suggested // by the relevant grammars. - autoIndentSelectedRows () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + autoIndentSelectedRows (options = {}) { + if (!this.ensureWritable('autoIndentSelectedRows', options)) return const [start, end] = this.getBufferRowRange() return this.editor.autoIndentBufferRows(start, end) } @@ -683,29 +765,45 @@ class Selection { // of a comment. // // Removes the comment if they are currently wrapped in a comment. - toggleLineComments () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + toggleLineComments (options = {}) { + if (!this.ensureWritable('toggleLineComments', options)) return this.editor.toggleLineCommentsForBufferRows(...(this.getBufferRowRange() || [])) } // Public: Cuts the selection until the end of the screen line. - cutToEndOfLine (maintainClipboard) { + // + // * `maintainClipboard` {Boolean} + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + cutToEndOfLine (maintainClipboard, options = {}) { + if (!this.ensureWritable('cutToEndOfLine', options)) return if (this.isEmpty()) this.selectToEndOfLine() - return this.cut(maintainClipboard) + return this.cut(maintainClipboard, false, options.bypassReadOnly) } // Public: Cuts the selection until the end of the buffer line. - cutToEndOfBufferLine (maintainClipboard) { + // + // * `maintainClipboard` {Boolean} + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + cutToEndOfBufferLine (maintainClipboard, options = {}) { + if (!this.ensureWritable('cutToEndOfBufferLine', options)) return if (this.isEmpty()) this.selectToEndOfBufferLine() - this.cut(maintainClipboard) + this.cut(maintainClipboard, false, options.bypassReadOnly) } // Public: Copies the selection to the clipboard and then deletes it. // // * `maintainClipboard` {Boolean} (default: false) See {::copy} // * `fullLine` {Boolean} (default: false) See {::copy} - cut (maintainClipboard = false, fullLine = false) { + // * `bypassReadOnly` {Boolean} (default: false) Must be `true` to modify text within a read-only editor. + cut (maintainClipboard = false, fullLine = false, bypassReadOnly = false) { + if (!this.ensureWritable('cut', {bypassReadOnly})) return this.copy(maintainClipboard, fullLine) - this.delete() + this.delete({bypassReadOnly}) } // Public: Copies the current selection to the clipboard. @@ -783,7 +881,9 @@ class Selection { // * `options` (optional) {Object} with the keys: // * `autoIndent` If `true`, the line is indented to an automatically-inferred // level. Otherwise, {TextEditor::getTabText} is inserted. - indent ({autoIndent} = {}) { + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + indent ({autoIndent, bypassReadOnly} = {}) { + if (!this.ensureWritable('indent', {bypassReadOnly})) return const {row} = this.cursor.getBufferPosition() if (this.isEmpty()) { @@ -793,17 +893,21 @@ class Selection { if (autoIndent && delta > 0) { if (!this.editor.getSoftTabs()) delta = Math.max(delta, 1) - this.insertText(this.editor.buildIndentString(delta)) + this.insertText(this.editor.buildIndentString(delta), {bypassReadOnly}) } else { - this.insertText(this.editor.buildIndentString(1, this.cursor.getBufferColumn())) + this.insertText(this.editor.buildIndentString(1, this.cursor.getBufferColumn()), {bypassReadOnly}) } } else { - this.indentSelectedRows() + this.indentSelectedRows({bypassReadOnly}) } } // Public: If the selection spans multiple rows, indent all of them. - indentSelectedRows () { + // + // * `options` (optional) {Object} with the keys: + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify text within a read-only editor. (default: false) + indentSelectedRows (options = {}) { + if (!this.ensureWritable('indentSelectedRows', options)) return const [start, end] = this.getBufferRowRange() for (let row = start; row <= end; row++) { if (this.editor.buffer.lineLengthForRow(row) !== 0) { @@ -933,14 +1037,15 @@ class Selection { this.editor.cursorMoved(cursorMovedEvent) } - this.emitter.emit('did-change-range') - this.editor.selectionRangeChanged({ + const rangeChangedEvent = { oldBufferRange: new Range(oldHeadBufferPosition, oldTailBufferPosition), oldScreenRange: new Range(oldHeadScreenPosition, oldTailScreenPosition), newBufferRange: this.getBufferRange(), newScreenRange: this.getScreenRange(), selection: this - }) + } + this.emitter.emit('did-change-range', rangeChangedEvent) + this.editor.selectionRangeChanged(rangeChangedEvent) } markerDidDestroy () { diff --git a/src/selectors.js b/src/selectors.js new file mode 100644 index 000000000..ce03b80b4 --- /dev/null +++ b/src/selectors.js @@ -0,0 +1,38 @@ +module.exports = {selectorMatchesAnyScope, matcherForSelector} + +const {isSubset} = require('underscore-plus') + +// Private: Parse a selector into parts. +// If already parsed, returns the selector unmodified. +// +// * `selector` a {String|Array} specifying what to match +// Returns selector parts, an {Array}. +function parse (selector) { + return typeof selector === 'string' + ? selector.replace(/^\./, '').split('.') + : selector +} + +const always = scope => true + +// Essential: Return a matcher function for a selector. +// +// * selector, a {String} selector +// Returns {(scope: String) -> Boolean}, a matcher function returning +// true iff the scope matches the selector. +function matcherForSelector (selector) { + const parts = parse(selector) + if (typeof parts === 'function') return parts + return selector + ? scope => isSubset(parts, parse(scope)) + : always +} + +// Essential: Return true iff the selector matches any provided scope. +// +// * {String} selector +// * {Array} scopes +// Returns {Boolean} true if any scope matches the selector. +function selectorMatchesAnyScope (selector, scopes) { + return !selector || scopes.some(matcherForSelector(selector)) +} diff --git a/src/test.ejs b/src/test.ejs new file mode 100644 index 000000000..7b93c31b3 --- /dev/null +++ b/src/test.ejs @@ -0,0 +1,9 @@ + + +<% if something() { %> +
+ <%= html `ok how about this` %> +
+<% } %> + + diff --git a/src/text-editor-component.js b/src/text-editor-component.js index 3e56dd821..ffb55c454 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -5,8 +5,8 @@ const {Point, Range} = require('text-buffer') const LineTopIndex = require('line-top-index') const TextEditor = require('./text-editor') const {isPairedCharacter} = require('./text-utils') -const clipboard = require('./safe-clipboard') const electron = require('electron') +const clipboard = electron.clipboard const $ = etch.dom let TextEditorElement @@ -148,12 +148,13 @@ class TextEditorComponent { this.lineNumbersToRender = { maxDigits: 2, bufferRows: [], + screenRows: [], keys: [], softWrappedFlags: [], foldableFlags: [] } this.decorationsToRender = { - lineNumbers: null, + lineNumbers: new Map(), lines: null, highlights: [], cursors: [], @@ -458,15 +459,18 @@ class TextEditorComponent { let clientContainerWidth = '100%' if (this.hasInitialMeasurements) { if (model.getAutoHeight()) { - clientContainerHeight = this.getContentHeight() - if (this.canScrollHorizontally()) clientContainerHeight += this.getHorizontalScrollbarHeight() - clientContainerHeight += 'px' + clientContainerHeight = + this.getContentHeight() + + this.getHorizontalScrollbarHeight() + + 'px' } if (model.getAutoWidth()) { style.width = 'min-content' - clientContainerWidth = this.getGutterContainerWidth() + this.getContentWidth() - if (this.canScrollVertically()) clientContainerWidth += this.getVerticalScrollbarWidth() - clientContainerWidth += 'px' + clientContainerWidth = + this.getGutterContainerWidth() + + this.getContentWidth() + + this.getVerticalScrollbarWidth() + + 'px' } else { style.width = this.element.style.width } @@ -477,7 +481,7 @@ class TextEditorComponent { attributes.mini = '' } - if (!this.isInputEnabled()) { + if (model.isReadOnly()) { attributes.readonly = '' } @@ -751,20 +755,14 @@ class TextEditorComponent { scrollLeft = this.getScrollLeft() canScrollHorizontally = this.canScrollHorizontally() canScrollVertically = this.canScrollVertically() - horizontalScrollbarHeight = - canScrollHorizontally - ? this.getHorizontalScrollbarHeight() - : 0 - verticalScrollbarWidth = - canScrollVertically - ? this.getVerticalScrollbarWidth() - : 0 + horizontalScrollbarHeight = this.getHorizontalScrollbarHeight() + verticalScrollbarWidth = this.getVerticalScrollbarWidth() forceScrollbarVisible = this.remeasureScrollbars } else { forceScrollbarVisible = true } - const dummyScrollbarVnodes = [ + return [ $(DummyScrollbarComponent, { ref: 'verticalScrollbar', orientation: 'vertical', @@ -786,13 +784,10 @@ class TextEditorComponent { scrollLeft, verticalScrollbarWidth, forceScrollbarVisible - }) - ] + }), - // If both scrollbars are visible, push a dummy element to force a "corner" - // to render where the two scrollbars meet at the lower right - if (verticalScrollbarWidth > 0 && horizontalScrollbarHeight > 0) { - dummyScrollbarVnodes.push($.div( + // Force a "corner" to render where the two scrollbars meet at the lower right + $.div( { ref: 'scrollbarCorner', className: 'scrollbar-corner', @@ -805,10 +800,8 @@ class TextEditorComponent { overflow: 'scroll' } } - )) - } - - return dummyScrollbarVnodes + ) + ] } else { return null } @@ -856,10 +849,7 @@ class TextEditorComponent { } for (let i = 0; i < newClassList.length; i++) { - const className = newClassList[i] - if (!oldClassList || !oldClassList.includes(className)) { - this.element.classList.add(className) - } + this.element.classList.add(newClassList[i]) } this.classList = newClassList @@ -897,7 +887,7 @@ class TextEditorComponent { queryLineNumbersToRender () { const {model} = this.props - if (!model.isLineNumberGutterVisible()) return + if (!model.anyLineNumberGutterVisible()) return if (this.showLineNumbers !== model.doesShowLineNumbers()) { this.remeasureGutterDimensions = true this.showLineNumbers = model.doesShowLineNumbers() @@ -953,7 +943,7 @@ class TextEditorComponent { queryMaxLineNumberDigits () { const {model} = this.props - if (model.isLineNumberGutterVisible()) { + if (model.anyLineNumberGutterVisible()) { const maxDigits = Math.max(2, model.getLineCount().toString().length) if (maxDigits !== this.lineNumbersToRender.maxDigits) { this.remeasureGutterDimensions = true @@ -988,7 +978,7 @@ class TextEditorComponent { } queryDecorationsToRender () { - this.decorationsToRender.lineNumbers = [] + this.decorationsToRender.lineNumbers.clear() this.decorationsToRender.lines = [] this.decorationsToRender.overlays.length = 0 this.decorationsToRender.customGutter.clear() @@ -1051,7 +1041,17 @@ class TextEditorComponent { } addLineDecorationToRender (type, decoration, screenRange, reversed) { - const decorationsToRender = (type === 'line') ? this.decorationsToRender.lines : this.decorationsToRender.lineNumbers + let decorationsToRender + if (type === 'line') { + decorationsToRender = this.decorationsToRender.lines + } else { + const gutterName = decoration.gutterName || 'line-number' + decorationsToRender = this.decorationsToRender.lineNumbers.get(gutterName) + if (!decorationsToRender) { + decorationsToRender = [] + this.decorationsToRender.lineNumbers.set(gutterName, decorationsToRender) + } + } let omitLastRow = false if (screenRange.isEmpty()) { @@ -2626,37 +2626,25 @@ class TextEditorComponent { getScrollContainerHeight () { if (this.props.model.getAutoHeight()) { - return this.getScrollHeight() + return this.getScrollHeight() + this.getHorizontalScrollbarHeight() } else { return this.getClientContainerHeight() } } getScrollContainerClientWidth () { - if (this.canScrollVertically()) { - return this.getScrollContainerWidth() - this.getVerticalScrollbarWidth() - } else { - return this.getScrollContainerWidth() - } + return this.getScrollContainerWidth() - this.getVerticalScrollbarWidth() } getScrollContainerClientHeight () { - if (this.canScrollHorizontally()) { - return this.getScrollContainerHeight() - this.getHorizontalScrollbarHeight() - } else { - return this.getScrollContainerHeight() - } + return this.getScrollContainerHeight() - this.getHorizontalScrollbarHeight() } canScrollVertically () { const {model} = this.props if (model.isMini()) return false if (model.getAutoHeight()) return false - if (this.getContentHeight() > this.getScrollContainerHeight()) return true - return ( - this.getContentWidth() > this.getScrollContainerWidth() && - this.getContentHeight() > (this.getScrollContainerHeight() - this.getHorizontalScrollbarHeight()) - ) + return this.getContentHeight() > this.getScrollContainerClientHeight() } canScrollHorizontally () { @@ -2664,11 +2652,7 @@ class TextEditorComponent { if (model.isMini()) return false if (model.getAutoWidth()) return false if (model.isSoftWrapped()) return false - if (this.getContentWidth() > this.getScrollContainerWidth()) return true - return ( - this.getContentHeight() > this.getScrollContainerHeight() && - this.getContentWidth() > (this.getScrollContainerWidth() - this.getVerticalScrollbarWidth()) - ) + return this.getContentWidth() > this.getScrollContainerClientWidth() } getScrollHeight () { @@ -2965,11 +2949,11 @@ class TextEditorComponent { } setInputEnabled (inputEnabled) { - this.props.model.update({readOnly: !inputEnabled}) + this.props.model.update({keyboardInputEnabled: inputEnabled}) } - isInputEnabled (inputEnabled) { - return !this.props.model.isReadOnly() + isInputEnabled () { + return !this.props.model.isReadOnly() && this.props.model.isKeyboardInputEnabled() } getHiddenInput () { @@ -3126,7 +3110,7 @@ class GutterContainerComponent { }, $.div({style: innerStyle}, guttersToRender.map((gutter) => { - if (gutter.name === 'line-number') { + if (gutter.type === 'line-number') { return this.renderLineNumberGutter(gutter) } else { return $(CustomGutterComponent, { @@ -3145,18 +3129,29 @@ class GutterContainerComponent { renderLineNumberGutter (gutter) { const { - rootComponent, isLineNumberGutterVisible, showLineNumbers, hasInitialMeasurements, lineNumbersToRender, + rootComponent, showLineNumbers, hasInitialMeasurements, lineNumbersToRender, renderedStartRow, renderedEndRow, rowsPerTile, decorationsToRender, didMeasureVisibleBlockDecoration, scrollHeight, lineNumberGutterWidth, lineHeight } = this.props - if (!isLineNumberGutterVisible) return null + if (!gutter.isVisible()) { + return null + } + + const oneTrueLineNumberGutter = gutter.name === 'line-number' + const ref = oneTrueLineNumberGutter ? 'lineNumberGutter' : undefined + const width = oneTrueLineNumberGutter ? lineNumberGutterWidth : undefined if (hasInitialMeasurements) { const {maxDigits, keys, bufferRows, screenRows, softWrappedFlags, foldableFlags} = lineNumbersToRender return $(LineNumberGutterComponent, { - ref: 'lineNumberGutter', + ref, element: gutter.getElement(), + name: gutter.name, + className: gutter.className, + labelFn: gutter.labelFn, + onMouseDown: gutter.onMouseDown, + onMouseMove: gutter.onMouseMove, rootComponent: rootComponent, startRow: renderedStartRow, endRow: renderedEndRow, @@ -3167,18 +3162,22 @@ class GutterContainerComponent { screenRows: screenRows, softWrappedFlags: softWrappedFlags, foldableFlags: foldableFlags, - decorations: decorationsToRender.lineNumbers, + decorations: decorationsToRender.lineNumbers.get(gutter.name) || [], blockDecorations: decorationsToRender.blocks, didMeasureVisibleBlockDecoration: didMeasureVisibleBlockDecoration, height: scrollHeight, - width: lineNumberGutterWidth, + width, lineHeight: lineHeight, showLineNumbers }) } else { return $(LineNumberGutterComponent, { - ref: 'lineNumberGutter', + ref, element: gutter.getElement(), + name: gutter.name, + className: gutter.className, + onMouseDown: gutter.onMouseDown, + onMouseMove: gutter.onMouseMove, maxDigits: lineNumbersToRender.maxDigits, showLineNumbers }) @@ -3206,7 +3205,8 @@ class LineNumberGutterComponent { render () { const { rootComponent, showLineNumbers, height, width, startRow, endRow, rowsPerTile, - maxDigits, keys, bufferRows, screenRows, softWrappedFlags, foldableFlags, decorations + maxDigits, keys, bufferRows, screenRows, softWrappedFlags, foldableFlags, decorations, + className } = this.props let children = null @@ -3234,8 +3234,12 @@ class LineNumberGutterComponent { let number = null if (showLineNumbers) { - number = softWrapped ? '•' : bufferRow + 1 - number = NBSP_CHARACTER.repeat(maxDigits - number.length) + number + if (this.props.labelFn == null) { + number = softWrapped ? '•' : bufferRow + 1 + number = NBSP_CHARACTER.repeat(maxDigits - number.length) + number + } else { + number = this.props.labelFn({bufferRow, screenRow, foldable, softWrapped, maxDigits}) + } } // We need to adjust the line number position to account for block @@ -3262,6 +3266,7 @@ class LineNumberGutterComponent { const tileTop = rootComponent.pixelPositionBeforeBlocksForRow(tileStartRow) const tileBottom = rootComponent.pixelPositionBeforeBlocksForRow(tileEndRow) const tileHeight = tileBottom - tileTop + const tileWidth = width != null && width > 0 ? width + 'px' : '' children[i] = $.div({ key: rootComponent.idsByTileStartRow.get(tileStartRow), @@ -3270,20 +3275,26 @@ class LineNumberGutterComponent { position: 'absolute', top: 0, height: tileHeight + 'px', - width: width + 'px', + width: tileWidth, transform: `translateY(${tileTop}px)` } }, ...tileChildren) } } + let rootClassName = 'gutter line-numbers' + if (className) { + rootClassName += ' ' + className + } + return $.div( { - className: 'gutter line-numbers', - attributes: {'gutter-name': 'line-number'}, + className: rootClassName, + attributes: {'gutter-name': this.props.name}, style: {position: 'relative', height: ceilToPhysicalPixelBoundary(height) + 'px'}, on: { - mousedown: this.didMouseDown + mousedown: this.didMouseDown, + mousemove: this.didMouseMove } }, $.div({key: 'placeholder', className: 'line-number dummy', style: {visibility: 'hidden'}}, @@ -3305,6 +3316,8 @@ class LineNumberGutterComponent { if (oldProps.endRow !== newProps.endRow) return true if (oldProps.rowsPerTile !== newProps.rowsPerTile) return true if (oldProps.maxDigits !== newProps.maxDigits) return true + if (oldProps.labelFn !== newProps.labelFn) return true + if (oldProps.className !== newProps.className) return true if (newProps.didMeasureVisibleBlockDecoration) return true if (!arraysEqual(oldProps.keys, newProps.keys)) return true if (!arraysEqual(oldProps.bufferRows, newProps.bufferRows)) return true @@ -3351,7 +3364,27 @@ class LineNumberGutterComponent { } didMouseDown (event) { - this.props.rootComponent.didMouseDownOnLineNumberGutter(event) + if (this.props.onMouseDown == null) { + this.props.rootComponent.didMouseDownOnLineNumberGutter(event) + } else { + const {bufferRow, screenRow} = event.target.dataset + this.props.onMouseDown({ + bufferRow: parseInt(bufferRow, 10), + screenRow: parseInt(screenRow, 10), + domEvent: event + }) + } + } + + didMouseMove (event) { + if (this.props.onMouseMove != null) { + const {bufferRow, screenRow} = event.target.dataset + this.props.onMouseMove({ + bufferRow: parseInt(bufferRow, 10), + screenRow: parseInt(screenRow, 10), + domEvent: event + }) + } } } @@ -3359,7 +3392,8 @@ class LineNumberComponent { constructor (props) { const {className, width, marginTop, bufferRow, screenRow, number, nodePool} = props this.props = props - const style = {width: width + 'px'} + const style = {} + if (width != null && width > 0) style.width = width + 'px' if (marginTop != null && marginTop > 0) style.marginTop = marginTop + 'px' this.element = nodePool.getElement('DIV', className, style) this.element.dataset.bufferRow = bufferRow @@ -3379,22 +3413,31 @@ class LineNumberComponent { if (this.props.bufferRow !== bufferRow) this.element.dataset.bufferRow = bufferRow if (this.props.screenRow !== screenRow) this.element.dataset.screenRow = screenRow if (this.props.className !== className) this.element.className = className - if (this.props.width !== width) this.element.style.width = width + 'px' + if (this.props.width !== width) { + if (width != null && width > 0) { + this.element.style.width = width + 'px' + } else { + this.element.style.width = '' + } + } if (this.props.marginTop !== marginTop) { - if (marginTop != null) { + if (marginTop != null && marginTop > 0) { this.element.style.marginTop = marginTop + 'px' } else { this.element.style.marginTop = '' } } + if (this.props.number !== number) { - if (number) { - this.element.insertBefore(nodePool.getTextNode(number), this.element.firstChild) - } else { + if (this.props.number != null) { const numberNode = this.element.firstChild numberNode.remove() nodePool.release(numberNode) } + + if (number != null) { + this.element.insertBefore(nodePool.getTextNode(number), this.element.firstChild) + } } this.props = props @@ -3420,9 +3463,13 @@ class CustomGutterComponent { } render () { + let className = 'gutter' + if (this.props.className) { + className += ' ' + this.props.className + } return $.div( { - className: 'gutter', + className, attributes: {'gutter-name': this.props.name}, style: { display: this.props.visible ? '' : 'none' @@ -3522,7 +3569,7 @@ class CursorsAndInputComponent { const cursorStyle = { height: cursorHeight, - width: pixelWidth + 'px', + width: Math.min(pixelWidth, scrollWidth - pixelLeft) + 'px', transform: `translate(${pixelLeft}px, ${pixelTop}px)` } if (extraCursorStyle) Object.assign(cursorStyle, extraCursorStyle) diff --git a/src/text-editor-registry.js b/src/text-editor-registry.js index 132b24ffb..e9dbf2f5c 100644 --- a/src/text-editor-registry.js +++ b/src/text-editor-registry.js @@ -218,7 +218,7 @@ class TextEditorRegistry { async updateAndMonitorEditorSettings (editor, oldLanguageMode) { await this.initialPackageActivationPromise this.updateEditorSettingsForLanguageMode(editor, oldLanguageMode) - await this.subscribeToSettingsForEditorScope(editor) + this.subscribeToSettingsForEditorScope(editor) } updateEditorSettingsForLanguageMode (editor, oldLanguageMode) { @@ -246,7 +246,9 @@ class TextEditorRegistry { } } - async subscribeToSettingsForEditorScope (editor) { + subscribeToSettingsForEditorScope (editor) { + if (!this.editorsWithMaintainedConfig) return + const scopeDescriptor = editor.getRootScopeDescriptor() const scopeChain = scopeDescriptor.getScopeChain() diff --git a/src/text-editor.js b/src/text-editor.js index 9bfa8ff3e..3616db28c 100644 --- a/src/text-editor.js +++ b/src/text-editor.js @@ -42,9 +42,10 @@ const DEFAULT_NON_WORD_CHARACTERS = "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-…" // then be called with all current editor instances and also when any editor is // created in the future. // -// ```coffee -// atom.workspace.observeTextEditors (editor) -> +// ```js +// atom.workspace.observeTextEditors(editor => { // editor.insertText('Hello World') +// }) // ``` // // ## Buffer vs. Screen Coordinates @@ -106,6 +107,13 @@ class TextEditor { } state.assert = atomEnvironment.assert.bind(atomEnvironment) + + // Semantics of the readOnly flag have changed since its introduction. + // Only respect readOnly2, which has been set with the current readOnly semantics. + delete state.readOnly + state.readOnly = state.readOnly2 + delete state.readOnly2 + const editor = new TextEditor(state) if (state.registered) { const disposable = atomEnvironment.textEditors.add(editor) @@ -129,6 +137,7 @@ class TextEditor { this.decorationManager = params.decorationManager this.selectionsMarkerLayer = params.selectionsMarkerLayer this.mini = (params.mini != null) ? params.mini : false + this.keyboardInputEnabled = (params.keyboardInputEnabled != null) ? params.keyboardInputEnabled : true this.readOnly = (params.readOnly != null) ? params.readOnly : false this.placeholderText = params.placeholderText this.showLineNumbers = params.showLineNumbers @@ -224,7 +233,7 @@ class TextEditor { this.defaultMarkerLayer = this.displayLayer.addMarkerLayer() if (!this.selectionsMarkerLayer) { - this.selectionsMarkerLayer = this.addMarkerLayer({maintainHistory: true, persistent: true}) + this.selectionsMarkerLayer = this.addMarkerLayer({maintainHistory: true, persistent: true, role: 'selections'}) } this.decorationManager = new DecorationManager(this) @@ -249,6 +258,7 @@ class TextEditor { this.gutterContainer = new GutterContainer(this) this.lineNumberGutter = this.gutterContainer.addGutter({ name: 'line-number', + type: 'line-number', priority: 0, visible: params.lineNumberGutterVisible }) @@ -415,6 +425,15 @@ class TextEditor { } break + case 'keyboardInputEnabled': + if (value !== this.keyboardInputEnabled) { + this.keyboardInputEnabled = value + if (this.component != null) { + this.component.scheduleUpdate() + } + } + break + case 'placeholderText': if (value !== this.placeholderText) { this.placeholderText = value @@ -545,7 +564,8 @@ class TextEditor { softWrapAtPreferredLineLength: this.softWrapAtPreferredLineLength, preferredLineLength: this.preferredLineLength, mini: this.mini, - readOnly: this.readOnly, + readOnly2: this.readOnly, // readOnly encompassed both readOnly and keyboardInputEnabled + keyboardInputEnabled: this.keyboardInputEnabled, editorWidthInChars: this.editorWidthInChars, width: this.width, maxScreenLineLength: this.maxScreenLineLength, @@ -987,6 +1007,12 @@ class TextEditor { isReadOnly () { return this.readOnly } + enableKeyboardInput (enabled) { + this.update({keyboardInputEnabled: enabled}) + } + + isKeyboardInputEnabled () { return this.keyboardInputEnabled } + onDidChangeMini (callback) { return this.emitter.on('did-change-mini', callback) } @@ -995,6 +1021,10 @@ class TextEditor { isLineNumberGutterVisible () { return this.lineNumberGutter.isVisible() } + anyLineNumberGutterVisible () { + return this.getGutters().some(gutter => gutter.type === 'line-number' && gutter.visible) + } + onDidChangeLineNumberGutterVisible (callback) { return this.emitter.on('did-change-line-number-gutter-visible', callback) } @@ -1306,7 +1336,12 @@ class TextEditor { // Essential: Replaces the entire contents of the buffer with the given {String}. // // * `text` A {String} to replace with - setText (text) { return this.buffer.setText(text) } + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. + setText (text, options = {}) { + if (!this.ensureWritable('setText', options)) return + return this.buffer.setText(text) + } // Essential: Set the text in the given {Range} in buffer coordinates. // @@ -1314,10 +1349,12 @@ class TextEditor { // * `text` A {String} // * `options` (optional) {Object} // * `normalizeLineEndings` (optional) {Boolean} (default: true) - // * `undo` (optional) {String} 'skip' will skip the undo system + // * `undo` (optional) *Deprecated* {String} 'skip' will skip the undo system. This property is deprecated. Call groupLastChanges() on the {TextBuffer} afterward instead. + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) // // Returns the {Range} of the newly-inserted text. - setTextInBufferRange (range, text, options) { + setTextInBufferRange (range, text, options = {}) { + if (!this.ensureWritable('setTextInBufferRange', options)) return return this.getBuffer().setTextInRange(range, text, options) } @@ -1326,9 +1363,9 @@ class TextEditor { // * `text` A {String} representing the text to insert. // * `options` (optional) See {Selection::insertText}. // - // Returns a {Range} when the text has been inserted - // Returns a {Boolean} false when the text has not been inserted + // Returns a {Range} when the text has been inserted. Returns a {Boolean} `false` when the text has not been inserted. insertText (text, options = {}) { + if (!this.ensureWritable('insertText', options)) return if (!this.emitWillInsertTextEvent(text)) return false let groupLastChanges = false @@ -1352,20 +1389,31 @@ class TextEditor { } // Essential: For each selection, replace the selected text with a newline. - insertNewline (options) { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + insertNewline (options = {}) { return this.insertText('\n', options) } // Essential: For each selection, if the selection is empty, delete the character // following the cursor. Otherwise delete the selected text. - delete () { - return this.mutateSelectedText(selection => selection.delete()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + delete (options = {}) { + if (!this.ensureWritable('delete', options)) return + return this.mutateSelectedText(selection => selection.delete(options)) } // Essential: For each selection, if the selection is empty, delete the character // preceding the cursor. Otherwise delete the selected text. - backspace () { - return this.mutateSelectedText(selection => selection.backspace()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + backspace (options = {}) { + if (!this.ensureWritable('backspace', options)) return + return this.mutateSelectedText(selection => selection.backspace(options)) } // Extended: Mutate the text of all the selections in a single transaction. @@ -1386,7 +1434,12 @@ class TextEditor { // Move lines intersecting the most recent selection or multiple selections // up by one row in screen coordinates. - moveLineUp () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + moveLineUp (options = {}) { + if (!this.ensureWritable('moveLineUp', options)) return + const selections = this.getSelectedBufferRanges().sort((a, b) => a.compare(b)) if (selections[0].start.row === 0) return @@ -1454,7 +1507,12 @@ class TextEditor { // Move lines intersecting the most recent selection or multiple selections // down by one row in screen coordinates. - moveLineDown () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + moveLineDown (options = {}) { + if (!this.ensureWritable('moveLineDown', options)) return + const selections = this.getSelectedBufferRanges() selections.sort((a, b) => b.compare(a)) @@ -1526,7 +1584,11 @@ class TextEditor { } // Move any active selections one column to the left. - moveSelectionLeft () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + moveSelectionLeft (options = {}) { + if (!this.ensureWritable('moveSelectionLeft', options)) return const selections = this.getSelectedBufferRanges() const noSelectionAtStartOfLine = selections.every(selection => selection.start.column !== 0) @@ -1550,7 +1612,11 @@ class TextEditor { } // Move any active selections one column to the right. - moveSelectionRight () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + moveSelectionRight (options = {}) { + if (!this.ensureWritable('moveSelectionRight', options)) return const selections = this.getSelectedBufferRanges() const noSelectionAtEndOfLine = selections.every(selection => { return selection.end.column !== this.buffer.lineLengthForRow(selection.end.row) @@ -1575,7 +1641,12 @@ class TextEditor { } } - duplicateLines () { + // Duplicate all lines containing active selections. + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + duplicateLines (options = {}) { + if (!this.ensureWritable('duplicateLines', options)) return this.transact(() => { const selections = this.getSelectionsOrderedByBufferPosition() const previousSelectionRanges = [] @@ -1662,7 +1733,11 @@ class TextEditor { // // If the selection is empty, the characters preceding and following the cursor // are swapped. Otherwise, the selected characters are reversed. - transpose () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + transpose (options = {}) { + if (!this.ensureWritable('transpose', options)) return this.mutateSelectedText(selection => { if (selection.isEmpty()) { selection.selectRight() @@ -1680,23 +1755,35 @@ class TextEditor { // // For each selection, if the selection is empty, converts the containing word // to upper case. Otherwise convert the selected text to upper case. - upperCase () { - this.replaceSelectedText({selectWordIfEmpty: true}, text => text.toUpperCase()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + upperCase (options = {}) { + if (!this.ensureWritable('upperCase', options)) return + this.replaceSelectedText({selectWordIfEmpty: true}, text => text.toUpperCase(options)) } // Extended: Convert the selected text to lower case. // // For each selection, if the selection is empty, converts the containing word // to upper case. Otherwise convert the selected text to upper case. - lowerCase () { - this.replaceSelectedText({selectWordIfEmpty: true}, text => text.toLowerCase()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + lowerCase (options = {}) { + if (!this.ensureWritable('lowerCase', options)) return + this.replaceSelectedText({selectWordIfEmpty: true}, text => text.toLowerCase(options)) } // Extended: Toggle line comments for rows intersecting selections. // // If the current grammar doesn't support comments, does nothing. - toggleLineCommentsInSelection () { - this.mutateSelectedText(selection => selection.toggleLineComments()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + toggleLineCommentsInSelection (options = {}) { + if (!this.ensureWritable('toggleLineCommentsInSelection', options)) return + this.mutateSelectedText(selection => selection.toggleLineComments(options)) } // Convert multiple lines to a single line. @@ -1707,20 +1794,32 @@ class TextEditor { // // Joining a line means that multiple lines are converted to a single line with // the contents of each of the original non-empty lines separated by a space. - joinLines () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + joinLines (options = {}) { + if (!this.ensureWritable('joinLines', options)) return this.mutateSelectedText(selection => selection.joinLines()) } // Extended: For each cursor, insert a newline at beginning the following line. - insertNewlineBelow () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + insertNewlineBelow (options = {}) { + if (!this.ensureWritable('insertNewlineBelow', options)) return this.transact(() => { this.moveToEndOfLine() - this.insertNewline() + this.insertNewline(options) }) } // Extended: For each cursor, insert a newline at the end of the preceding line. - insertNewlineAbove () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + insertNewlineAbove (options = {}) { + if (!this.ensureWritable('insertNewlineAbove', options)) return this.transact(() => { const bufferRow = this.getCursorBufferPosition().row const indentLevel = this.indentationForBufferRow(bufferRow) @@ -1728,7 +1827,7 @@ class TextEditor { this.moveToBeginningOfLine() this.moveLeft() - this.insertNewline() + this.insertNewline(options) if (this.shouldAutoIndent() && (this.indentationForBufferRow(bufferRow) < indentLevel)) { this.setIndentationForBufferRow(bufferRow, indentLevel) @@ -1744,62 +1843,117 @@ class TextEditor { // Extended: For each selection, if the selection is empty, delete all characters // of the containing word that precede the cursor. Otherwise delete the // selected text. - deleteToBeginningOfWord () { - this.mutateSelectedText(selection => selection.deleteToBeginningOfWord()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteToBeginningOfWord (options = {}) { + if (!this.ensureWritable('deleteToBeginningOfWord', options)) return + this.mutateSelectedText(selection => selection.deleteToBeginningOfWord(options)) } // Extended: Similar to {::deleteToBeginningOfWord}, but deletes only back to the // previous word boundary. - deleteToPreviousWordBoundary () { - this.mutateSelectedText(selection => selection.deleteToPreviousWordBoundary()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteToPreviousWordBoundary (options = {}) { + if (!this.ensureWritable('deleteToPreviousWordBoundary', options)) return + this.mutateSelectedText(selection => selection.deleteToPreviousWordBoundary(options)) } // Extended: Similar to {::deleteToEndOfWord}, but deletes only up to the // next word boundary. - deleteToNextWordBoundary () { - this.mutateSelectedText(selection => selection.deleteToNextWordBoundary()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteToNextWordBoundary (options = {}) { + if (!this.ensureWritable('deleteToNextWordBoundary', options)) return + this.mutateSelectedText(selection => selection.deleteToNextWordBoundary(options)) } // Extended: For each selection, if the selection is empty, delete all characters // of the containing subword following the cursor. Otherwise delete the selected // text. - deleteToBeginningOfSubword () { - this.mutateSelectedText(selection => selection.deleteToBeginningOfSubword()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteToBeginningOfSubword (options = {}) { + if (!this.ensureWritable('deleteToBeginningOfSubword', options)) return + this.mutateSelectedText(selection => selection.deleteToBeginningOfSubword(options)) } // Extended: For each selection, if the selection is empty, delete all characters // of the containing subword following the cursor. Otherwise delete the selected // text. - deleteToEndOfSubword () { - this.mutateSelectedText(selection => selection.deleteToEndOfSubword()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteToEndOfSubword (options = {}) { + if (!this.ensureWritable('deleteToEndOfSubword', options)) return + this.mutateSelectedText(selection => selection.deleteToEndOfSubword(options)) } // Extended: For each selection, if the selection is empty, delete all characters // of the containing line that precede the cursor. Otherwise delete the // selected text. - deleteToBeginningOfLine () { - this.mutateSelectedText(selection => selection.deleteToBeginningOfLine()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteToBeginningOfLine (options = {}) { + if (!this.ensureWritable('deleteToBeginningOfLine', options)) return + this.mutateSelectedText(selection => selection.deleteToBeginningOfLine(options)) } // Extended: For each selection, if the selection is not empty, deletes the // selection; otherwise, deletes all characters of the containing line // following the cursor. If the cursor is already at the end of the line, // deletes the following newline. - deleteToEndOfLine () { - this.mutateSelectedText(selection => selection.deleteToEndOfLine()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteToEndOfLine (options = {}) { + if (!this.ensureWritable('deleteToEndOfLine', options)) return + this.mutateSelectedText(selection => selection.deleteToEndOfLine(options)) } // Extended: For each selection, if the selection is empty, delete all characters // of the containing word following the cursor. Otherwise delete the selected // text. - deleteToEndOfWord () { - this.mutateSelectedText(selection => selection.deleteToEndOfWord()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteToEndOfWord (options = {}) { + if (!this.ensureWritable('deleteToEndOfWord', options)) return + this.mutateSelectedText(selection => selection.deleteToEndOfWord(options)) } // Extended: Delete all lines intersecting selections. - deleteLine () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + deleteLine (options = {}) { + if (!this.ensureWritable('deleteLine', options)) return this.mergeSelectionsOnSameRows() - this.mutateSelectedText(selection => selection.deleteLine()) + this.mutateSelectedText(selection => selection.deleteLine(options)) + } + + // Private: Ensure that this editor is not marked read-only before allowing a buffer modification to occur. If + // the editor is read-only, require an explicit opt-in option to proceed (`bypassReadOnly`) or throw an Error. + ensureWritable (methodName, opts) { + if (!opts.bypassReadOnly && this.isReadOnly()) { + if (atom.inDevMode() || atom.inSpecMode()) { + const e = new Error('Attempt to mutate a read-only TextEditor') + e.detail = + `Your package is attempting to call ${methodName} on an editor that has been marked read-only. ` + + 'Pass {bypassReadOnly: true} to modify it anyway, or test editors with .isReadOnly() before attempting ' + + 'modifications.' + throw e + } + + return false + } + + return true } /* @@ -1807,14 +1961,22 @@ class TextEditor { */ // Essential: Undo the last change. - undo () { - this.avoidMergingSelections(() => this.buffer.undo()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + undo (options = {}) { + if (!this.ensureWritable('undo', options)) return + this.avoidMergingSelections(() => this.buffer.undo({selectionsMarkerLayer: this.selectionsMarkerLayer})) this.getLastSelection().autoscroll() } // Essential: Redo the last change. - redo () { - this.avoidMergingSelections(() => this.buffer.redo()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. (default: false) + redo (options = {}) { + if (!this.ensureWritable('redo', options)) return + this.avoidMergingSelections(() => this.buffer.redo({selectionsMarkerLayer: this.selectionsMarkerLayer})) this.getLastSelection().autoscroll() } @@ -1831,7 +1993,13 @@ class TextEditor { // still 'groupable', the two transactions are merged with respect to undo and redo. // * `fn` A {Function} to call inside the transaction. transact (groupingInterval, fn) { - return this.buffer.transact(groupingInterval, fn) + const options = {selectionsMarkerLayer: this.selectionsMarkerLayer} + if (typeof groupingInterval === 'function') { + fn = groupingInterval + } else { + options.groupingInterval = groupingInterval + } + return this.buffer.transact(options, fn) } // Extended: Abort an open transaction, undoing any operations performed so far @@ -1842,7 +2010,9 @@ class TextEditor { // with {::revertToCheckpoint} and {::groupChangesSinceCheckpoint}. // // Returns a checkpoint value. - createCheckpoint () { return this.buffer.createCheckpoint() } + createCheckpoint () { + return this.buffer.createCheckpoint({selectionsMarkerLayer: this.selectionsMarkerLayer}) + } // Extended: Revert the buffer to the state it was in when the given // checkpoint was created. @@ -1866,7 +2036,9 @@ class TextEditor { // * `checkpoint` The checkpoint from which to group changes. // // Returns a {Boolean} indicating whether the operation succeeded. - groupChangesSinceCheckpoint (checkpoint) { return this.buffer.groupChangesSinceCheckpoint(checkpoint) } + groupChangesSinceCheckpoint (checkpoint) { + return this.buffer.groupChangesSinceCheckpoint(checkpoint, {selectionsMarkerLayer: this.selectionsMarkerLayer}) + } /* Section: TextEditor Coordinates @@ -1957,11 +2129,11 @@ class TextEditor { // // ## Examples // - // ```coffee - // editor.clipBufferPosition([-1, -1]) # -> `[0, 0]` + // ```js + // editor.clipBufferPosition([-1, -1]) // -> `[0, 0]` // - // # When the line at buffer row 2 is 10 characters long - // editor.clipBufferPosition([2, Infinity]) # -> `[2, 10]` + // // When the line at buffer row 2 is 10 characters long + // editor.clipBufferPosition([2, Infinity]) // -> `[2, 10]` // ``` // // * `bufferPosition` The {Point} representing the position to clip. @@ -1986,11 +2158,11 @@ class TextEditor { // // ## Examples // - // ```coffee - // editor.clipScreenPosition([-1, -1]) # -> `[0, 0]` + // ```js + // editor.clipScreenPosition([-1, -1]) // -> `[0, 0]` // - // # When the line at screen row 2 is 10 characters long - // editor.clipScreenPosition([2, Infinity]) # -> `[2, 10]` + // // When the line at screen row 2 is 10 characters long + // editor.clipScreenPosition([2, Infinity]) // -> `[2, 10]` // ``` // // * `screenPosition` The {Point} representing the position to clip. @@ -3548,13 +3720,21 @@ class TextEditor { } // Extended: Indent rows intersecting selections by one level. - indentSelectedRows () { - return this.mutateSelectedText(selection => selection.indentSelectedRows()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. + indentSelectedRows (options = {}) { + if (!this.ensureWritable('indentSelectedRows', options)) return + return this.mutateSelectedText(selection => selection.indentSelectedRows(options)) } // Extended: Outdent rows intersecting selections by one level. - outdentSelectedRows () { - return this.mutateSelectedText(selection => selection.outdentSelectedRows()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. + outdentSelectedRows (options = {}) { + if (!this.ensureWritable('outdentSelectedRows', options)) return + return this.mutateSelectedText(selection => selection.outdentSelectedRows(options)) } // Extended: Get the indentation level of the given line of text. @@ -3585,13 +3765,21 @@ class TextEditor { // Extended: Indent rows intersecting selections based on the grammar's suggested // indent level. - autoIndentSelectedRows () { - return this.mutateSelectedText(selection => selection.autoIndentSelectedRows()) + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. + autoIndentSelectedRows (options = {}) { + if (!this.ensureWritable('autoIndentSelectedRows', options)) return + return this.mutateSelectedText(selection => selection.autoIndentSelectedRows(options)) } // Indent all lines intersecting selections. See {Selection::indent} for more // information. + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. indent (options = {}) { + if (!this.ensureWritable('indent', options)) return if (options.autoIndent == null) options.autoIndent = this.shouldAutoIndent() this.mutateSelectedText(selection => selection.indent(options)) } @@ -3729,14 +3917,18 @@ class TextEditor { } // Essential: For each selection, cut the selected text. - cutSelectedText () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. + cutSelectedText (options = {}) { + if (!this.ensureWritable('cutSelectedText', options)) return let maintainClipboard = false this.mutateSelectedText(selection => { if (selection.isEmpty()) { selection.selectLine() - selection.cut(maintainClipboard, true) + selection.cut(maintainClipboard, true, options.bypassReadOnly) } else { - selection.cut(maintainClipboard, false) + selection.cut(maintainClipboard, false, options.bypassReadOnly) } maintainClipboard = true }) @@ -3750,7 +3942,8 @@ class TextEditor { // corresponding clipboard selection text. // // * `options` (optional) See {Selection::insertText}. - pasteText (options) { + pasteText (options = {}) { + if (!this.ensureWritable('parseText', options)) return options = Object.assign({}, options) let {text: clipboardText, metadata} = this.constructor.clipboard.readWithMetadata() if (!this.emitWillInsertTextEvent(clipboardText)) return false @@ -3791,10 +3984,14 @@ class TextEditor { // Essential: For each selection, if the selection is empty, cut all characters // of the containing screen line following the cursor. Otherwise cut the selected // text. - cutToEndOfLine () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. + cutToEndOfLine (options = {}) { + if (!this.ensureWritable('cutToEndOfLine', options)) return let maintainClipboard = false this.mutateSelectedText(selection => { - selection.cutToEndOfLine(maintainClipboard) + selection.cutToEndOfLine(maintainClipboard, options) maintainClipboard = true }) } @@ -3802,10 +3999,14 @@ class TextEditor { // Essential: For each selection, if the selection is empty, cut all characters // of the containing buffer line following the cursor. Otherwise cut the // selected text. - cutToEndOfBufferLine () { + // + // * `options` (optional) {Object} + // * `bypassReadOnly` (optional) {Boolean} Must be `true` to modify a read-only editor. + cutToEndOfBufferLine (options = {}) { + if (!this.ensureWritable('cutToEndOfBufferLine', options)) return let maintainClipboard = false this.mutateSelectedText(selection => { - selection.cutToEndOfBufferLine(maintainClipboard) + selection.cutToEndOfBufferLine(maintainClipboard, options) maintainClipboard = true }) } @@ -3897,7 +4098,7 @@ class TextEditor { // Extended: Unfold all existing folds. unfoldAll () { const result = this.displayLayer.destroyAllFolds() - this.scrollToCursorPosition() + if (result.length > 0) this.scrollToCursorPosition() return result } @@ -4015,6 +4216,29 @@ class TextEditor { // window. (default: -100) // * `visible` (optional) {Boolean} specifying whether the gutter is visible // initially after being created. (default: true) + // * `type` (optional) {String} specifying the type of gutter to create. `'decorated'` + // gutters are useful as a destination for decorations created with {Gutter::decorateMarker}. + // `'line-number'` gutters. + // * `class` (optional) {String} added to the CSS classnames of the gutter's root DOM element. + // * `labelFn` (optional) {Function} called by a `'line-number'` gutter to generate the label for each line number + // element. Should return a {String} that will be used to label the corresponding line. + // * `lineData` an {Object} containing information about each line to label. + // * `bufferRow` {Number} indicating the zero-indexed buffer index of this line. + // * `screenRow` {Number} indicating the zero-indexed screen index. + // * `foldable` {Boolean} that is `true` if a fold may be created here. + // * `softWrapped` {Boolean} if this screen row is the soft-wrapped continuation of the same buffer row. + // * `maxDigits` {Number} the maximum number of digits necessary to represent any known screen row. + // * `onMouseDown` (optional) {Function} to be called when a mousedown event is received by a line-number + // element within this `type: 'line-number'` {Gutter}. If unspecified, the default behavior is to select the + // clicked buffer row. + // * `lineData` an {Object} containing information about the line that's being clicked. + // * `bufferRow` {Number} of the originating line element + // * `screenRow` {Number} + // * `onMouseMove` (optional) {Function} to be called when a mousemove event occurs on a line-number element within + // within this `type: 'line-number'` {Gutter}. + // * `lineData` an {Object} containing information about the line that's being clicked. + // * `bufferRow` {Number} of the originating line element + // * `screenRow` {Number} // // Returns the newly-created {Gutter}. addGutter (options) { @@ -4619,7 +4843,7 @@ class TextEditor { let endRow = bufferRow const rowCount = this.getLineCount() - while (endRow < rowCount) { + while (endRow + 1 < rowCount) { if (!NON_WHITESPACE_REGEXP.test(this.lineTextForBufferRow(endRow + 1))) break if (languageMode.isRowCommented(endRow + 1) !== isCommented) break endRow++ diff --git a/src/text-mate-language-mode.js b/src/text-mate-language-mode.js index 152636ab7..471af9af2 100644 --- a/src/text-mate-language-mode.js +++ b/src/text-mate-language-mode.js @@ -7,6 +7,7 @@ const ScopeDescriptor = require('./scope-descriptor') const NullGrammar = require('./null-grammar') const {OnigRegExp} = require('oniguruma') const {toFirstMateScopeId, fromFirstMateScopeId} = require('./first-mate-helpers') +const {selectorMatchesAnyScope} = require('./selectors') const NON_WHITESPACE_REGEX = /\S/ @@ -235,15 +236,18 @@ class TextMateLanguageMode { return this.buffer.getTextInRange([[0, 0], [10, 0]]) } - hasTokenForSelector (selector) { + updateForInjection (grammar) { + if (!grammar.injectionSelector) return for (const tokenizedLine of this.tokenizedLines) { if (tokenizedLine) { for (let token of tokenizedLine.tokens) { - if (selector.matches(token.scopes)) return true + if (grammar.injectionSelector.matches(token.scopes)) { + this.retokenizeLines() + return + } } } } - return false } retokenizeLines () { @@ -723,14 +727,6 @@ class TextMateLanguageMode { TextMateLanguageMode.prototype.chunkSize = 50 -function selectorMatchesAnyScope (selector, scopes) { - const targetClasses = selector.replace(/^\./, '').split('.') - return scopes.some((scope) => { - const scopeClasses = scope.split('.') - return _.isSubset(targetClasses, scopeClasses) - }) -} - class TextMateHighlightIterator { constructor (languageMode) { this.languageMode = languageMode diff --git a/src/tooltip-manager.js b/src/tooltip-manager.js index 34f96775b..07b4f196a 100644 --- a/src/tooltip-manager.js +++ b/src/tooltip-manager.js @@ -153,9 +153,11 @@ class TooltipManager { } window.addEventListener('resize', hideTooltip) + window.addEventListener('keydown', hideTooltip) const disposable = new Disposable(() => { window.removeEventListener('resize', hideTooltip) + window.removeEventListener('keydown', hideTooltip) hideTooltip() tooltip.destroy() diff --git a/src/tree-sitter-grammar.js b/src/tree-sitter-grammar.js index d00344fb1..fc572221a 100644 --- a/src/tree-sitter-grammar.js +++ b/src/tree-sitter-grammar.js @@ -6,12 +6,17 @@ module.exports = class TreeSitterGrammar { constructor (registry, filePath, params) { this.registry = registry - this.id = params.id this.name = params.name - this.legacyScopeName = params.legacyScopeName - if (params.contentRegExp) this.contentRegExp = new RegExp(params.contentRegExp) + this.scopeName = params.scopeName + + // TODO - Remove the `RegExp` spelling and only support `Regex`, once all of the existing + // Tree-sitter grammars are updated to spell it `Regex`. + this.contentRegex = buildRegex(params.contentRegex || params.contentRegExp) + this.injectionRegex = buildRegex(params.injectionRegex || params.injectionRegExp) + this.firstLineRegex = buildRegex(params.firstLineRegex) this.folds = params.folds || [] + this.folds.forEach(normalizeFoldSpecification) this.commentStrings = { commentStartString: params.comments && params.comments.start, @@ -20,14 +25,22 @@ class TreeSitterGrammar { const scopeSelectors = {} for (const key in params.scopes || {}) { - scopeSelectors[key] = params.scopes[key] - .split('.') - .map(s => `syntax--${s}`) - .join(' ') + const classes = toSyntaxClasses(params.scopes[key]) + const selectors = key.split(/,\s+/) + for (let selector of selectors) { + selector = selector.trim() + if (!selector) continue + if (scopeSelectors[selector]) { + scopeSelectors[selector] = [].concat(scopeSelectors[selector], classes) + } else { + scopeSelectors[selector] = classes + } + } } this.scopeMap = new SyntaxScopeMap(scopeSelectors) - this.fileTypes = params.fileTypes + this.fileTypes = params.fileTypes || [] + this.injectionPoints = params.injectionPoints || [] // TODO - When we upgrade to a new enough version of node, use `require.resolve` // with the new `paths` option instead of this private API. @@ -39,11 +52,16 @@ class TreeSitterGrammar { this.languageModule = require(languageModulePath) this.scopesById = new Map() + this.conciseScopesById = new Map() this.idsByScope = {} this.nextScopeId = 256 + 1 this.registration = null } + inspect () { + return `TreeSitterGrammar {scopeName: ${this.scopeName}}` + } + idForScope (scope) { let id = this.idsByScope[scope] if (!id) { @@ -58,8 +76,15 @@ class TreeSitterGrammar { return this.scopesById.get(id) } - get scopeName () { - return this.id + scopeNameForScopeId (id) { + let result = this.conciseScopesById.get(id) + if (!result) { + result = this.scopesById.get(id) + .slice('syntax--'.length) + .replace(/ syntax--/g, '.') + this.conciseScopesById.set(id, result) + } + return result } activate () { @@ -70,3 +95,56 @@ class TreeSitterGrammar { if (this.registration) this.registration.dispose() } } + +const toSyntaxClasses = scopes => + typeof scopes === 'string' + ? scopes + .split('.') + .map(s => `syntax--${s}`) + .join(' ') + : Array.isArray(scopes) + ? scopes.map(toSyntaxClasses) + : scopes.match + ? {match: new RegExp(scopes.match), scopes: toSyntaxClasses(scopes.scopes)} + : Object.assign({}, scopes, {scopes: toSyntaxClasses(scopes.scopes)}) + +const NODE_NAME_REGEX = /[\w_]+/ + +function matcherForSpec (spec) { + if (typeof spec === 'string') { + if (spec[0] === '"' && spec[spec.length - 1] === '"') { + return { + type: spec.substr(1, spec.length - 2), + named: false + } + } + + if (!NODE_NAME_REGEX.test(spec)) { + return {type: spec, named: false} + } + + return {type: spec, named: true} + } + return spec +} + +function normalizeFoldSpecification (spec) { + if (spec.type) { + if (Array.isArray(spec.type)) { + spec.matchers = spec.type.map(matcherForSpec) + } else { + spec.matchers = [matcherForSpec(spec.type)] + } + } + + if (spec.start) normalizeFoldSpecification(spec.start) + if (spec.end) normalizeFoldSpecification(spec.end) +} + +function buildRegex (value) { + // Allow multiple alternatives to be specified via an array, for + // readability of the grammar file + if (Array.isArray(value)) value = value.map(_ => `(${_})`).join('|') + if (typeof value === 'string') return new RegExp(value) + return null +} diff --git a/src/tree-sitter-language-mode.js b/src/tree-sitter-language-mode.js index 0d2fab8cf..05aeaaa2b 100644 --- a/src/tree-sitter-language-mode.js +++ b/src/tree-sitter-language-mode.js @@ -1,49 +1,117 @@ -const {Document} = require('tree-sitter') -const {Point, Range} = require('text-buffer') -const {Emitter, Disposable} = require('event-kit') +const Parser = require('tree-sitter') +const {Point, Range, spliceArray} = require('text-buffer') +const {Patch} = require('superstring') +const {Emitter} = require('event-kit') const ScopeDescriptor = require('./scope-descriptor') const TokenizedLine = require('./tokenized-line') const TextMateLanguageMode = require('./text-mate-language-mode') +const {matcherForSelector} = require('./selectors') let nextId = 0 +const MAX_RANGE = new Range(Point.ZERO, Point.INFINITY).freeze() +const PARSER_POOL = [] +const WORD_REGEX = /\w/ -module.exports = class TreeSitterLanguageMode { - constructor ({buffer, grammar, config}) { + static _patchSyntaxNode () { + if (!Parser.SyntaxNode.prototype.hasOwnProperty('range')) { + Object.defineProperty(Parser.SyntaxNode.prototype, 'range', { + get () { + return rangeForNode(this) + } + }) + } + } + + constructor ({buffer, grammar, config, grammars, syncOperationLimit}) { + TreeSitterLanguageMode._patchSyntaxNode() this.id = nextId++ this.buffer = buffer this.grammar = grammar this.config = config - this.document = new Document() - this.document.setInput(new TreeSitterTextBufferInput(buffer)) - this.document.setLanguage(grammar.languageModule) - this.document.parse() - this.rootScopeDescriptor = new ScopeDescriptor({scopes: [this.grammar.id]}) + this.grammarRegistry = grammars + this.parser = new Parser() + this.rootLanguageLayer = new LanguageLayer(this, grammar) + this.injectionsMarkerLayer = buffer.addMarkerLayer() + + if (syncOperationLimit != null) { + this.syncOperationLimit = syncOperationLimit + } + + this.rootScopeDescriptor = new ScopeDescriptor({scopes: [this.grammar.scopeName]}) this.emitter = new Emitter() this.isFoldableCache = [] + this.hasQueuedParse = false + + this.grammarForLanguageString = this.grammarForLanguageString.bind(this) + this.emitRangeUpdate = this.emitRangeUpdate.bind(this) + + this.subscription = this.buffer.onDidChangeText(({changes}) => { + for (let i = 0, {length} = changes; i < length; i++) { + const {oldRange, newRange} = changes[i] + spliceArray( + this.isFoldableCache, + newRange.start.row, + oldRange.end.row - oldRange.start.row, + {length: newRange.end.row - newRange.start.row} + ) + } + + this.rootLanguageLayer.update(null) + }) + + this.rootLanguageLayer.update(null).then(() => + this.emitter.emit('did-tokenize') + ) // TODO: Remove this once TreeSitterLanguageMode implements its own auto-indentation system. This // is temporarily needed in order to delegate to the TextMateLanguageMode's auto-indent system. this.regexesByPattern = {} } - getLanguageId () { - return this.grammar.id + destroy () { + this.injectionsMarkerLayer.destroy() + this.subscription.dispose() + this.rootLanguageLayer = null + this.parser = null } - bufferDidChange ({oldRange, newRange, oldText, newText}) { - const startRow = oldRange.start.row - const oldEndRow = oldRange.end.row - const newEndRow = newRange.end.row - this.isFoldableCache.splice(startRow, oldEndRow - startRow, ...new Array(newEndRow - startRow)) - this.document.edit({ - startIndex: this.buffer.characterIndexForPosition(oldRange.start), - lengthRemoved: oldText.length, - lengthAdded: newText.length, - startPosition: oldRange.start, - extentRemoved: oldRange.getExtent(), - extentAdded: newRange.getExtent() + getLanguageId () { + return this.grammar.scopeName + } + + bufferDidChange (change) { + this.rootLanguageLayer.handleTextChange(change) + for (const marker of this.injectionsMarkerLayer.getMarkers()) { + marker.languageLayer.handleTextChange(change) + } + } + + parse (language, oldTree, ranges) { + const parser = PARSER_POOL.pop() || new Parser() + parser.setLanguage(language) + const result = parser.parseTextBuffer(this.buffer.buffer, oldTree, { + syncOperationLimit: this.syncOperationLimit, + includedRanges: ranges }) + + if (result.then) { + return result.then(tree => { + PARSER_POOL.push(parser) + return tree + }) + } else { + PARSER_POOL.push(parser) + return result + } + } + + get tree () { + return this.rootLanguageLayer.tree + } + + updateForInjection (grammar) { + this.rootLanguageLayer.updateInjections(grammar) } /* @@ -51,17 +119,16 @@ class TreeSitterLanguageMode { */ buildHighlightIterator () { - const invalidatedRanges = this.document.parse() - for (let i = 0, n = invalidatedRanges.length; i < n; i++) { - const range = invalidatedRanges[i] - const startRow = range.start.row - const endRow = range.end.row - for (let row = startRow; row < endRow; row++) { - this.isFoldableCache[row] = undefined - } - this.emitter.emit('did-change-highlighting', range) - } - return new TreeSitterHighlightIterator(this) + if (!this.rootLanguageLayer) return new NullHighlightIterator() + const layerIterators = [ + this.rootLanguageLayer.buildHighlightIterator(), + ...this.injectionsMarkerLayer.getMarkers().map(m => m.languageLayer.buildHighlightIterator()) + ] + return new HighlightIterator(this, layerIterators) + } + + onDidTokenize (callback) { + return this.emitter.on('did-tokenize', callback) } onDidChangeHighlighting (callback) { @@ -80,7 +147,15 @@ class TreeSitterLanguageMode { return this.grammar.commentStrings } - isRowCommented () { + isRowCommented (row) { + const firstNonWhitespaceRange = this.buffer.findInRangeSync( + /\S/, + new Range(new Point(row, 0), new Point(row, Infinity)) + ) + if (firstNonWhitespaceRange) { + const firstNode = this.getSyntaxNodeContainingRange(firstNonWhitespaceRange) + if (firstNode) return firstNode.type.includes('comment') + } return false } @@ -137,13 +212,17 @@ class TreeSitterLanguageMode { return this.getFoldableRangesAtIndentLevel(null) } + /** + * TODO: Make this method generate folds for nested languages (currently, + * folds are only generated for the root language layer). + */ getFoldableRangesAtIndentLevel (goalLevel) { let result = [] - let stack = [{node: this.document.rootNode, level: 0}] + let stack = [{node: this.tree.rootNode, level: 0}] while (stack.length > 0) { const {node, level} = stack.pop() - const range = this.getFoldableRangeForNode(node) + const range = this.getFoldableRangeForNode(node, this.grammar) if (range) { if (goalLevel == null || level === goalLevel) { let updatedExistingRange = false @@ -183,54 +262,71 @@ class TreeSitterLanguageMode { } getFoldableRangeContainingPoint (point, tabLength, existenceOnly = false) { - let node = this.document.rootNode.descendantForPosition(this.buffer.clipPosition(point)) - while (node) { - if (existenceOnly && node.startPosition.row < point.row) break - if (node.endPosition.row > point.row) { - const range = this.getFoldableRangeForNode(node, existenceOnly) - if (range) return range + if (!this.tree) return null + + let smallestRange + this._forEachTreeWithRange(new Range(point, point), (tree, grammar) => { + let node = tree.rootNode.descendantForPosition(this.buffer.clipPosition(point)) + while (node) { + if (existenceOnly && node.startPosition.row < point.row) return + if (node.endPosition.row > point.row) { + const range = this.getFoldableRangeForNode(node, grammar) + if (range && rangeIsSmaller(range, smallestRange)) { + smallestRange = range + return + } + } + node = node.parent } - node = node.parent + }) + + return existenceOnly + ? smallestRange && smallestRange.start.row === point.row + : smallestRange + } + + _forEachTreeWithRange (range, callback) { + if (this.rootLanguageLayer.tree) { + callback(this.rootLanguageLayer.tree, this.rootLanguageLayer.grammar) + } + + const injectionMarkers = this.injectionsMarkerLayer.findMarkers({ + intersectsRange: range + }) + + for (const injectionMarker of injectionMarkers) { + const {tree, grammar} = injectionMarker.languageLayer + if (tree) callback(tree, grammar) } } - getFoldableRangeForNode (node, existenceOnly) { - const {children, type: nodeType} = node + getFoldableRangeForNode (node, grammar, existenceOnly) { + const {children} = node const childCount = children.length - let childTypes - for (var i = 0, {length} = this.grammar.folds; i < length; i++) { - const foldEntry = this.grammar.folds[i] + for (var i = 0, {length} = grammar.folds; i < length; i++) { + const foldSpec = grammar.folds[i] - if (foldEntry.type) { - if (typeof foldEntry.type === 'string') { - if (foldEntry.type !== nodeType) continue - } else { - if (!foldEntry.type.includes(nodeType)) continue - } - } + if (foldSpec.matchers && !hasMatchingFoldSpec(foldSpec.matchers, node)) continue let foldStart - const startEntry = foldEntry.start + const startEntry = foldSpec.start if (startEntry) { + let foldStartNode if (startEntry.index != null) { - const child = children[startEntry.index] - if (!child || (startEntry.type && startEntry.type !== child.type)) continue - foldStart = child.endPosition + foldStartNode = children[startEntry.index] + if (!foldStartNode || startEntry.matchers && !hasMatchingFoldSpec(startEntry.matchers, foldStartNode)) continue } else { - if (!childTypes) childTypes = children.map(child => child.type) - const index = typeof startEntry.type === 'string' - ? childTypes.indexOf(startEntry.type) - : childTypes.findIndex(type => startEntry.type.includes(type)) - if (index === -1) continue - foldStart = children[index].endPosition + foldStartNode = children.find(child => hasMatchingFoldSpec(startEntry.matchers, child)) + if (!foldStartNode) continue } + foldStart = new Point(foldStartNode.endPosition.row, Infinity) } else { foldStart = new Point(node.startPosition.row, Infinity) } let foldEnd - const endEntry = foldEntry.end + const endEntry = foldSpec.end if (endEntry) { let foldEndNode if (endEntry.index != null) { @@ -238,18 +334,17 @@ class TreeSitterLanguageMode { foldEndNode = children[index] if (!foldEndNode || (endEntry.type && endEntry.type !== foldEndNode.type)) continue } else { - if (!childTypes) childTypes = children.map(foldEndNode => foldEndNode.type) - const index = typeof endEntry.type === 'string' - ? childTypes.indexOf(endEntry.type) - : childTypes.findIndex(type => endEntry.type.includes(type)) - if (index === -1) continue - foldEndNode = children[index] + foldEndNode = children.find(child => hasMatchingFoldSpec(endEntry.matchers, child)) + if (!foldEndNode) continue } - if (foldEndNode.endIndex - foldEndNode.startIndex > 1 && foldEndNode.startPosition.row > foldStart.row) { - foldEnd = new Point(foldEndNode.startPosition.row - 1, Infinity) - } else { - foldEnd = foldEndNode.startPosition + if (foldEndNode.startPosition.row <= foldStart.row) continue + + foldEnd = foldEndNode.startPosition + if (this.buffer.findInRangeSync( + WORD_REGEX, new Range(foldEnd, new Point(foldEnd.row, Infinity)) + )) { + foldEnd = new Point(foldEnd.row - 1, Infinity) } } else { const {endPosition} = node @@ -267,29 +362,52 @@ class TreeSitterLanguageMode { } /* - Syntax Tree APIs + Section - Syntax Tree APIs */ - getRangeForSyntaxNodeContainingRange (range) { + getSyntaxNodeContainingRange (range, where = _ => true) { const startIndex = this.buffer.characterIndexForPosition(range.start) const endIndex = this.buffer.characterIndexForPosition(range.end) - let node = this.document.rootNode.descendantForIndex(startIndex, endIndex - 1) - while (node && node.startIndex === startIndex && node.endIndex === endIndex) { - node = node.parent - } - if (node) return new Range(node.startPosition, node.endPosition) + const searchEndIndex = Math.max(0, endIndex - 1) + + let smallestNode + this._forEachTreeWithRange(range, tree => { + let node = tree.rootNode.descendantForIndex(startIndex, searchEndIndex) + while (node) { + if (nodeContainsIndices(node, startIndex, endIndex) && where(node)) { + if (nodeIsSmaller(node, smallestNode)) smallestNode = node + break + } + node = node.parent + } + }) + + return smallestNode } - bufferRangeForScopeAtPosition (position) { - return this.getRangeForSyntaxNodeContainingRange(new Range(position, position)) + getRangeForSyntaxNodeContainingRange (range, where) { + const node = this.getSyntaxNodeContainingRange(range, where) + return node && node.range + } + + getSyntaxNodeAtPosition (position, where) { + return this.getSyntaxNodeContainingRange(new Range(position, position), where) + } + + bufferRangeForScopeAtPosition (selector, position) { + if (typeof selector === 'string') { + const match = matcherForSelector(selector) + selector = ({type}) => match(type) + } + if (selector === null) selector = undefined + const node = this.getSyntaxNodeAtPosition(position, selector) + return node && node.range } /* Section - Backward compatibility shims */ - onDidTokenize (callback) { return new Disposable(() => {}) } - tokenizedLineForRow (row) { return new TokenizedLine({ openScopes: [], @@ -303,52 +421,346 @@ class TreeSitterLanguageMode { } scopeDescriptorForPosition (point) { - point = Point.fromObject(point) - const result = [] - let node = this.document.rootNode.descendantForPosition(point) - - // Don't include anonymous token types like '(' because they prevent scope chains - // from being parsed as CSS selectors by the `slick` parser. Other css selector - // parsers like `postcss-selector-parser` do allow arbitrary quoted strings in - // selectors. - if (!node.isNamed) node = node.parent - - while (node) { - result.push(node.type) - node = node.parent + const iterator = this.buildHighlightIterator() + const scopes = [] + for (const scope of iterator.seek(point)) { + scopes.push(this.grammar.scopeNameForScopeId(scope, false)) } - result.push(this.grammar.id) - return new ScopeDescriptor({scopes: result.reverse()}) - } - - hasTokenForSelector (scopeSelector) { - return false + for (const scope of iterator.getOpenScopeIds()) { + scopes.push(this.grammar.scopeNameForScopeId(scope, false)) + } + if (scopes.length === 0 || scopes[0] !== this.grammar.scopeName) { + scopes.unshift(this.grammar.scopeName) + } + return new ScopeDescriptor({scopes}) } getGrammar () { return this.grammar } + + /* + Section - Private + */ + + grammarForLanguageString (languageString) { + return this.grammarRegistry.treeSitterGrammarForLanguageString(languageString) + } + + emitRangeUpdate (range) { + const startRow = range.start.row + const endRow = range.end.row + for (let row = startRow; row < endRow; row++) { + this.isFoldableCache[row] = undefined + } + this.emitter.emit('did-change-highlighting', range) + } } -class TreeSitterHighlightIterator { - constructor (layer, document) { - this.layer = layer +class LanguageLayer { + constructor (languageMode, grammar, contentChildTypes) { + this.languageMode = languageMode + this.grammar = grammar + this.tree = null + this.currentParsePromise = null + this.patchSinceCurrentParseStarted = null + this.contentChildTypes = contentChildTypes + } - // Conceptually, the iterator represents a single position in the text. It stores this - // position both as a character index and as a `Point`. This position corresponds to a - // leaf node of the syntax tree, which either contains or follows the iterator's - // textual position. The `currentNode` property represents that leaf node, and - // `currentChildIndex` represents the child index of that leaf node within its parent. - this.currentIndex = null - this.currentPosition = null - this.currentNode = null - this.currentChildIndex = null + buildHighlightIterator () { + if (this.tree) { + return new LayerHighlightIterator(this, this.tree.walk()) + } else { + return new NullHighlightIterator() + } + } + + handleTextChange ({oldRange, newRange, oldText, newText}) { + if (this.tree) { + this.tree.edit(this._treeEditForBufferChange( + oldRange.start, oldRange.end, newRange.end, oldText, newText + )) + + if (this.editedRange) { + if (newRange.start.isLessThan(this.editedRange.start)) { + this.editedRange.start = newRange.start + } + if (oldRange.end.isLessThan(this.editedRange.end)) { + this.editedRange.end = newRange.end.traverse(this.editedRange.end.traversalFrom(oldRange.end)) + } else { + this.editedRange.end = newRange.end + } + } else { + this.editedRange = newRange.copy() + } + } + + if (this.patchSinceCurrentParseStarted) { + this.patchSinceCurrentParseStarted.splice( + oldRange.start, + oldRange.end, + newRange.end, + oldText, + newText + ) + } + } + + destroy () { + for (const marker of this.languageMode.injectionsMarkerLayer.getMarkers()) { + if (marker.parentLanguageLayer === this) { + marker.languageLayer.destroy() + marker.destroy() + } + } + } + + async update (nodeRangeSet) { + if (!this.currentParsePromise) { + do { + const params = {async: false} + this.currentParsePromise = this._performUpdate(nodeRangeSet, params) + if (!params.async) break + await this.currentParsePromise + } while (this.tree && this.tree.rootNode.hasChanges()) + this.currentParsePromise = null + } + } + + updateInjections (grammar) { + if (grammar.injectionRegex) { + if (!this.currentParsePromise) this.currentParsePromise = Promise.resolve() + this.currentParsePromise = this.currentParsePromise.then(async () => { + await this._populateInjections(MAX_RANGE, null) + this.currentParsePromise = null + }) + } + } + + async _performUpdate (nodeRangeSet, params) { + let includedRanges = null + if (nodeRangeSet) { + includedRanges = nodeRangeSet.getRanges() + if (includedRanges.length === 0) { + this.tree = null + return + } + } + + let affectedRange = this.editedRange + this.editedRange = null + + this.patchSinceCurrentParseStarted = new Patch() + let tree = this.languageMode.parse( + this.grammar.languageModule, + this.tree, + includedRanges + ) + if (tree.then) { + params.async = true + tree = await tree + } + tree.buffer = this.languageMode.buffer + + const changes = this.patchSinceCurrentParseStarted.getChanges() + this.patchSinceCurrentParseStarted = null + for (let i = changes.length - 1; i >= 0; i--) { + const {oldStart, oldEnd, newEnd, oldText, newText} = changes[i] + tree.edit(this._treeEditForBufferChange( + oldStart, oldEnd, newEnd, oldText, newText + )) + } + + if (this.tree) { + const rangesWithSyntaxChanges = this.tree.getChangedRanges(tree) + this.tree = tree + + if (!affectedRange) return + if (rangesWithSyntaxChanges.length > 0) { + for (const range of rangesWithSyntaxChanges) { + this.languageMode.emitRangeUpdate(rangeForNode(range)) + } + + affectedRange = affectedRange.union(new Range( + rangesWithSyntaxChanges[0].startPosition, + last(rangesWithSyntaxChanges).endPosition + )) + } else { + this.languageMode.emitRangeUpdate(affectedRange) + } + } else { + this.tree = tree + this.languageMode.emitRangeUpdate(rangeForNode(tree.rootNode)) + if (includedRanges) { + affectedRange = new Range(includedRanges[0].startPosition, last(includedRanges).endPosition) + } else { + affectedRange = MAX_RANGE + } + } + + const injectionPromise = this._populateInjections(affectedRange, nodeRangeSet) + if (injectionPromise) { + params.async = true + return injectionPromise + } + } + + _populateInjections (range, nodeRangeSet) { + const {injectionsMarkerLayer, grammarForLanguageString} = this.languageMode + + const existingInjectionMarkers = injectionsMarkerLayer + .findMarkers({intersectsRange: range}) + .filter(marker => marker.parentLanguageLayer === this) + + if (existingInjectionMarkers.length > 0) { + range = range.union(new Range( + existingInjectionMarkers[0].getRange().start, + last(existingInjectionMarkers).getRange().end + )) + } + + const markersToUpdate = new Map() + for (const injectionPoint of this.grammar.injectionPoints) { + const nodes = this.tree.rootNode.descendantsOfType( + injectionPoint.type, + range.start, + range.end + ) + + for (const node of nodes) { + const languageName = injectionPoint.language(node) + if (!languageName) continue + + const grammar = grammarForLanguageString(languageName) + if (!grammar) continue + + const contentNodes = injectionPoint.content(node) + if (!contentNodes) continue + + const injectionNodes = [].concat(contentNodes) + if (!injectionNodes.length) continue + + const injectionRange = rangeForNode(node) + let marker = existingInjectionMarkers.find(m => + m.getRange().isEqual(injectionRange) && + m.languageLayer.grammar === grammar + ) + if (!marker) { + marker = injectionsMarkerLayer.markRange(injectionRange) + marker.languageLayer = new LanguageLayer(this.languageMode, grammar, injectionPoint.contentChildTypes) + marker.parentLanguageLayer = this + } + + markersToUpdate.set(marker, new NodeRangeSet(nodeRangeSet, injectionNodes)) + } + } + + for (const marker of existingInjectionMarkers) { + if (!markersToUpdate.has(marker)) { + marker.languageLayer.destroy() + this.languageMode.emitRangeUpdate(marker.getRange()) + marker.destroy() + } + } + + if (markersToUpdate.size > 0) { + this.lastUpdateWasAsync = true + const promises = [] + for (const [marker, nodeRangeSet] of markersToUpdate) { + promises.push(marker.languageLayer.update(nodeRangeSet)) + } + return Promise.all(promises) + } + } + + _treeEditForBufferChange (start, oldEnd, newEnd, oldText, newText) { + const startIndex = this.languageMode.buffer.characterIndexForPosition(start) + return { + startIndex, + oldEndIndex: startIndex + oldText.length, + newEndIndex: startIndex + newText.length, + startPosition: start, + oldEndPosition: oldEnd, + newEndPosition: newEnd + } + } +} + +class HighlightIterator { + constructor (languageMode, iterators) { + this.languageMode = languageMode + this.iterators = iterators.sort((a, b) => b.getIndex() - a.getIndex()) + } + + seek (targetPosition) { + const containingTags = [] + const containingTagStartIndices = [] + const targetIndex = this.languageMode.buffer.characterIndexForPosition(targetPosition) + for (let i = this.iterators.length - 1; i >= 0; i--) { + this.iterators[i].seek(targetIndex, containingTags, containingTagStartIndices) + } + this.iterators.sort((a, b) => b.getIndex() - a.getIndex()) + return containingTags + } + + moveToSuccessor () { + const lastIndex = this.iterators.length - 1 + const leader = this.iterators[lastIndex] + leader.moveToSuccessor() + const leaderCharIndex = leader.getIndex() + let i = lastIndex + while (i > 0 && this.iterators[i - 1].getIndex() < leaderCharIndex) i-- + if (i < lastIndex) this.iterators.splice(i, 0, this.iterators.pop()) + } + + getPosition () { + return last(this.iterators).getPosition() + } + + getCloseScopeIds () { + return last(this.iterators).getCloseScopeIds() + } + + getOpenScopeIds () { + return last(this.iterators).getOpenScopeIds() + } + + logState () { + const iterator = last(this.iterators) + if (iterator.treeCursor) { + console.log( + iterator.getPosition(), + iterator.treeCursor.nodeType, + new Range( + iterator.languageLayer.tree.rootNode.startPosition, + iterator.languageLayer.tree.rootNode.endPosition + ).toString() + ) + console.log('close', iterator.closeTags.map(id => this.shortClassNameForScopeId(id))) + console.log('open', iterator.openTags.map(id => this.shortClassNameForScopeId(id))) + } + } + + shortClassNameForScopeId (id) { + return this.languageMode.classNameForScopeId(id).replace(/syntax--/g, '') + } +} + +class LayerHighlightIterator { + constructor (languageLayer, treeCursor) { + this.languageLayer = languageLayer + + // The iterator is always positioned at either the start or the end of some node + // in the syntax tree. + this.atEnd = false + this.treeCursor = treeCursor // In order to determine which selectors match its current node, the iterator maintains // a list of the current node's ancestors. Because the selectors can use the `:nth-child` // pseudo-class, each node's child index is also stored. this.containingNodeTypes = [] this.containingNodeChildIndices = [] + this.containingNodeEndIndices = [] // At any given position, the iterator exposes the list of class names that should be // *ended* at its current position and the list of class names that should be *started* @@ -357,42 +769,57 @@ class TreeSitterHighlightIterator { this.openTags = [] } - seek (targetPosition) { - const containingTags = [] + seek (targetIndex, containingTags, containingTagStartIndices) { + while (this.treeCursor.gotoParent()) {} + this.done = false + this.atEnd = true this.closeTags.length = 0 this.openTags.length = 0 this.containingNodeTypes.length = 0 this.containingNodeChildIndices.length = 0 - this.currentPosition = targetPosition - this.currentIndex = this.layer.buffer.characterIndexForPosition(targetPosition) + this.containingNodeEndIndices.length = 0 - var node = this.layer.document.rootNode - var childIndex = -1 - var nodeContainsTarget = true + const containingTagEndIndices = [] + + if (targetIndex >= this.treeCursor.endIndex) { + this.done = true + return + } + + let childIndex = -1 for (;;) { - this.currentNode = node - this.currentChildIndex = childIndex - if (!nodeContainsTarget) break - this.containingNodeTypes.push(node.type) + this.containingNodeTypes.push(this.treeCursor.nodeType) this.containingNodeChildIndices.push(childIndex) + this.containingNodeEndIndices.push(this.treeCursor.endIndex) - const scopeName = this.currentScopeName() - if (scopeName) { - const id = this.layer.grammar.idForScope(scopeName) - if (this.currentIndex === node.startIndex) { - this.openTags.push(id) + const scopeId = this._currentScopeId() + if (scopeId) { + if (this.treeCursor.startIndex < targetIndex) { + insertContainingTag( + scopeId, this.treeCursor.startIndex, + containingTags, containingTagStartIndices + ) + containingTagEndIndices.push(this.treeCursor.endIndex) } else { - containingTags.push(id) + this.atEnd = false + this.openTags.push(scopeId) + this._moveDown() + break } } - node = node.firstChildForIndex(this.currentIndex) - if (node) { - if (node.startIndex > this.currentIndex) nodeContainsTarget = false - childIndex = node.childIndex - } else { - break + childIndex = this.treeCursor.gotoFirstChildForIndex(targetIndex) + if (childIndex === null) break + if (this.treeCursor.startIndex >= targetIndex) this.atEnd = false + } + + if (this.atEnd) { + const currentIndex = this.treeCursor.endIndex + for (let i = 0, {length} = containingTags; i < length; i++) { + if (containingTagEndIndices[i] === currentIndex) { + this.closeTags.push(containingTags[i]) + } } } @@ -403,48 +830,45 @@ class TreeSitterHighlightIterator { this.closeTags.length = 0 this.openTags.length = 0 - if (!this.currentNode) { - this.currentPosition = {row: Infinity, column: Infinity} - return false - } - - do { - if (this.currentIndex < this.currentNode.startIndex) { - this.currentIndex = this.currentNode.startIndex - this.currentPosition = this.currentNode.startPosition - this.pushOpenTag() - this.descendLeft() - } else if (this.currentIndex < this.currentNode.endIndex) { - while (true) { - this.currentIndex = this.currentNode.endIndex - this.currentPosition = this.currentNode.endPosition - this.pushCloseTag() - - const {nextSibling} = this.currentNode - if (nextSibling && nextSibling.endIndex > this.currentIndex) { - this.currentNode = nextSibling - this.currentChildIndex++ - if (this.currentIndex === nextSibling.startIndex) { - this.pushOpenTag() - this.descendLeft() - } - break - } else { - this.currentNode = this.currentNode.parent - this.currentChildIndex = last(this.containingNodeChildIndices) - if (!this.currentNode) break - } + while (!this.done && !this.closeTags.length && !this.openTags.length) { + if (this.atEnd) { + if (this._moveRight()) { + const scopeId = this._currentScopeId() + if (scopeId) this.openTags.push(scopeId) + this.atEnd = false + this._moveDown() + } else if (this._moveUp(true)) { + this.atEnd = true + } else { + this.done = true } - } else { - this.currentNode = this.currentNode.nextSibling + } else if (!this._moveDown()) { + const scopeId = this._currentScopeId() + if (scopeId) this.closeTags.push(scopeId) + this.atEnd = true + this._moveUp(false) } - } while (this.closeTags.length === 0 && this.openTags.length === 0 && this.currentNode) - - return true + } } getPosition () { - return this.currentPosition + if (this.done) { + return Point.INFINITY + } else if (this.atEnd) { + return this.treeCursor.endPosition + } else { + return this.treeCursor.startPosition + } + } + + getIndex () { + if (this.done) { + return Infinity + } else if (this.atEnd) { + return this.treeCursor.endIndex + } else { + return this.treeCursor.startIndex + } } getCloseScopeIds () { @@ -456,67 +880,219 @@ class TreeSitterHighlightIterator { } // Private methods + _moveUp (atLastChild) { + let result = false + const {endIndex} = this.treeCursor + let depth = this.containingNodeEndIndices.length - descendLeft () { - let child - while ((child = this.currentNode.firstChild) && this.currentIndex === child.startIndex) { - this.currentNode = child - this.currentChildIndex = 0 - this.pushOpenTag() + // The iterator should not move up until it has visited all of the children of this node. + while (depth > 1 && (atLastChild || this.containingNodeEndIndices[depth - 2] === endIndex)) { + atLastChild = false + result = true + this.treeCursor.gotoParent() + this.containingNodeTypes.pop() + this.containingNodeChildIndices.pop() + this.containingNodeEndIndices.pop() + --depth + const scopeId = this._currentScopeId() + if (scopeId) this.closeTags.push(scopeId) + } + return result + } + + _moveDown () { + let result = false + const {startIndex} = this.treeCursor + + // Once the iterator has found a scope boundary, it needs to stay at the same + // position, so it should not move down if the first child node starts later than the + // current node. + while (this.treeCursor.gotoFirstChild()) { + if ((this.closeTags.length || this.openTags.length) && + this.treeCursor.startIndex > startIndex) { + this.treeCursor.gotoParent() + break + } + + result = true + this.containingNodeTypes.push(this.treeCursor.nodeType) + this.containingNodeChildIndices.push(0) + this.containingNodeEndIndices.push(this.treeCursor.endIndex) + + const scopeId = this._currentScopeId() + if (scopeId) this.openTags.push(scopeId) + } + + return result + } + + _moveRight () { + if (this.treeCursor.gotoNextSibling()) { + const depth = this.containingNodeTypes.length + this.containingNodeTypes[depth - 1] = this.treeCursor.nodeType + this.containingNodeChildIndices[depth - 1]++ + this.containingNodeEndIndices[depth - 1] = this.treeCursor.endIndex + return true } } - currentScopeName () { - return this.layer.grammar.scopeMap.get( + _currentScopeId () { + const rules = this.languageLayer.grammar.scopeMap.get( this.containingNodeTypes, this.containingNodeChildIndices, - this.currentNode.isNamed + this.treeCursor.nodeIsNamed ) - } - - pushCloseTag () { - const scopeName = this.currentScopeName() - if (scopeName) this.closeTags.push(this.layer.grammar.idForScope(scopeName)) - this.containingNodeTypes.pop() - this.containingNodeChildIndices.pop() - } - - pushOpenTag () { - this.containingNodeTypes.push(this.currentNode.type) - this.containingNodeChildIndices.push(this.currentChildIndex) - const scopeName = this.currentScopeName() - if (scopeName) this.openTags.push(this.layer.grammar.idForScope(scopeName)) + const scopes = applyLeafRules(rules, this.treeCursor) + if (scopes) { + return this.languageLayer.languageMode.grammar.idForScope(scopes) + } } } -class TreeSitterTextBufferInput { - constructor (buffer) { - this.buffer = buffer - this.position = {row: 0, column: 0} - this.isBetweenCRLF = false - } - - seek (offset, position) { - this.position = position - this.isBetweenCRLF = this.position.column > this.buffer.lineLengthForRow(this.position.row) - } - - read () { - const endPosition = this.buffer.clipPosition(new Point(this.position.row + 1000, 0)) - let text = this.buffer.getTextInRange([this.position, endPosition]) - if (this.isBetweenCRLF) { - text = text.slice(1) - this.isBetweenCRLF = false +const applyLeafRules = (rules, cursor) => { + if (!rules || typeof rules === 'string') return rules + if (Array.isArray(rules)) { + for (let i = 0, {length} = rules; i !== length; ++i) { + const result = applyLeafRules(rules[i], cursor) + if (result) return result } - this.position = endPosition - return text + return undefined } + if (typeof rules === 'object') { + if (rules.exact) { + return cursor.nodeText === rules.exact + ? applyLeafRules(rules.scopes, cursor) + : undefined + } + if (rules.match) { + return rules.match.test(cursor.nodeText) + ? applyLeafRules(rules.scopes, cursor) + : undefined + } + } +} + +class NullHighlightIterator { + seek () { return [] } + moveToSuccessor () {} + getIndex () { return Infinity } + getPosition () { return Point.INFINITY } + getOpenScopeIds () { return [] } + getCloseScopeIds () { return [] } +} + +class NodeRangeSet { + constructor (previous, nodes) { + this.previous = previous + this.nodes = nodes + } + + getRanges () { + const previousRanges = this.previous && this.previous.getRanges() + const result = [] + + for (const node of this.nodes) { + let position = node.startPosition + let index = node.startIndex + + for (const child of node.children) { + const nextPosition = child.startPosition + const nextIndex = child.startIndex + if (nextIndex > index) { + this._pushRange(previousRanges, result, { + startIndex: index, + endIndex: nextIndex, + startPosition: position, + endPosition: nextPosition + }) + } + position = child.endPosition + index = child.endIndex + } + + if (node.endIndex > index) { + this._pushRange(previousRanges, result, { + startIndex: index, + endIndex: node.endIndex, + startPosition: position, + endPosition: node.endPosition + }) + } + } + + return result + } + + _pushRange (previousRanges, newRanges, newRange) { + if (!previousRanges) { + newRanges.push(newRange) + return + } + + for (const previousRange of previousRanges) { + if (previousRange.endIndex <= newRange.startIndex) continue + if (previousRange.startIndex >= newRange.endIndex) break + newRanges.push({ + startIndex: Math.max(previousRange.startIndex, newRange.startIndex), + endIndex: Math.min(previousRange.endIndex, newRange.endIndex), + startPosition: Point.max(previousRange.startPosition, newRange.startPosition), + endPosition: Point.min(previousRange.endPosition, newRange.endPosition) + }) + } + } +} + +function insertContainingTag (tag, index, tags, indices) { + const i = indices.findIndex(existingIndex => existingIndex > index) + if (i === -1) { + tags.push(tag) + indices.push(index) + } else { + tags.splice(i, 0, tag) + indices.splice(i, 0, index) + } +} + +// Return true iff `mouse` is smaller than `house`. Only correct if +// mouse and house overlap. +// +// * `mouse` {Range} +// * `house` {Range} +function rangeIsSmaller (mouse, house) { + if (!house) return true + const mvec = vecFromRange(mouse) + const hvec = vecFromRange(house) + return Point.min(mvec, hvec) === mvec +} + +function vecFromRange ({start, end}) { + return end.translate(start.negate()) +} + +function rangeForNode (node) { + return new Range(node.startPosition, node.endPosition) +} + +function nodeContainsIndices (node, start, end) { + if (node.startIndex < start) return node.endIndex >= end + if (node.startIndex === start) return node.endIndex > end + return false +} + +function nodeIsSmaller (left, right) { + if (!left) return false + if (!right) return true + return left.endIndex - left.startIndex < right.endIndex - right.startIndex } function last (array) { return array[array.length - 1] } +function hasMatchingFoldSpec (specs, node) { + return specs.some(({type, named}) => type === node.type && named === node.isNamed) +} + // TODO: Remove this once TreeSitterLanguageMode implements its own auto-indent system. [ '_suggestedIndentForLineWithScopeAtBufferRow', @@ -524,7 +1100,13 @@ function last (array) { 'increaseIndentRegexForScopeDescriptor', 'decreaseIndentRegexForScopeDescriptor', 'decreaseNextIndentRegexForScopeDescriptor', - 'regexForPattern' + 'regexForPattern', + 'getNonWordCharacters' ].forEach(methodName => { - module.exports.prototype[methodName] = TextMateLanguageMode.prototype[methodName] + TreeSitterLanguageMode.prototype[methodName] = TextMateLanguageMode.prototype[methodName] }) + +TreeSitterLanguageMode.LanguageLayer = LanguageLayer +TreeSitterLanguageMode.prototype.syncOperationLimit = 1000 + +module.exports = TreeSitterLanguageMode diff --git a/src/update-process-env.js b/src/update-process-env.js index 6dab00a7d..20d937d96 100644 --- a/src/update-process-env.js +++ b/src/update-process-env.js @@ -18,7 +18,7 @@ async function updateProcessEnv (launchEnv) { if (launchEnv) { if (shouldGetEnvFromShell(launchEnv)) { envToAssign = await getEnvFromShell(launchEnv) - } else if (launchEnv.PWD) { + } else if (launchEnv.PWD || launchEnv.PROMPT || launchEnv.PSModulePath) { envToAssign = launchEnv } } diff --git a/src/workspace-element.js b/src/workspace-element.js index 5531aafdf..f94dbd6e9 100644 --- a/src/workspace-element.js +++ b/src/workspace-element.js @@ -310,7 +310,7 @@ class WorkspaceElement extends HTMLElement { } } - runPackageSpecs () { + runPackageSpecs (options = {}) { const activePaneItem = this.model.getActivePaneItem() const activePath = activePaneItem && typeof activePaneItem.getPath === 'function' ? activePaneItem.getPath() : null let projectPath @@ -326,7 +326,7 @@ class WorkspaceElement extends HTMLElement { specPath = testPath } - ipcRenderer.send('run-package-specs', specPath) + ipcRenderer.send('run-package-specs', specPath, options) } } diff --git a/src/workspace.js b/src/workspace.js index de51651ec..a3f85ddeb 100644 --- a/src/workspace.js +++ b/src/workspace.js @@ -225,6 +225,8 @@ module.exports = class Workspace extends Model { modal: new PanelContainer({viewRegistry: this.viewRegistry, location: 'modal'}) } + this.incoming = new Map() + this.subscribeToEvents() } @@ -495,14 +497,22 @@ module.exports = class Workspace extends Model { if (item instanceof TextEditor) { const subscriptions = new CompositeDisposable( this.textEditorRegistry.add(item), - this.textEditorRegistry.maintainConfig(item), - item.observeGrammar(this.handleGrammarUsed.bind(this)) + this.textEditorRegistry.maintainConfig(item) ) if (!this.project.findBufferForId(item.buffer.id)) { this.project.addBuffer(item.buffer) } item.onDidDestroy(() => { subscriptions.dispose() }) this.emitter.emit('did-add-text-editor', {textEditor: item, pane, index}) + // It's important to call handleGrammarUsed after emitting the did-add event: + // if we activate a package between adding the editor to the registry and emitting + // the package may receive the editor twice from `observeTextEditors`. + // (Note that the item can be destroyed by an `observeTextEditors` handler.) + if (!item.isDestroyed()) { + subscriptions.add( + item.observeGrammar(this.handleGrammarUsed.bind(this)) + ) + } } }) } @@ -921,133 +931,150 @@ module.exports = class Workspace extends Model { if (typeof item.getURI === 'function') uri = item.getURI() } - if (!atom.config.get('core.allowPendingPaneItems')) { - options.pending = false - } - - // Avoid adding URLs as recent documents to work-around this Spotlight crash: - // https://github.com/atom/atom/issues/10071 - if (uri && (!url.parse(uri).protocol || process.platform === 'win32')) { - this.applicationDelegate.addRecentDocument(uri) - } - - let pane, itemExistsInWorkspace - - // Try to find an existing item in the workspace. - if (item || uri) { - if (options.pane) { - pane = options.pane - } else if (options.searchAllPanes) { - pane = item ? this.paneForItem(item) : this.paneForURI(uri) + let resolveItem = () => {} + if (uri) { + const incomingItem = this.incoming.get(uri) + if (!incomingItem) { + this.incoming.set(uri, new Promise(resolve => { resolveItem = resolve })) } else { - // If an item with the given URI is already in the workspace, assume - // that item's pane container is the preferred location for that URI. - let container - if (uri) container = this.paneContainerForURI(uri) - if (!container) container = this.getActivePaneContainer() + await incomingItem + } + } - // The `split` option affects where we search for the item. - pane = container.getActivePane() - switch (options.split) { - case 'left': - pane = pane.findLeftmostSibling() - break - case 'right': - pane = pane.findRightmostSibling() - break - case 'up': - pane = pane.findTopmostSibling() - break - case 'down': - pane = pane.findBottommostSibling() - break - } + try { + if (!atom.config.get('core.allowPendingPaneItems')) { + options.pending = false } - if (pane) { - if (item) { - itemExistsInWorkspace = pane.getItems().includes(item) + // Avoid adding URLs as recent documents to work-around this Spotlight crash: + // https://github.com/atom/atom/issues/10071 + if (uri && (!url.parse(uri).protocol || process.platform === 'win32')) { + this.applicationDelegate.addRecentDocument(uri) + } + + let pane, itemExistsInWorkspace + + // Try to find an existing item in the workspace. + if (item || uri) { + if (options.pane) { + pane = options.pane + } else if (options.searchAllPanes) { + pane = item ? this.paneForItem(item) : this.paneForURI(uri) } else { - item = pane.itemForURI(uri) - itemExistsInWorkspace = item != null + // If an item with the given URI is already in the workspace, assume + // that item's pane container is the preferred location for that URI. + let container + if (uri) container = this.paneContainerForURI(uri) + if (!container) container = this.getActivePaneContainer() + + // The `split` option affects where we search for the item. + pane = container.getActivePane() + switch (options.split) { + case 'left': + pane = pane.findLeftmostSibling() + break + case 'right': + pane = pane.findRightmostSibling() + break + case 'up': + pane = pane.findTopmostSibling() + break + case 'down': + pane = pane.findBottommostSibling() + break + } + } + + if (pane) { + if (item) { + itemExistsInWorkspace = pane.getItems().includes(item) + } else { + item = pane.itemForURI(uri) + itemExistsInWorkspace = item != null + } } } - } - // If we already have an item at this stage, we won't need to do an async - // lookup of the URI, so we yield the event loop to ensure this method - // is consistently asynchronous. - if (item) await Promise.resolve() + // If we already have an item at this stage, we won't need to do an async + // lookup of the URI, so we yield the event loop to ensure this method + // is consistently asynchronous. + if (item) await Promise.resolve() - if (!itemExistsInWorkspace) { - item = item || await this.createItemForURI(uri, options) - if (!item) return + if (!itemExistsInWorkspace) { + item = item || await this.createItemForURI(uri, options) + if (!item) return - if (options.pane) { - pane = options.pane + if (options.pane) { + pane = options.pane + } else { + let location = options.location + if (!location && !options.split && uri && this.enablePersistence) { + location = await this.itemLocationStore.load(uri) + } + if (!location && typeof item.getDefaultLocation === 'function') { + location = item.getDefaultLocation() + } + + const allowedLocations = typeof item.getAllowedLocations === 'function' ? item.getAllowedLocations() : ALL_LOCATIONS + location = allowedLocations.includes(location) ? location : allowedLocations[0] + + const container = this.paneContainers[location] || this.getCenter() + pane = container.getActivePane() + switch (options.split) { + case 'left': + pane = pane.findLeftmostSibling() + break + case 'right': + pane = pane.findOrCreateRightmostSibling() + break + case 'up': + pane = pane.findTopmostSibling() + break + case 'down': + pane = pane.findOrCreateBottommostSibling() + break + } + } + } + + if (!options.pending && (pane.getPendingItem() === item)) { + pane.clearPendingItem() + } + + this.itemOpened(item) + + if (options.activateItem === false) { + pane.addItem(item, {pending: options.pending}) } else { - let location = options.location - if (!location && !options.split && uri && this.enablePersistence) { - location = await this.itemLocationStore.load(uri) - } - if (!location && typeof item.getDefaultLocation === 'function') { - location = item.getDefaultLocation() - } + pane.activateItem(item, {pending: options.pending}) + } - const allowedLocations = typeof item.getAllowedLocations === 'function' ? item.getAllowedLocations() : ALL_LOCATIONS - location = allowedLocations.includes(location) ? location : allowedLocations[0] + if (options.activatePane !== false) { + pane.activate() + } - const container = this.paneContainers[location] || this.getCenter() - pane = container.getActivePane() - switch (options.split) { - case 'left': - pane = pane.findLeftmostSibling() - break - case 'right': - pane = pane.findOrCreateRightmostSibling() - break - case 'up': - pane = pane.findTopmostSibling() - break - case 'down': - pane = pane.findOrCreateBottommostSibling() - break + let initialColumn = 0 + let initialLine = 0 + if (!Number.isNaN(options.initialLine)) { + initialLine = options.initialLine + } + if (!Number.isNaN(options.initialColumn)) { + initialColumn = options.initialColumn + } + if (initialLine >= 0 || initialColumn >= 0) { + if (typeof item.setCursorBufferPosition === 'function') { + item.setCursorBufferPosition([initialLine, initialColumn]) } } - } - if (!options.pending && (pane.getPendingItem() === item)) { - pane.clearPendingItem() - } - - this.itemOpened(item) - - if (options.activateItem === false) { - pane.addItem(item, {pending: options.pending}) - } else { - pane.activateItem(item, {pending: options.pending}) - } - - if (options.activatePane !== false) { - pane.activate() - } - - let initialColumn = 0 - let initialLine = 0 - if (!Number.isNaN(options.initialLine)) { - initialLine = options.initialLine - } - if (!Number.isNaN(options.initialColumn)) { - initialColumn = options.initialColumn - } - if (initialLine >= 0 || initialColumn >= 0) { - if (typeof item.setCursorBufferPosition === 'function') { - item.setCursorBufferPosition([initialLine, initialColumn]) + const index = pane.getActiveItemIndex() + this.emitter.emit('did-open', {uri, pane, item, index}) + if (uri) { + this.incoming.delete(uri) } + } finally { + resolveItem() } - - const index = pane.getActiveItemIndex() - this.emitter.emit('did-open', {uri, pane, item, index}) return item } @@ -1217,42 +1244,32 @@ module.exports = class Workspace extends Model { const fileSize = fs.getSizeSync(filePath) - let [resolveConfirmFileOpenPromise, rejectConfirmFileOpenPromise] = [] - const confirmFileOpenPromise = new Promise((resolve, reject) => { - resolveConfirmFileOpenPromise = resolve - rejectConfirmFileOpenPromise = reject - }) - if (fileSize >= (this.config.get('core.warnOnLargeFileLimit') * 1048576)) { // 40MB by default - this.applicationDelegate.confirm({ - message: 'Atom will be unresponsive during the loading of very large files.', - detail: 'Do you still want to load this file?', - buttons: ['Proceed', 'Cancel'] - }, response => { - if (response === 1) { - rejectConfirmFileOpenPromise() - } else { - resolveConfirmFileOpenPromise() - } + await new Promise((resolve, reject) => { + this.applicationDelegate.confirm({ + message: 'Atom will be unresponsive during the loading of very large files.', + detail: 'Do you still want to load this file?', + buttons: ['Proceed', 'Cancel'] + }, response => { + if (response === 1) { + const error = new Error() + error.code = 'CANCELLED' + reject(error) + } else { + resolve() + } + }) }) - } else { - resolveConfirmFileOpenPromise() } - try { - await confirmFileOpenPromise - const buffer = await this.project.bufferForPath(filePath, options) - return this.textEditorRegistry.build(Object.assign({buffer, autoHeight: false}, options)) - } catch (e) { - const error = new Error() - error.code = 'CANCELLED' - throw error - } + const buffer = await this.project.bufferForPath(filePath, options) + return this.textEditorRegistry.build(Object.assign({buffer, autoHeight: false}, options)) } handleGrammarUsed (grammar) { if (grammar == null) { return } - return this.packageManager.triggerActivationHook(`${grammar.packageName}:grammar-used`) + this.packageManager.triggerActivationHook(`${grammar.scopeName}:root-scope-used`) + this.packageManager.triggerActivationHook(`${grammar.packageName}:grammar-used`) } // Public: Returns a {Boolean} that is `true` if `object` is a `TextEditor`. diff --git a/static/cursors.less b/static/cursors.less index 843dab2c6..5cbfadef6 100644 --- a/static/cursors.less +++ b/static/cursors.less @@ -8,7 +8,7 @@ @ibeam-2x: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAz0lEQVRIx2NgYGBY/R8I/vx5eelX3n82IJ9FxGf6tksvf/8FiTMQAcAGQMDvSwu09abffY8QYSAScNk45G198eX//yev73/4///701eh//kZSARckrNBRvz//+8+6ZohwCzjGNjdgQxkAg7B9WADeBjIBqtJCbhRA0YNoIkBSNmaPEMoNmA0FkYNoFKhapJ6FGyAH3nauaSmPfwI0v/3OukVi0CIZ+F25KrtYcx/CTIy0e+rC7R1Z4KMICVTQQ14feVXIbR695u14+Ir4gwAAD49E54wc1kWAAAAAElFTkSuQmCC'); .cursor-white() { - cursor: -webkit-image-set(@ibeam-1x 1dppx, @ibeam-2x 2dppx) 5 8, text; + cursor: -webkit-image-set(@ibeam-1x 1x, @ibeam-2x 2x) 5 8, text; } // Editors diff --git a/stylelint.config.js b/stylelint.config.js index 49caab46d..136c754fa 100644 --- a/stylelint.config.js +++ b/stylelint.config.js @@ -19,5 +19,6 @@ module.exports = { "rule-empty-line-before": null, // TODO: enable? "at-rule-empty-line-before": null, // TODO: enable? "font-family-no-duplicate-names": null, // TODO: enable? + "unit-no-unknown": [true, {"ignoreUnits": [ "x" ]}], // Needed for -webkit-image-set 1x/2x units } } diff --git a/vendor/jasmine.js b/vendor/jasmine.js index 1b80d662f..ac443e1c8 100644 --- a/vendor/jasmine.js +++ b/vendor/jasmine.js @@ -2317,6 +2317,14 @@ jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessag } } + if (optional_timeoutMessage_ == null) { + const objectToCaptureStack = {} + Error.captureStackTrace(objectToCaptureStack, waitsFor) + const stack = objectToCaptureStack.stack + const line = stack.split('\n')[1] + optional_timeoutMessage_ = `condition ${line}` + } + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); this.addToQueue(waitsForFunc); return this;