├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .github └── stale.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── keymaps └── project-manager.cson ├── lib ├── Manager.js ├── Settings.js ├── models │ └── Project.js ├── project-manager.js ├── stores │ ├── FileStore.js │ └── GitStore.js └── views │ ├── EditView.js │ ├── projects-list-view.js │ └── view-uri.js ├── menus └── project-manager.cson ├── package-lock.json ├── package.json ├── project-manager.gif ├── spec ├── .eslintrc.json ├── file-store-spec.js ├── project-spec.js ├── settings-spec.js └── stores │ ├── array-structure.cson │ ├── empty.cson │ ├── object-structure.cson │ └── with-template-and-project.cson └── styles └── project-manager.less /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb-base", 3 | "parser": "babel-eslint", 4 | "env": { 5 | "node": true, 6 | "browser": true 7 | }, 8 | "globals": { 9 | "atom": true 10 | }, 11 | "rules": { 12 | "global-require": 0, 13 | "no-unused-vars": ["error", { 14 | "vars": "all", 15 | "args": "after-used", 16 | "ignoreRestSiblings": true 17 | }] 18 | }, 19 | "settings": { 20 | "import/core-modules": ["atom"] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: staled 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | spec/db 5 | project.cson 6 | .tags 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | notifications: 4 | email: 5 | on_success: never 6 | on_failure: change 7 | 8 | script: 'curl -s https://raw.githubusercontent.com/atom/ci/master/build-package.sh | sh' -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 3.3.8 4 | Fixes a bug introduced by atom. [#396](https://github.com/danielbrodin/atom-project-manager/pull/396) 5 | 6 | ## 3.3.7 7 | Updates to fix some smaller issues. 8 | 9 | ## 3.3.6 10 | 11 | Merge a bunch of PR. [#334](https://github.com/danielbrodin/atom-project-manager/pull/334), [#377](https://github.com/danielbrodin/atom-project-manager/pull/377), [#377](https://github.com/danielbrodin/atom-project-manager/pull/382) 12 | 13 | ## 3.3.5 14 | 15 | Fixes issues with the tree-view since atom 1.17.0. 16 | 17 | ## 3.3.4 18 | 19 | - Fixes [#297](https://github.com/danielbrodin/atom-project-manager/issues/297). Thanks to [@wmcmurray](https://github.com/wmcmurray). 20 | - Link added for available icons thanks to [@umpirsky](https://github.com/umpirsky). 21 | 22 | ## 3.3.3 23 | 24 | Fixed an issue when the projects file was empty. 25 | 26 | ## 3.3.2 27 | 28 | - Added back the check to see if the path exists in a project. You can however still open it which you couldn't before. 29 | - Added a link to the documentation about `devMode`. 30 | 31 | And some other fixes behind the scenes :) 32 | 33 | ## 3.3.1 34 | 35 | - Deploy seems to be broken so this is pretty much 3.3.0. 36 | 37 | ## 3.3.0 38 | 39 | - Added option to save paths relative to home dir. 40 | - Fixed bug that would change a relative path to absolute when saving a project. 41 | - The Prettify Title option now works again. 42 | 43 | And some other things and corrections. 44 | 45 | ## 3.2.5 46 | 47 | Now automatically closes the edit/save view on save and restores focus to whatever had focus last. 48 | 49 | ## 3.2.4 50 | 51 | - Added `Project Manager: Update Projects` command that for example can be used to include a new git repository without having to reload Atom. 52 | - Added a notification when saving or editing a project. 53 | - Added a notification for when a syntax error is found in `projects.cson`. 54 | - Only properties that have been changed on a project is now saved to keep `projects.cson` a bit more clean. 55 | 56 | ## 3.2.3 57 | 58 | Fixes [#260](https://github.com/danielbrodin/atom-project-manager/issues/260) 59 | 60 | ## 3.2.2 61 | 62 | Fixes the sorting option. 63 | 64 | ## 3.2.1 65 | 66 | Fixes [#259](https://github.com/danielbrodin/atom-project-manager/issues/259) 67 | 68 | ## 3.2.0 69 | 70 | Added a new setting for reversing the effect of `shift+enter` in the list view, so it will default to open in the same window. 71 | 72 | ## 3.1.0 73 | 74 | Added a method to save a project in the provider. Check the readme for more info. 75 | 76 | ## 3.0.1 77 | 78 | Fixed an issue that prevent the settings from being loaded. 79 | 80 | ## 3.0.0 81 | 82 | This release features a complete rewrite and structure that should hopefully fix some bugs. Make sure to reload Atom after the update. 83 | 84 | Some of the new features include: 85 | 86 | - A new setting to include git repositories found in your `core.projectHome` directory. 87 | - You can now open a project with `shift + enter` which will open it in the current window. 88 | - The start of a new project edit mode. `Project Manager: Edit Project` in the command palette. It currently only features some of the fields, but everything should be added. 89 | - A new structure in the `projects.cson` file. Finally rid of the unnecessary object key :) Your file will be updated the first time you save a project. 90 | - The templates integration isn't 100% yet, but it's there. 91 | 92 | Please report any bugs you find, but first make sure you have reloaded Atom. 93 | 94 | ## 2.9.7 95 | 96 | Apm seem to have screwed up with publishing. 97 | 98 | ## 2.9.6 99 | 100 | Missed including a node package. 101 | 102 | ## 2.9.5 103 | 104 | Recursion should be fixed now. 105 | 106 | ## 2.9.4 107 | 108 | Fix recursion that could happen in some cases. 109 | 110 | ## 2.9.3 111 | 112 | Just publishing to add the correct changelog. See 2.9.1 113 | 114 | ## 2.9.2 115 | 116 | This is really 2.9.1 but a git issue messed up the version number. 117 | 118 | ## 2.9.1 119 | 120 | - Fixes [#209](https://github.com/danielbrodin/atom-project-manager/issues/209) 121 | - Now adds and removes paths when added to the projects settings. 122 | 123 | ## 2.9.0 124 | 125 | - Added some prettifying of autosuggested project title. 126 | - Bugfixes 127 | 128 | ## 2.8.0 129 | 130 | - You can now sort projects by the last modification date of the root path. 131 | - The Project Manager will now look for a local settings file (`project.cson`) for the currently active project and merge the settings with what's in `projects.cson`. 132 | - Plus some other behind the scenes stuff which could mean you have to restart Atom for everything to work as it should. Thanks to [@mrodalgaard](https://github.com/mrodalgaard) for one of the fixes. 133 | 134 | ## 2.7.6 135 | 136 | Fix [#195](https://github.com/danielbrodin/atom-project-manager/issues/195) 137 | 138 | ## 2.7.5 139 | 140 | Bugfix 141 | 142 | ## 2.7.4 143 | 144 | Now adds back focus to editor when closing the project list view. 145 | 146 | ## 2.7.3 147 | 148 | Fixes [#143](https://github.com/danielbrodin/atom-project-manager/issues/143) 149 | 150 | ## 2.7.2 151 | 152 | Fixes [#185](https://github.com/danielbrodin/atom-project-manager/issues/185) and [#182](https://github.com/danielbrodin/atom-project-manager/issues/182) 153 | 154 | ## 2.7.1 155 | 156 | Fixes [#180](https://github.com/danielbrodin/atom-project-manager/issues/180) 157 | 158 | ## 2.7.0 159 | 160 | - The option to close the current window when opening a new project is now back. Still not a great implementation but the old one seems to work again. 161 | - The project listing will now warn you if a projects path is not available. 162 | 163 | ## 2.6.5 164 | 165 | Fixes [#163](https://github.com/danielbrodin/atom-project-manager/issues/163) 166 | 167 | ## 2.6.4 168 | 169 | [#161](https://github.com/danielbrodin/atom-project-manager/issues/161) should now be fixed for real thanks to [@douggr](https://github.com/douggr) :) 170 | 171 | ## 2.6.3 172 | 173 | Should fix [#161](https://github.com/danielbrodin/atom-project-manager/issues/161) 174 | 175 | ## 2.6.2 176 | 177 | Fixed [#160](https://github.com/danielbrodin/atom-project-manager/issues/160) 178 | 179 | ## 2.6.1 180 | 181 | Fixed bug that happened when there where no settings on a project 182 | 183 | ## 2.6.0 184 | 185 | Package now use ES6 mostly. Still some views done in CoffeeScript. A restart of Atom could be needed for it to work after the update. 186 | 187 | ## 2.5.2 188 | 189 | Now shows a notification if the `projects.cson` file isn't correctly formatted. 190 | 191 | ## 2.5.1 192 | 193 | - Fixes a bug that would not update a project if the key had changed manually in the `projects.cson`. Not a 100% fix, but will hopefully work for now until a prettier one is around :) 194 | - Added a notification with a link to a fix for when the `projects.cson` file can't be watched. 195 | 196 | ## 2.5.0 197 | 198 | - Updated READ ME to be a bit more clear 199 | - Added cleaning of package commands on deactivation. 200 | 201 | ## 2.4.0 202 | 203 | Now automatically updates a project and its settings if it's the active project when it has been updated in the `projects.cson` file 204 | 205 | ## 2.3.0 206 | 207 | Added services to let other packages get access to the saved projects. Look through the API section of the read me and let me know if you have any questions or you find any bugs with it. 208 | 209 | And also fixed some bugs :) 210 | 211 | ## 2.2.1 212 | 213 | Fixed bug where the list view would sort projects wrong if there were to many 214 | 215 | ## 2.2.0 216 | 217 | Added back the menu under Packages 218 | 219 | ## 2.1.0 220 | 221 | Renamed `Project Manager: Toggle` to `Project Manager: List Projects` to make it clearer what it does. 222 | 223 | ## 2.0.1 224 | 225 | Fixed an issue where the projects file would be added to late. 226 | 227 | ## 2.0.0 228 | 229 | No noticeable changes, just a rewrite of the package to make it easier to add new features and take in pull requests. Please let me know if you find any bugs :) 230 | 231 | ## 1.16.0 232 | 233 | Added support for scoped settings. Thanks to [@benjic](https://github.com/benjic) 234 | 235 | ## 1.15.11 236 | 237 | Fixes issue where projects couldn't be listed because template didn't exist. Thanks to [@coopermaruyama](https://github.com/coopermaruyama) 238 | 239 | ## 1.15.10 240 | 241 | A issue with enabling project settings turned up with an updated to Atom. Did a fix that got rid of the error, but might need an improved fix. 242 | 243 | ## 1.15.9 244 | 245 | - Fixes sorting when more than 10 projects are saved 246 | - Updated dependencies 247 | - Now shows an error notification if the projects file isn't valid 248 | 249 | ## 1.15.8 250 | 251 | Updated the save project dialog 252 | 253 | ## 1.15.7 254 | 255 | Here just because apm got messed up and thought it published 1.15.6 but it did not and now I have to publish 1.15.7 instead. Weird and annoying. Anyone know how to fix this? 256 | 257 | ## 1.15.6 258 | 259 | Bugfix 260 | 261 | ## 1.15.5 262 | 263 | Performance fix 264 | 265 | ## 1.15.4 266 | 267 | Update deprecated calls 268 | 269 | ## 1.15.3 270 | 271 | Updated readme with new keybinding 272 | 273 | ## 1.15.2 274 | 275 | Windows seems to be case sensitive so now using `alt-shift-P` 276 | 277 | ## 1.15.1 278 | 279 | Changed keybindings on windows and linux to `alt-shift-p`. 280 | 281 | ## 1.15.0 282 | 283 | Fixed deprecated calls. Thanks to [@tswaters](https://github.com/tswaters) 284 | 285 | ## 1.14.1 286 | 287 | Added notifications 288 | 289 | ## 1.14.0 290 | 291 | Added filters for project listing, ex: `group: atom` 292 | 293 | ## 1.13.0 294 | 295 | - Improved loading of settings 296 | - Fixed deprecated warnings 297 | - Added tests for most things 298 | 299 | Big thanks to [@alvaromartin](https://github.com/alvaromartin) 300 | 301 | ## 1.12.0 302 | 303 | Now using the new commands API 304 | 305 | ## 1.11.1 306 | 307 | Fixed link to octicons in readme 308 | 309 | ## 1.11.0 310 | 311 | `Project Manager: Save Project` now automatically fills in the title field with the current directory name 312 | 313 | ## 1.10.2 314 | 315 | Disabled **Close Current** since it currently breaks in Atom. Will enable it again as soon as there is a good solution to fix it. 316 | 317 | ## 1.10.1 318 | 319 | Bugfix 320 | 321 | ## 1.10.0 322 | 323 | - You can now add a `group:` setting on a project and sort the projects list by group. 324 | - Added a marker for projects with `devMode: true` to the projects list to make it more clear that it will open in developer mode 325 | 326 | ## 1.9.3 327 | 328 | Did a fix that might fix an error that sometimes came up when updating to latest version. If an error still comes up, try updating to latest version of Atom, currently 0.135 329 | 330 | ## 1.9.2 331 | 332 | Bug fix 333 | 334 | ## 1.9.1 335 | 336 | Now using the updated config system. If you were using "sort by title" you will have to set it again with the new sort by option. 337 | 338 | ## 1.9.0 339 | 340 | - You can now add templates in the projects file. 341 | 342 | ## 1.8.2 343 | 344 | Now using FS instead of pathwatcher for monitoring changes in the projects file. 345 | 346 | ## 1.8.1 347 | 348 | - **Project Manager: Edit Projects** will now open file in the current window instead of a new one 349 | - Added possibility to open project in dev mode with `devMode: true` 350 | 351 | ## 1.8.0 352 | 353 | Changed the way settings work which mean that if you have used any of the old settings, you have to redo them. This way all settings that can be set from the settings view/config.cson can be project specific. 354 | 355 | ```coffee 356 | # Old way 357 | 'settings': 358 | 'setTabLength': 2 359 | 360 | # New way 361 | 'settings': 362 | 'editor.tabLength': 2 363 | 'editor.showIndentGuide': true 364 | 'project-manager.showPath': true 365 | ``` 366 | 367 | ## 1.7.6 368 | 369 | Miss read the updated Atom::open() API so going back to the old way of closing the current window, but with a fix to it. 370 | 371 | ## 1.7.5 372 | 373 | Now use the updated Atom::open() API 374 | 375 | ## 1.7.4 376 | 377 | - Removed Project Manager from the context menu since it has nothing todo with the interface. 378 | - Some code cleanup and fix 379 | 380 | ## 1.7.3 381 | 382 | - Fixed inconsistency in filename in README and CHANGELOG. 383 | - Added brackets around hostname in `projects.[hostname].cson` to make it clearer that that part will change to use the hostname of the environment. 384 | 385 | ## 1.7.2 386 | 387 | - Updated changelog 388 | 389 | ## 1.7.1 390 | 391 | - Updated readme 392 | 393 | ## 1.7 394 | 395 | _Something seems to have happend during publish so 1.6 was skipped_ 396 | 397 | - Project path now shows when saving a project 398 | 399 | ## 1.5 400 | 401 | This update adds an option for **environment specific project** files which are based on your hostname to be able to sync the atom folder between environments without ignoring `projects.cson`. Enabling this option will create a `projects.[hostname].cson` file. 402 | 403 | After enabling this option you will have to manually move the contents of `projects.cson` to the new `projects.[hostname].cson` file. After this `projects.cson`can be delete or left alone. 404 | 405 | ## 1.4 406 | 407 | - Added option to sort by title. 408 | - Added changelog 409 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Daniel Brodin 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project Manager 2 | [![Build status](https://travis-ci.org/danielbrodin/atom-project-manager.svg?branch=master)](https://travis-ci.org/danielbrodin/atom-project-manager/) 3 | [![apm](https://img.shields.io/apm/dm/project-manager.svg)](https://atom.io/packages/project-manager) 4 | [![apm](https://img.shields.io/apm/v/project-manager.svg)]() 5 | 6 | [![Paypal Donations](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=DR4XQWAZV6M2A&lc=SE&item_name=Project%20Manager&item_number=atom%2dproject%2dmanager¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted) a :beer: if you enjoy using the [project manager](https://github.com/danielbrodin/atom-project-manager) :) 7 | 8 | ![Project Manager](https://raw.github.com/danielbrodin/atom-project-manager/master/project-manager.gif) 9 | 10 | 11 | Get easy access to all your projects and manage them with project specific settings and options. 12 | 13 | ## Install 14 | ``` 15 | $ apm install project-manager 16 | ``` 17 | You can also open Atom and go to Preferences > Install and search for `project-manager` 18 | 19 | 20 | ## Use 21 | ### List Projects 22 | `ctrl-cmd-p` (mac) / `alt-shift-P` (win & linux) or `Project Manager: List Projects` in the Command Palette. 23 | 24 | Projects can be filtered by `title`, `group` and `template` by typing `group: atom` which would give all projects with the `atom` group. 25 | 26 | 27 | ### Save Project 28 | `Project Manager: Save Project` in the Command Palette and write the title you want to save the project as. 29 | 30 | ### Edit Project 31 | `Project Manager: Edit Project` will open a page where you can edit the current project. It currently only supports certain fields. 32 | 33 | ### Edit Projects 34 | All projects are saved in a `.cson` file which you can easily reach by searching for `Project Manager: Edit Projects` in the Command Palette. 35 | 36 | ## Project Settings 37 | 38 | setting | Type | Description | Default 39 | -----------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------- 40 | `title` | `string` | Projects title. Used in the projects list | `''` 41 | `paths` | `array` | The folders that will open in the tree view. First path is the main one that counts as the project. | `[]` 42 | `settings` | `Object` | Enables you to set project specific settings. Everything that goes in the `config.cson` file can go here. It also supports scoped settings. | `{}` 43 | `icon` | `string` | Icon that shows in the projects list. It's class-based so can either be a class already provided by Atom like `icon-squirrel` or a class of your own. You can find a list of all icons on [octicons.github.com](https://octicons.github.com/). | `'icon-chevron-right'` 44 | `devMode` | `boolean` | `true` if project should open in dev mode. [Look here][devMode] for more info. | `false` 45 | `group` | `string` | Adds a group to the projects list that can be used to group and filter projects | `null` 46 | `template` | `string` | If you add a project in the `projects.cson` file without `paths` it will count as a template. This way you can easily share settings between projects | `null` 47 | 48 | ### Local settings file 49 | All these settings can be added to a `project.cson` file in the root folder of the project. It follows the below example, but without the array. 50 | 51 | ### Example 52 | ```coffeescript 53 | [ 54 | { 55 | title: 'Project Manager' 56 | group: 'Atom' 57 | paths: [ 58 | '/path/to/project-manager' 59 | ] 60 | devMode: true 61 | settings: 62 | 'editor.tabLength': 4 63 | 'editor.showInvisibles': true 64 | } 65 | ] 66 | 67 | ``` 68 | 69 | ## Provider 70 | If you want to use the projects available through the Project Manager you can use the provided methods. 71 | 72 | ```javascript 73 | function consumeProjectManager({ getProjects, getProject, saveProject, openProject } => { 74 | /** 75 | * Get an array containing all projects. 76 | * The callback will be run each time a project is added. 77 | * Returns a Disposable. 78 | */ 79 | disposables.add( getProjects(projects => { 80 | // Do something with the projects. 81 | })); 82 | 83 | /** 84 | * Get the currently active project. 85 | * The callback will be run whenever the active project changes. 86 | * Returns a Disposable. 87 | */ 88 | disposables.add( getProject(project => { 89 | if (project) { 90 | // We have an active project. 91 | } else { 92 | // Project is either not loaded yet, or there is no project saved. 93 | } 94 | })); 95 | 96 | /** 97 | * Can take either a project recieved from getProjects/getProject or 98 | * just an object with the props for a new project. 99 | */ 100 | saveProject(project); 101 | 102 | /** 103 | * Will open the project. 104 | * `openInSameWindow` should be true if the project should open up in the 105 | * current window. 106 | */ 107 | openProject(project, openInSameWindow); 108 | }); 109 | 110 | ``` 111 | 112 | 113 | ## Contribute 114 | If you would like to contribute to the project manager, be it new features or bugs, 115 | please do the following: 116 | 117 | 1. Fork the repository 118 | 2. Create a new topic branch off the master branch that describe what it does 119 | 3. Commit and push the branch 120 | 4. Make a pull request describing what you have done 121 | 5. Now it will hopefully get merged :) 122 | 123 | All PR's should: 124 | - Pass the [eslint](https://atom.io/packages/linter-eslint) linter 125 | - Add a test when it makes sense, which should be most of the time 126 | 127 | [devMode]: https://atom.io/docs/api/v1.11.2/AtomEnvironment#instance-open 128 | -------------------------------------------------------------------------------- /keymaps/project-manager.cson: -------------------------------------------------------------------------------- 1 | '.platform-darwin': 2 | 'ctrl-cmd-p': 'project-manager:list-projects' 3 | 4 | '.platform-win32': 5 | 'alt-shift-P': 'project-manager:list-projects' 6 | 7 | '.platform-linux': 8 | 'alt-shift-P': 'project-manager:list-projects' 9 | 10 | '.project-manager input': 11 | 'enter': 'core:confirm' 12 | 13 | '.project-manager atom-text-editor[mini]': 14 | 'shift-enter': 'project-manager:alt-confirm' 15 | -------------------------------------------------------------------------------- /lib/Manager.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | import { observable, autorun, computed, action } from 'mobx'; 4 | import untildify from 'untildify'; 5 | import tildify from 'tildify'; 6 | import projectUtil from 'atom-project-util'; 7 | import { each, map } from 'underscore-plus'; 8 | import FileStore from './stores/FileStore'; 9 | import GitStore from './stores/GitStore'; 10 | import Settings from './Settings'; 11 | import Project from './models/Project'; 12 | 13 | export class Manager { 14 | @observable projects = []; 15 | @observable activePaths = []; 16 | 17 | @computed get activeProject() { 18 | if (this.activePaths.length === 0) { 19 | return null; 20 | } 21 | 22 | return this.projects.find(project => project.rootPath === this.activePaths[0]); 23 | } 24 | 25 | constructor() { 26 | this.gitStore = new GitStore(); 27 | this.fileStore = new FileStore(); 28 | this.settings = new Settings(); 29 | 30 | this.fetchProjects(); 31 | 32 | atom.config.onDidChange('project-manager.includeGitRepositories', ({ newValue }) => { 33 | if (newValue) { 34 | this.gitStore.fetch(); 35 | } else { 36 | this.gitStore.empty(); 37 | } 38 | }); 39 | 40 | autorun(() => { 41 | each(this.fileStore.data, (fileProp) => { 42 | this.addProject(fileProp); 43 | }, this); 44 | }); 45 | 46 | autorun(() => { 47 | each(this.gitStore.data, (gitProp) => { 48 | this.addProject(gitProp); 49 | }, this); 50 | }); 51 | 52 | autorun(() => { 53 | if (this.activeProject) { 54 | this.settings.load(this.activeProject.settings); 55 | } 56 | }); 57 | 58 | this.activePaths = atom.project.getPaths(); 59 | atom.project.onDidChangePaths(() => { 60 | this.activePaths = atom.project.getPaths(); 61 | const activePaths = atom.project.getPaths(); 62 | 63 | if (this.activeProject && this.activeProject.rootPath === activePaths[0]) { 64 | if (this.activeProject.paths.length !== activePaths.length) { 65 | this.activeProject.updateProps({ paths: activePaths }); 66 | this.saveProjects(); 67 | } 68 | } 69 | }); 70 | } 71 | 72 | /** 73 | * Create or Update a project. 74 | * 75 | * Props coming from file goes before any other source. 76 | */ 77 | @action addProject(props) { 78 | const foundProject = this.projects.find((project) => { 79 | const projectRootPath = project.rootPath.toLowerCase(); 80 | const propsRootPath = untildify(props.paths[0]).toLowerCase(); 81 | return projectRootPath === propsRootPath; 82 | }); 83 | 84 | if (!foundProject) { 85 | const newProject = new Project(props); 86 | this.projects.push(newProject); 87 | } else { 88 | if (foundProject.source === 'file' && props.source === 'file') { 89 | foundProject.updateProps(props); 90 | } 91 | 92 | if (props.source === 'file' || typeof props.source === 'undefined') { 93 | foundProject.updateProps(props); 94 | } 95 | } 96 | } 97 | 98 | fetchProjects() { 99 | this.fileStore.fetch(); 100 | 101 | if (atom.config.get('project-manager.includeGitRepositories')) { 102 | this.gitStore.fetch(); 103 | } 104 | } 105 | 106 | static open(project, openInSameWindow = false) { 107 | if (Manager.isProject(project)) { 108 | const { devMode } = project.getProps(); 109 | 110 | if (openInSameWindow) { 111 | projectUtil.switch(project.paths); 112 | } else { 113 | atom.open({ 114 | devMode, 115 | pathsToOpen: project.paths, 116 | }); 117 | } 118 | } 119 | } 120 | 121 | saveProject(props) { 122 | let propsToSave = props; 123 | if (Manager.isProject(props)) { 124 | propsToSave = props.getProps(); 125 | } 126 | this.addProject({ ...propsToSave, source: 'file' }); 127 | this.saveProjects(); 128 | } 129 | 130 | saveProjects() { 131 | const projects = this.projects.filter(project => project.props.source === 'file'); 132 | 133 | const arr = map(projects, (project) => { 134 | const props = project.getChangedProps(); 135 | delete props.source; 136 | 137 | if (atom.config.get('project-manager.savePathsRelativeToHome')) { 138 | props.paths = props.paths.map(path => tildify(path)); 139 | } 140 | 141 | return props; 142 | }); 143 | 144 | this.fileStore.store(arr); 145 | } 146 | 147 | static isProject(project) { 148 | if (project instanceof Project) { 149 | return true; 150 | } 151 | 152 | return false; 153 | } 154 | } 155 | 156 | const manager = new Manager(); 157 | export default manager; 158 | -------------------------------------------------------------------------------- /lib/Settings.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | import { each, isArray, isObject } from 'underscore-plus'; 4 | 5 | export default class Settings { 6 | update(settings = {}) { 7 | this.load(settings); 8 | } 9 | 10 | load(values = {}) { 11 | let settings = values; 12 | if ('global' in settings) { 13 | settings['*'] = settings.global; 14 | delete settings.global; 15 | } 16 | 17 | if ('*' in settings) { 18 | const scopedSettings = settings; 19 | settings = settings['*']; 20 | delete scopedSettings['*']; 21 | 22 | each(scopedSettings, this.set, this); 23 | } 24 | 25 | this.set(settings); 26 | } 27 | 28 | set(settings, scope) { 29 | const flatSettings = {}; 30 | const options = scope ? { scopeSelector: scope } : {}; 31 | options.save = false; 32 | this.flatten(flatSettings, settings); 33 | 34 | each(flatSettings, (value, key) => { 35 | atom.config.set(key, value, options); 36 | }); 37 | } 38 | 39 | flatten(root, dict, path) { 40 | let dotPath; 41 | let valueIsObject; 42 | 43 | each(dict, (value, key) => { 44 | dotPath = path ? `${path}.${key}` : key; 45 | valueIsObject = !isArray(value) && isObject(value); 46 | 47 | if (valueIsObject) { 48 | this.flatten(root, dict[key], dotPath); 49 | } else { 50 | root[dotPath] = value; // eslint-disable-line no-param-reassign 51 | } 52 | }, this); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/models/Project.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | import { observable, computed, extendObservable, action, toJS } from 'mobx'; 4 | import fs from 'fs'; 5 | import untildify from 'untildify'; 6 | import CSON from 'season'; 7 | 8 | export default class Project { 9 | @observable props = {} 10 | @observable stats = null; 11 | 12 | @computed get title() { 13 | return this.props.title; 14 | } 15 | 16 | @computed get paths() { 17 | return this.props.paths.map(path => untildify(path)); 18 | } 19 | 20 | @computed get group() { 21 | return this.props.group; 22 | } 23 | 24 | @computed get rootPath() { 25 | return this.paths[0]; 26 | } 27 | 28 | @computed get settings() { 29 | return toJS(this.props.settings); 30 | } 31 | 32 | @computed get source() { 33 | return this.props.source; 34 | } 35 | 36 | @computed get lastModified() { 37 | let mtime = new Date(0); 38 | if (this.stats) { 39 | mtime = this.stats.mtime; 40 | } 41 | 42 | return mtime; 43 | } 44 | 45 | @computed get isCurrent() { 46 | const activePath = atom.project.getPaths()[0]; 47 | 48 | if (activePath === this.rootPath) { 49 | return true; 50 | } 51 | 52 | return false; 53 | } 54 | 55 | static get defaultProps() { 56 | return { 57 | title: '', 58 | group: '', 59 | paths: [], 60 | icon: 'icon-chevron-right', 61 | color: '', 62 | settings: {}, 63 | devMode: false, 64 | template: null, 65 | source: null, 66 | }; 67 | } 68 | 69 | constructor(props) { 70 | extendObservable(this.props, Project.defaultProps); 71 | this.updateProps(props); 72 | } 73 | 74 | updateProps(props) { 75 | extendObservable(this.props, props); 76 | this.setFileStats(); 77 | } 78 | 79 | getProps() { 80 | return toJS(this.props); 81 | } 82 | 83 | getChangedProps() { 84 | const { ...props } = this.getProps(); 85 | const defaults = Project.defaultProps; 86 | 87 | Object.keys(defaults).forEach((key) => { 88 | switch (key) { 89 | case 'settings': { 90 | if (Object.keys(props[key]).length === 0) { 91 | delete props[key]; 92 | } 93 | break; 94 | } 95 | 96 | default: { 97 | if (props[key] === defaults[key]) { 98 | delete props[key]; 99 | } 100 | } 101 | } 102 | }); 103 | 104 | return props; 105 | } 106 | 107 | @action setFileStats() { 108 | fs.stat(this.rootPath, (err, stats) => { 109 | if (!err) { 110 | this.stats = stats; 111 | } 112 | }); 113 | } 114 | 115 | /** 116 | * Fetch settings that are saved locally with the project 117 | * if there are any. 118 | */ 119 | @action fetchLocalSettings() { 120 | const file = `${this.rootPath}/project.cson`; 121 | CSON.readFile(file, (err, settings) => { 122 | if (err) { 123 | return; 124 | } 125 | 126 | extendObservable(this.props.settings, settings); 127 | }); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /lib/project-manager.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | import { autorun } from 'mobx'; 4 | import { CompositeDisposable, Disposable } from 'atom'; 5 | import manager from './Manager'; 6 | import { SAVE_URI, EDIT_URI } from './views/view-uri'; 7 | 8 | let disposables = null; 9 | let projectsListView = null; 10 | let FileStore = null; 11 | 12 | export function editComponent() { 13 | const EditView = require('./views/EditView'); 14 | 15 | return new EditView({ project: manager.activeProject }); 16 | } 17 | 18 | export function activate() { 19 | disposables = new CompositeDisposable(); 20 | 21 | disposables.add(atom.workspace.addOpener((uri) => { 22 | if (uri === EDIT_URI || uri === SAVE_URI) { 23 | return editComponent(); 24 | } 25 | 26 | return null; 27 | })); 28 | 29 | disposables.add(atom.commands.add('atom-workspace', { 30 | 'project-manager:list-projects': () => { 31 | if (!this.projectsListView) { 32 | const ProjectsListView = require('./views/projects-list-view'); 33 | 34 | projectsListView = new ProjectsListView(); 35 | } 36 | 37 | projectsListView.toggle(); 38 | }, 39 | 'project-manager:edit-projects': () => { 40 | if (!FileStore) { 41 | FileStore = require('./stores/FileStore'); 42 | } 43 | 44 | atom.workspace.open(FileStore.getPath()); 45 | }, 46 | 'project-manager:save-project': () => { 47 | atom.workspace.open(SAVE_URI); 48 | }, 49 | 'project-manager:edit-project': () => { 50 | atom.workspace.open(EDIT_URI); 51 | }, 52 | 'project-manager:update-projects': () => { 53 | manager.fetchProjects(); 54 | }, 55 | })); 56 | } 57 | 58 | export function deactivate() { 59 | disposables.dispose(); 60 | } 61 | 62 | export function provideProjects() { 63 | return { 64 | getProjects: (callback) => { 65 | const disposer = autorun(() => { 66 | callback(manager.projects); 67 | }); 68 | 69 | return new Disposable(() => { 70 | disposer(); 71 | }); 72 | }, 73 | getProject: (callback) => { 74 | const disposer = autorun(() => { 75 | callback(manager.activeProject); 76 | }); 77 | 78 | return new Disposable(() => { 79 | disposer(); 80 | }); 81 | }, 82 | saveProject: (project) => { 83 | manager.saveProject(project); 84 | }, 85 | openProject: (project) => { 86 | manager.open(project); 87 | }, 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /lib/stores/FileStore.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | import { observable, action, asFlat, transaction } from 'mobx'; 4 | import CSON from 'season'; 5 | import fs from 'fs'; 6 | import os from 'os'; 7 | import { deepExtend, each } from 'underscore-plus'; 8 | 9 | export default class FileStore { 10 | @observable data = asFlat([]); 11 | @observable fetching = false; 12 | templates = []; 13 | 14 | constructor() { 15 | fs.exists(FileStore.getPath(), (exists) => { 16 | if (exists) { 17 | this.observeFile(); 18 | } else { 19 | this.store([]); 20 | this.observeFile(); 21 | } 22 | }); 23 | } 24 | 25 | static getPath() { 26 | const filedir = atom.getConfigDirPath(); 27 | const envSettings = atom.config.get('project-manager.environmentSpecificProjects'); 28 | let filename = 'projects.cson'; 29 | 30 | if (envSettings) { 31 | const hostname = os.hostname().split('.').shift().toLowerCase(); 32 | filename = `projects.${hostname}.cson`; 33 | } 34 | 35 | return `${filedir}/${filename}`; 36 | } 37 | 38 | @action fetch() { 39 | this.fetching = true; 40 | CSON.readFile(FileStore.getPath(), (err, data) => { 41 | transaction(() => { 42 | let results = []; 43 | if (err) { 44 | FileStore.handleError(err); 45 | } 46 | if (!err && data !== null) { 47 | results = data; 48 | } 49 | 50 | this.data.clear(); 51 | this.templates = []; 52 | 53 | // Support for old structure. 54 | if (Array.isArray(results) === false) { 55 | results = Object.keys(results).map(k => results[k]); 56 | } 57 | 58 | // Make sure we have an array. 59 | if (Array.isArray(results) === false) { 60 | results = []; 61 | } 62 | 63 | each(results, (res) => { 64 | let result = res; 65 | const templateName = result.template || null; 66 | 67 | if (templateName) { 68 | const template = results.filter(props => props.title === templateName); 69 | 70 | if (template.length) { 71 | result = deepExtend({}, template[0], result); 72 | } 73 | } 74 | 75 | if (FileStore.isProject(result)) { 76 | result.source = 'file'; 77 | 78 | this.data.push(result); 79 | } else { 80 | this.templates.push(result); 81 | } 82 | }, this); 83 | 84 | this.fetching = false; 85 | }); 86 | }); 87 | } 88 | 89 | static handleError(err) { 90 | switch (err.name) { 91 | case 'SyntaxError': { 92 | atom.notifications.addError('There is a syntax error in your projects file. Run **Project Manager: Edit Projects** to open and fix the issue.', { 93 | detail: err.message, 94 | description: `Line: ${err.location.first_line} Row: ${err.location.first_column}`, 95 | dismissable: true, 96 | }); 97 | break; 98 | } 99 | 100 | default: { 101 | // No default. 102 | } 103 | } 104 | } 105 | 106 | static isProject(settings) { 107 | if (typeof settings.paths === 'undefined') { 108 | return false; 109 | } 110 | 111 | if (settings.paths.length === 0) { 112 | return false; 113 | } 114 | 115 | return true; 116 | } 117 | 118 | store(projects) { 119 | const store = projects.concat(this.templates); 120 | try { 121 | CSON.writeFileSync(FileStore.getPath(), store); 122 | } catch (e) { 123 | // console.log(e); 124 | } 125 | } 126 | 127 | observeFile() { 128 | if (this.fileWatcher) { 129 | this.fileWatcher.close(); 130 | } 131 | 132 | try { 133 | this.fileWatcher = fs.watch(FileStore.getPath(), () => { 134 | this.fetch(); 135 | }); 136 | } catch (error) { 137 | // console.log(error); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /lib/stores/GitStore.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | import { observable, action, asFlat } from 'mobx'; 4 | import findit from 'findit'; 5 | import path from 'path'; 6 | import untildify from 'untildify'; 7 | 8 | export default class GitStore { 9 | @observable data = asFlat([]); 10 | 11 | constructor() { 12 | const ignoreDirectories = atom.config.get('project-manager.ignoreDirectories'); 13 | this.ignore = ignoreDirectories.replace(/ /g, '').split(','); 14 | } 15 | 16 | @action fetch() { 17 | const projectHome = atom.config.get('core.projectHome'); 18 | const finder = findit(untildify(projectHome)); 19 | this.data.clear(); 20 | 21 | finder.on('directory', (dir, stat, stop) => { 22 | const base = path.basename(dir); 23 | const projectPath = path.dirname(dir); 24 | const projectName = path.basename(projectPath); 25 | 26 | if (base === '.git') { 27 | this.data.push({ 28 | title: projectName, 29 | paths: [projectPath], 30 | source: 'git', 31 | icon: 'icon-repo', 32 | }); 33 | } 34 | 35 | if (this.ignore.includes(base)) { 36 | stop(); 37 | } 38 | }); 39 | } 40 | 41 | @action empty() { 42 | this.data.clear(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/views/EditView.js: -------------------------------------------------------------------------------- 1 | /** @babel */ 2 | /** @jsx etch.dom */ 3 | 4 | import { CompositeDisposable } from 'atom'; 5 | import etch from 'etch'; 6 | import changeCase from 'change-case'; 7 | import path from 'path'; 8 | import { EDIT_URI } from './view-uri'; 9 | import manager from '../Manager'; 10 | import Project from '../models/Project'; 11 | 12 | const disposables = new CompositeDisposable(); 13 | 14 | etch.setScheduler(atom.views); 15 | 16 | export default class EditView { 17 | constructor(props, children) { 18 | this.props = props; 19 | this.children = children; 20 | etch.initialize(this); 21 | 22 | this.storeFocusedElement(); 23 | 24 | this.element.addEventListener('click', (event) => { 25 | if (event.target === this.refs.save) { 26 | this.saveProject(); 27 | } 28 | }); 29 | 30 | disposables.add(atom.commands.add(this.element, { 31 | 'core:save': () => this.saveProject(), 32 | 'core:confirm': () => this.saveProject(), 33 | })); 34 | 35 | disposables.add(atom.commands.add('atom-workspace', { 36 | 'core:cancel': () => this.close(), 37 | })); 38 | } 39 | 40 | storeFocusedElement() { 41 | this.previouslyFocusedElement = document.activeElement; 42 | } 43 | 44 | restoreFocus() { 45 | if (this.previouslyFocusedElement) { 46 | this.previouslyFocusedElement.focus(); 47 | } 48 | } 49 | 50 | close() { 51 | this.destroy(); 52 | } 53 | 54 | async destroy() { 55 | const pane = atom.workspace.paneForURI(EDIT_URI); 56 | if (pane) { 57 | const item = pane.itemForURI(EDIT_URI); 58 | pane.destroyItem(item); 59 | } 60 | 61 | disposables.dispose(); 62 | await etch.destroy(this); 63 | } 64 | 65 | saveProject() { 66 | const projectProps = { 67 | title: this.refs.title.value, 68 | paths: atom.project.getPaths(), 69 | group: this.refs.group.value, 70 | icon: this.refs.icon.value, 71 | color: this.refs.color.value, 72 | devMode: this.refs.devMode.checked, 73 | }; 74 | let message = `${projectProps.title} has been saved.`; 75 | 76 | if (this.props.project) { 77 | // Paths should already be up-to-date, so use 78 | // the current paths as to not break possible relative paths. 79 | projectProps.paths = this.props.project.getProps().paths; 80 | } 81 | 82 | // many stuff will break if there is no root path, 83 | // so we don't continue without a root path 84 | if (!projectProps.paths.length) { 85 | atom.notifications.addError('You must have at least one folder in your project before you can save !'); 86 | } else { 87 | manager.saveProject(projectProps); 88 | 89 | if (this.props.project) { 90 | message = `${this.props.project.title} has been updated.`; 91 | } 92 | atom.notifications.addSuccess(message); 93 | 94 | this.close(); 95 | } 96 | } 97 | 98 | update(props, children) { 99 | this.props = props; 100 | this.children = children; 101 | } 102 | 103 | getTitle() { 104 | if (this.props.project) { 105 | return `Edit ${this.props.project.title}`; 106 | } 107 | 108 | return 'Save Project'; 109 | } 110 | 111 | getIconName() { // eslint-disable-line class-methods-use-this 112 | return 'gear'; 113 | } 114 | 115 | getURI() { // eslint-disable-line class-methods-use-this 116 | return EDIT_URI; 117 | } 118 | 119 | render() { 120 | const defaultProps = Project.defaultProps; 121 | const rootPath = atom.project.getPaths()[0]; 122 | let props = { ...defaultProps, title: path.basename(rootPath) }; 123 | 124 | if (atom.config.get('project-manager.prettifyTitle')) { 125 | props.title = changeCase.titleCase(path.basename(rootPath)); 126 | } 127 | 128 | if (this.props.project && this.props.project.source === 'file') { 129 | const projectProps = this.props.project.getProps(); 130 | props = Object.assign({}, props, projectProps); 131 | } 132 | 133 | const wrapperStyle = { 134 | display: 'flex', 135 | alignItems: 'center', 136 | justifyContent: 'center', 137 | }; 138 | 139 | const style = { 140 | width: '500px', 141 | }; 142 | 143 | const colorDisplay = { 144 | color: props.color, 145 | }; 146 | 147 | return ( 148 |
149 |
150 |

{this.getTitle()}

151 | 152 |
153 | 154 | 155 |
156 | 157 |
158 | 159 | 160 |
161 | 162 |
163 | 164 | 165 |
166 | 167 |
168 | 169 | 170 |
171 | 172 |
173 | 174 | 183 |
184 | 185 |
186 | 187 |
188 |
189 |
190 | ); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /lib/views/projects-list-view.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | /* eslint "class-methods-use-this": ["error", {"exceptMethods": ["viewForItem"]}] */ 4 | 5 | import { SelectListView, $$ } from 'atom-space-pen-views-plus'; 6 | import { autorun } from 'mobx'; 7 | import { each } from 'underscore-plus'; 8 | import manager, { Manager } from '../Manager'; 9 | 10 | export default class ProjectsListView extends SelectListView { 11 | constructor() { 12 | super(); 13 | 14 | autorun('Loading projects for list view', () => { 15 | if (this.panel && this.panel.isVisible()) { 16 | this.show(manager.projects); 17 | } 18 | }); 19 | } 20 | initialize() { 21 | super.initialize(); 22 | this.addClass('project-manager'); 23 | 24 | let infoText = 'shift+click or shift+enter will open project in the current window'; 25 | if (ProjectsListView.reversedConfirm) { 26 | infoText = 'shift+click or shift+enter will open project in a new window'; 27 | } 28 | const infoElement = document.createElement('div'); 29 | infoElement.className = 'text-smaller'; 30 | infoElement.innerHTML = infoText; 31 | this.error.after(infoElement); 32 | 33 | atom.commands.add(this.element, { 34 | 'project-manager:alt-confirm': (event) => { 35 | this.altConfirmed(); 36 | event.stopPropagation(); 37 | }, 38 | }); 39 | } 40 | 41 | static get possibleFilterKeys() { 42 | return ['title', 'group', 'template']; 43 | } 44 | 45 | static get defaultFilterKey() { 46 | return 'title'; 47 | } 48 | 49 | static get sortBy() { 50 | return atom.config.get('project-manager.sortBy'); 51 | } 52 | 53 | static get showPath() { 54 | return atom.config.get('project-manager.showPath'); 55 | } 56 | 57 | static get reversedConfirm() { 58 | return atom.config.get('project-manager.alwaysOpenInSameWindow'); 59 | } 60 | 61 | getFilterKey() { 62 | const input = this.filterEditorView.getText(); 63 | const inputArr = input.split(':'); 64 | const isFilterKey = ProjectsListView.possibleFilterKeys.includes(inputArr[0]); 65 | let filter = ProjectsListView.defaultFilterKey; 66 | 67 | if (inputArr.length > 1 && isFilterKey) { 68 | filter = inputArr[0]; 69 | } 70 | 71 | return filter; 72 | } 73 | 74 | getFilterQuery() { 75 | const input = this.filterEditorView.getText(); 76 | const inputArr = input.split(':'); 77 | let filter = input; 78 | 79 | if (inputArr.length > 1) { 80 | filter = inputArr[1]; 81 | } 82 | 83 | return filter; 84 | } 85 | 86 | getEmptyMessage(itemCount, filteredItemCount) { 87 | if (itemCount === 0) { 88 | return 'No projects saved yet'; 89 | } 90 | return super.getEmptyMessage(itemCount, filteredItemCount); 91 | } 92 | 93 | toggle() { 94 | if (this.panel && this.panel.isVisible()) { 95 | this.cancel(); 96 | } else { 97 | this.show(manager.projects); 98 | } 99 | } 100 | 101 | show(projects) { 102 | if (this.panel == null) { 103 | this.panel = atom.workspace.addModalPanel({ item: this }); 104 | } 105 | 106 | this.storeFocusedElement(); 107 | 108 | const sortedProjects = ProjectsListView.sortItems(projects); 109 | 110 | this.setItems(sortedProjects); 111 | this.focusFilterEditor(); 112 | } 113 | 114 | confirmed(project) { 115 | if (project) { 116 | Manager.open(project, this.isShiftPressed ? 117 | !ProjectsListView.reversedConfirm : ProjectsListView.reversedConfirm); 118 | this.hide(); 119 | } 120 | } 121 | 122 | altConfirmed() { 123 | const project = this.getSelectedItem(); 124 | if (project) { 125 | Manager.open(project, !ProjectsListView.reversedConfirm); 126 | this.hide(); 127 | } 128 | } 129 | 130 | hide() { 131 | if (this.panel) { 132 | this.panel.hide(); 133 | } 134 | } 135 | 136 | cancel() { 137 | super.cancel(); 138 | } 139 | 140 | cancelled() { 141 | this.hide(); 142 | } 143 | 144 | viewForItem(project) { 145 | const { title, group, icon, color, devMode, paths } = project.props; 146 | const showPath = ProjectsListView.showPath; 147 | const projectMissing = !project.stats; 148 | 149 | const border = color ? `border-left: 4px inset ${color}` : 'border-left: 4px inset transparent'; 150 | const itemView = $$(function itemView() { 151 | this.li({ class: 'two-lines' }, 152 | { 'data-path-missing': projectMissing, style: border }, () => { 153 | this.div({ class: 'primary-line' }, () => { 154 | if (devMode) { 155 | this.span({ class: 'project-manager-devmode' }); 156 | } 157 | 158 | this.div({ class: `icon ${icon}`, style: `color: ${color}` }, () => { 159 | this.span({ class: 'project-manager-title' }, title); 160 | if (group) { 161 | this.span({ class: 'project-manager-list-group' }, group); 162 | } 163 | }); 164 | }); 165 | this.div({ class: 'secondary-line' }, () => { 166 | if (projectMissing) { 167 | this.div({ class: 'icon icon-alert' }, 'Path is not available'); 168 | } else if (showPath) { 169 | each(paths, (path) => { 170 | this.div({ class: 'no-icon' }, path); 171 | }, this); 172 | } 173 | }); 174 | }); 175 | }); 176 | 177 | itemView.on('mouseup', (e) => { 178 | this.isShiftPressed = e.shiftKey; 179 | }); 180 | 181 | return itemView; 182 | } 183 | 184 | static sortItems(items) { 185 | const key = ProjectsListView.sortBy; 186 | let sorted = items; 187 | 188 | if (key === 'default') { 189 | return items; 190 | } else if (key === 'last modified') { 191 | sorted = items.sort((a, b) => { 192 | const aModified = a.lastModified.getTime(); 193 | const bModified = b.lastModified.getTime(); 194 | 195 | return aModified > bModified ? -1 : 1; 196 | }); 197 | } else { 198 | sorted = items.sort((a, b) => { 199 | const aValue = (a[key] || '\uffff').toUpperCase(); 200 | const bValue = (b[key] || '\uffff').toUpperCase(); 201 | 202 | return aValue > bValue ? 1 : -1; 203 | }); 204 | } 205 | 206 | return sorted; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /lib/views/view-uri.js: -------------------------------------------------------------------------------- 1 | /** @babel */ 2 | 3 | export const EDIT_URI = 'atom://project-manager-edit'; 4 | export const SAVE_URI = 'atom://project-manager-save'; 5 | -------------------------------------------------------------------------------- /menus/project-manager.cson: -------------------------------------------------------------------------------- 1 | 'menu': [ 2 | { 3 | 'label': 'Packages' 4 | 'submenu': [ 5 | 'label': 'Project Manager' 6 | 'submenu': [ 7 | { 8 | 'label': 'List Projects', 9 | 'command': 'project-manager:list-projects' 10 | } 11 | { 12 | 'label': 'Save Project', 13 | 'command': 'project-manager:save-project' 14 | } 15 | { 16 | 'label': 'Edit Project', 17 | 'command': 'project-manager:edit-project' 18 | } 19 | { 20 | 'label': 'Edit Projects', 21 | 'command': 'project-manager:edit-projects' 22 | } 23 | { 24 | 'label': 'Update Projects', 25 | 'command': 'project-manager:update-projects' 26 | } 27 | ] 28 | ] 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-manager", 3 | "version": "3.3.8", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "acorn": { 8 | "version": "3.3.0", 9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 10 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 11 | "dev": true 12 | }, 13 | "acorn-jsx": { 14 | "version": "3.0.1", 15 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 16 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 17 | "dev": true, 18 | "requires": { 19 | "acorn": "^3.0.4" 20 | } 21 | }, 22 | "ansi-escapes": { 23 | "version": "1.4.0", 24 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", 25 | "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", 26 | "dev": true 27 | }, 28 | "ansi-regex": { 29 | "version": "2.0.0", 30 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", 31 | "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=", 32 | "dev": true 33 | }, 34 | "ansi-styles": { 35 | "version": "2.2.1", 36 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 37 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 38 | "dev": true 39 | }, 40 | "argparse": { 41 | "version": "1.0.10", 42 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 43 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 44 | "dev": true, 45 | "requires": { 46 | "sprintf-js": "~1.0.2" 47 | } 48 | }, 49 | "array-union": { 50 | "version": "1.0.2", 51 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 52 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 53 | "dev": true, 54 | "requires": { 55 | "array-uniq": "^1.0.1" 56 | } 57 | }, 58 | "array-uniq": { 59 | "version": "1.0.3", 60 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 61 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 62 | "dev": true 63 | }, 64 | "arrify": { 65 | "version": "1.0.1", 66 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 67 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 68 | "dev": true 69 | }, 70 | "async": { 71 | "version": "0.2.10", 72 | "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", 73 | "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" 74 | }, 75 | "at-least-node": { 76 | "version": "1.0.0", 77 | "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", 78 | "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" 79 | }, 80 | "atom-project-util": { 81 | "version": "4.2.0", 82 | "resolved": "https://registry.npmjs.org/atom-project-util/-/atom-project-util-4.2.0.tgz", 83 | "integrity": "sha512-i2j2kcApIDOJUBAPev2vHO72kVNA5GVaCala6ia8IRpeHZxrhWTJJA/Rgj5YwR5TEa7RcaHvcnBXEXM9NyEC9A==" 84 | }, 85 | "atom-space-pen-views-plus": { 86 | "version": "3.0.4", 87 | "resolved": "https://registry.npmjs.org/atom-space-pen-views-plus/-/atom-space-pen-views-plus-3.0.4.tgz", 88 | "integrity": "sha512-PfCBrD6RUN359P8Do3D3m2d1Ws2DyR7Jl1Ym97R2Gr9liM+5CYU5AvopJNL9m8pZqOBpu5ePcHjSrC/V1cL8oA==", 89 | "requires": { 90 | "fs-extra": "^9.0.1", 91 | "fuzzaldrin": "^2.1.0", 92 | "space-pen-plus": "^6.0.3" 93 | } 94 | }, 95 | "babel-eslint": { 96 | "version": "7.0.0", 97 | "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.0.0.tgz", 98 | "integrity": "sha1-VOUbQDP1SsgTJuzqTGRqd5k1GW0=", 99 | "dev": true, 100 | "requires": { 101 | "babel-traverse": "^6.15.0", 102 | "babel-types": "^6.15.0", 103 | "babylon": "^6.11.2", 104 | "lodash.pickby": "^4.6.0" 105 | }, 106 | "dependencies": { 107 | "babel-traverse": { 108 | "version": "6.16.0", 109 | "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.16.0.tgz", 110 | "integrity": "sha1-+6ha4f1NEH3pzgAxScxX9TvvDE8=", 111 | "dev": true, 112 | "requires": { 113 | "babel-code-frame": "^6.16.0", 114 | "babel-messages": "^6.8.0", 115 | "babel-runtime": "^6.9.0", 116 | "babel-types": "^6.16.0", 117 | "babylon": "^6.11.0", 118 | "debug": "^2.2.0", 119 | "globals": "^8.3.0", 120 | "invariant": "^2.2.0", 121 | "lodash": "^4.2.0" 122 | }, 123 | "dependencies": { 124 | "babel-code-frame": { 125 | "version": "6.16.0", 126 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.16.0.tgz", 127 | "integrity": "sha1-+Q5g2ghikJ084JhzO105h8l8uN4=", 128 | "dev": true, 129 | "requires": { 130 | "chalk": "^1.1.0", 131 | "esutils": "^2.0.2", 132 | "js-tokens": "^2.0.0" 133 | } 134 | }, 135 | "globals": { 136 | "version": "8.18.0", 137 | "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz", 138 | "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ=", 139 | "dev": true 140 | } 141 | } 142 | }, 143 | "babel-types": { 144 | "version": "6.16.0", 145 | "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.16.0.tgz", 146 | "integrity": "sha1-ccyh2+Uzd2YiXFwZMHHo68vP/P4=", 147 | "dev": true, 148 | "requires": { 149 | "babel-runtime": "^6.9.1", 150 | "esutils": "^2.0.2", 151 | "lodash": "^4.2.0", 152 | "to-fast-properties": "^1.0.1" 153 | } 154 | }, 155 | "babylon": { 156 | "version": "6.13.0", 157 | "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.13.0.tgz", 158 | "integrity": "sha1-WO1A3SqBIGEr5fMYwsC+2+veSgs=", 159 | "dev": true 160 | } 161 | } 162 | }, 163 | "babel-messages": { 164 | "version": "6.8.0", 165 | "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz", 166 | "integrity": "sha1-v1BHNsqWfm1l7wrbWipflHyODrk=", 167 | "dev": true, 168 | "requires": { 169 | "babel-runtime": "^6.0.0" 170 | } 171 | }, 172 | "babel-runtime": { 173 | "version": "6.11.6", 174 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.11.6.tgz", 175 | "integrity": "sha1-bbcH/vLUnEm/o8tk79tDa1GLgiI=", 176 | "dev": true, 177 | "requires": { 178 | "core-js": "^2.4.0", 179 | "regenerator-runtime": "^0.9.5" 180 | } 181 | }, 182 | "balanced-match": { 183 | "version": "1.0.0", 184 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 185 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 186 | "dev": true 187 | }, 188 | "bluebird": { 189 | "version": "3.4.5", 190 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.5.tgz", 191 | "integrity": "sha1-3+ojxzO3uOkkr5dmL5x7vv7+X/k=", 192 | "dev": true 193 | }, 194 | "brace-expansion": { 195 | "version": "1.1.11", 196 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 197 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 198 | "dev": true, 199 | "requires": { 200 | "balanced-match": "^1.0.0", 201 | "concat-map": "0.0.1" 202 | } 203 | }, 204 | "browser-split": { 205 | "version": "0.0.1", 206 | "resolved": "https://registry.npmjs.org/browser-split/-/browser-split-0.0.1.tgz", 207 | "integrity": "sha1-ewl1dPjj6tYG+0Zk5krf3aKYGpM=" 208 | }, 209 | "builtin-modules": { 210 | "version": "1.1.1", 211 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 212 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 213 | "dev": true 214 | }, 215 | "caller-path": { 216 | "version": "0.1.0", 217 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 218 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 219 | "dev": true, 220 | "requires": { 221 | "callsites": "^0.2.0" 222 | } 223 | }, 224 | "callsites": { 225 | "version": "0.2.0", 226 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 227 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 228 | "dev": true 229 | }, 230 | "camelize": { 231 | "version": "1.0.0", 232 | "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", 233 | "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" 234 | }, 235 | "chalk": { 236 | "version": "1.1.3", 237 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 238 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 239 | "dev": true, 240 | "requires": { 241 | "ansi-styles": "^2.2.1", 242 | "escape-string-regexp": "^1.0.2", 243 | "has-ansi": "^2.0.0", 244 | "strip-ansi": "^3.0.0", 245 | "supports-color": "^2.0.0" 246 | } 247 | }, 248 | "change-case": { 249 | "version": "3.0.0", 250 | "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.0.0.tgz", 251 | "integrity": "sha1-bJyONfh5CHCoK2sHRb6MPL75sIE=", 252 | "requires": { 253 | "camel-case": "^3.0.0", 254 | "constant-case": "^2.0.0", 255 | "dot-case": "^2.1.0", 256 | "header-case": "^1.0.0", 257 | "is-lower-case": "^1.1.0", 258 | "is-upper-case": "^1.1.0", 259 | "lower-case": "^1.1.1", 260 | "lower-case-first": "^1.0.0", 261 | "no-case": "^2.2.0", 262 | "param-case": "^2.1.0", 263 | "pascal-case": "^2.0.0", 264 | "path-case": "^2.1.0", 265 | "sentence-case": "^2.1.0", 266 | "snake-case": "^2.1.0", 267 | "swap-case": "^1.1.0", 268 | "title-case": "^2.1.0", 269 | "upper-case": "^1.1.1", 270 | "upper-case-first": "^1.1.0" 271 | }, 272 | "dependencies": { 273 | "camel-case": { 274 | "version": "3.0.0", 275 | "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", 276 | "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", 277 | "requires": { 278 | "no-case": "^2.2.0", 279 | "upper-case": "^1.1.1" 280 | } 281 | }, 282 | "constant-case": { 283 | "version": "2.0.0", 284 | "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz", 285 | "integrity": "sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=", 286 | "requires": { 287 | "snake-case": "^2.1.0", 288 | "upper-case": "^1.1.1" 289 | } 290 | }, 291 | "dot-case": { 292 | "version": "2.1.0", 293 | "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.0.tgz", 294 | "integrity": "sha1-S0PdDXQDw0y2RUJK3Tl+gL/oXKY=", 295 | "requires": { 296 | "no-case": "^2.2.0" 297 | } 298 | }, 299 | "header-case": { 300 | "version": "1.0.0", 301 | "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.0.tgz", 302 | "integrity": "sha1-2eM1kJUF1WBR7BagEGghiJ6RB4E=", 303 | "requires": { 304 | "no-case": "^2.2.0", 305 | "upper-case": "^1.1.3" 306 | } 307 | }, 308 | "param-case": { 309 | "version": "2.1.0", 310 | "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.0.tgz", 311 | "integrity": "sha1-Jhn5D9bIKe0LlY8chO0Dp0Wm1wo=", 312 | "requires": { 313 | "no-case": "^2.2.0" 314 | } 315 | }, 316 | "pascal-case": { 317 | "version": "2.0.0", 318 | "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.0.tgz", 319 | "integrity": "sha1-OcJIveWo3ALVFgaWvbAeBE0BbuE=", 320 | "requires": { 321 | "camel-case": "^3.0.0", 322 | "upper-case-first": "^1.1.0" 323 | } 324 | }, 325 | "path-case": { 326 | "version": "2.1.0", 327 | "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.0.tgz", 328 | "integrity": "sha1-WsSR3mQpNuXf4OGNFsRhuL6M8HM=", 329 | "requires": { 330 | "no-case": "^2.2.0" 331 | } 332 | }, 333 | "sentence-case": { 334 | "version": "2.1.0", 335 | "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.0.tgz", 336 | "integrity": "sha1-1ZL77UV/0aWeOvDuF+mfb9cNfv0=", 337 | "requires": { 338 | "no-case": "^2.2.0", 339 | "upper-case-first": "^1.1.2" 340 | } 341 | }, 342 | "snake-case": { 343 | "version": "2.1.0", 344 | "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", 345 | "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=", 346 | "requires": { 347 | "no-case": "^2.2.0" 348 | } 349 | }, 350 | "title-case": { 351 | "version": "2.1.0", 352 | "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.0.tgz", 353 | "integrity": "sha1-xozLQjIHne1k+UuRtJQa3pE5GXk=", 354 | "requires": { 355 | "no-case": "^2.2.0", 356 | "upper-case": "^1.0.3" 357 | } 358 | } 359 | } 360 | }, 361 | "circular-json": { 362 | "version": "0.3.1", 363 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", 364 | "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", 365 | "dev": true 366 | }, 367 | "cli-cursor": { 368 | "version": "1.0.2", 369 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", 370 | "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", 371 | "dev": true, 372 | "requires": { 373 | "restore-cursor": "^1.0.1" 374 | } 375 | }, 376 | "cli-width": { 377 | "version": "2.1.0", 378 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", 379 | "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", 380 | "dev": true 381 | }, 382 | "code-point-at": { 383 | "version": "1.0.0", 384 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz", 385 | "integrity": "sha1-9psZLT99keOC5Lcb3bd4eGGasMY=", 386 | "dev": true, 387 | "requires": { 388 | "number-is-nan": "^1.0.0" 389 | } 390 | }, 391 | "concat-map": { 392 | "version": "0.0.1", 393 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 394 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 395 | "dev": true 396 | }, 397 | "concat-stream": { 398 | "version": "1.5.2", 399 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", 400 | "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", 401 | "dev": true, 402 | "requires": { 403 | "inherits": "~2.0.1", 404 | "readable-stream": "~2.0.0", 405 | "typedarray": "~0.0.5" 406 | } 407 | }, 408 | "contains-path": { 409 | "version": "0.1.0", 410 | "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", 411 | "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", 412 | "dev": true 413 | }, 414 | "core-js": { 415 | "version": "2.4.1", 416 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", 417 | "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=", 418 | "dev": true 419 | }, 420 | "core-util-is": { 421 | "version": "1.0.2", 422 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 423 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 424 | "dev": true 425 | }, 426 | "d": { 427 | "version": "0.1.1", 428 | "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", 429 | "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", 430 | "dev": true, 431 | "requires": { 432 | "es5-ext": "~0.10.2" 433 | } 434 | }, 435 | "debug": { 436 | "version": "2.6.9", 437 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 438 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 439 | "dev": true, 440 | "requires": { 441 | "ms": "2.0.0" 442 | } 443 | }, 444 | "deep-is": { 445 | "version": "0.1.3", 446 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 447 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 448 | "dev": true 449 | }, 450 | "del": { 451 | "version": "2.2.2", 452 | "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", 453 | "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", 454 | "dev": true, 455 | "requires": { 456 | "globby": "^5.0.0", 457 | "is-path-cwd": "^1.0.0", 458 | "is-path-in-cwd": "^1.0.0", 459 | "object-assign": "^4.0.1", 460 | "pify": "^2.0.0", 461 | "pinkie-promise": "^2.0.0", 462 | "rimraf": "^2.2.8" 463 | } 464 | }, 465 | "dom-walk": { 466 | "version": "0.1.1", 467 | "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", 468 | "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" 469 | }, 470 | "error": { 471 | "version": "4.4.0", 472 | "resolved": "https://registry.npmjs.org/error/-/error-4.4.0.tgz", 473 | "integrity": "sha1-v2n/JR+0onnBmtzNqmth6Q2b8So=", 474 | "requires": { 475 | "camelize": "^1.0.0", 476 | "string-template": "~0.2.0", 477 | "xtend": "~4.0.0" 478 | } 479 | }, 480 | "error-ex": { 481 | "version": "1.3.1", 482 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", 483 | "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", 484 | "dev": true, 485 | "requires": { 486 | "is-arrayish": "^0.2.1" 487 | } 488 | }, 489 | "es5-ext": { 490 | "version": "0.10.12", 491 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz", 492 | "integrity": "sha1-qoRkHU23a2Krul5F/YBey6sUAEc=", 493 | "dev": true, 494 | "requires": { 495 | "es6-iterator": "2", 496 | "es6-symbol": "~3.1" 497 | } 498 | }, 499 | "es6-iterator": { 500 | "version": "2.0.0", 501 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz", 502 | "integrity": "sha1-vZaFZ9YWNeM8C4BydhPJy0sJa6w=", 503 | "dev": true, 504 | "requires": { 505 | "d": "^0.1.1", 506 | "es5-ext": "^0.10.7", 507 | "es6-symbol": "3" 508 | } 509 | }, 510 | "es6-map": { 511 | "version": "0.1.4", 512 | "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.4.tgz", 513 | "integrity": "sha1-o0sUe+IkdzpNfagHJ5TO+jYyuJc=", 514 | "dev": true, 515 | "requires": { 516 | "d": "~0.1.1", 517 | "es5-ext": "~0.10.11", 518 | "es6-iterator": "2", 519 | "es6-set": "~0.1.3", 520 | "es6-symbol": "~3.1.0", 521 | "event-emitter": "~0.3.4" 522 | } 523 | }, 524 | "es6-set": { 525 | "version": "0.1.4", 526 | "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.4.tgz", 527 | "integrity": "sha1-lRa2dhwpZLkv9HlFYjOiR9xwfOg=", 528 | "dev": true, 529 | "requires": { 530 | "d": "~0.1.1", 531 | "es5-ext": "~0.10.11", 532 | "es6-iterator": "2", 533 | "es6-symbol": "3", 534 | "event-emitter": "~0.3.4" 535 | } 536 | }, 537 | "es6-symbol": { 538 | "version": "3.1.0", 539 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz", 540 | "integrity": "sha1-lEgcZV56fK2C66gy2X1UM0ltf/o=", 541 | "dev": true, 542 | "requires": { 543 | "d": "~0.1.1", 544 | "es5-ext": "~0.10.11" 545 | } 546 | }, 547 | "es6-weak-map": { 548 | "version": "2.0.1", 549 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.1.tgz", 550 | "integrity": "sha1-DSu9iCfrX7S6j5f7/qUNQ9sh6oE=", 551 | "dev": true, 552 | "requires": { 553 | "d": "^0.1.1", 554 | "es5-ext": "^0.10.8", 555 | "es6-iterator": "2", 556 | "es6-symbol": "3" 557 | } 558 | }, 559 | "escape-string-regexp": { 560 | "version": "1.0.5", 561 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 562 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 563 | "dev": true 564 | }, 565 | "escope": { 566 | "version": "3.6.0", 567 | "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", 568 | "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", 569 | "dev": true, 570 | "requires": { 571 | "es6-map": "^0.1.3", 572 | "es6-weak-map": "^2.0.1", 573 | "esrecurse": "^4.1.0", 574 | "estraverse": "^4.1.1" 575 | } 576 | }, 577 | "eslint": { 578 | "version": "3.19.0", 579 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", 580 | "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", 581 | "dev": true, 582 | "requires": { 583 | "babel-code-frame": "^6.16.0", 584 | "chalk": "^1.1.3", 585 | "concat-stream": "^1.5.2", 586 | "debug": "^2.1.1", 587 | "doctrine": "^2.0.0", 588 | "escope": "^3.6.0", 589 | "espree": "^3.4.0", 590 | "esquery": "^1.0.0", 591 | "estraverse": "^4.2.0", 592 | "esutils": "^2.0.2", 593 | "file-entry-cache": "^2.0.0", 594 | "glob": "^7.0.3", 595 | "globals": "^9.14.0", 596 | "ignore": "^3.2.0", 597 | "imurmurhash": "^0.1.4", 598 | "inquirer": "^0.12.0", 599 | "is-my-json-valid": "^2.10.0", 600 | "is-resolvable": "^1.0.0", 601 | "js-yaml": "^3.5.1", 602 | "json-stable-stringify": "^1.0.0", 603 | "levn": "^0.3.0", 604 | "lodash": "^4.0.0", 605 | "mkdirp": "^0.5.0", 606 | "natural-compare": "^1.4.0", 607 | "optionator": "^0.8.2", 608 | "path-is-inside": "^1.0.1", 609 | "pluralize": "^1.2.1", 610 | "progress": "^1.1.8", 611 | "require-uncached": "^1.0.2", 612 | "shelljs": "^0.7.5", 613 | "strip-bom": "^3.0.0", 614 | "strip-json-comments": "~2.0.1", 615 | "table": "^3.7.8", 616 | "text-table": "~0.2.0", 617 | "user-home": "^2.0.0" 618 | }, 619 | "dependencies": { 620 | "acorn": { 621 | "version": "5.0.3", 622 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", 623 | "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", 624 | "dev": true 625 | }, 626 | "babel-code-frame": { 627 | "version": "6.22.0", 628 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", 629 | "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", 630 | "dev": true, 631 | "requires": { 632 | "chalk": "^1.1.0", 633 | "esutils": "^2.0.2", 634 | "js-tokens": "^3.0.0" 635 | } 636 | }, 637 | "doctrine": { 638 | "version": "2.0.0", 639 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", 640 | "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", 641 | "dev": true, 642 | "requires": { 643 | "esutils": "^2.0.2", 644 | "isarray": "^1.0.0" 645 | } 646 | }, 647 | "espree": { 648 | "version": "3.4.3", 649 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", 650 | "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", 651 | "dev": true, 652 | "requires": { 653 | "acorn": "^5.0.1", 654 | "acorn-jsx": "^3.0.0" 655 | } 656 | }, 657 | "fast-levenshtein": { 658 | "version": "2.0.6", 659 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 660 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 661 | "dev": true 662 | }, 663 | "globals": { 664 | "version": "9.17.0", 665 | "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", 666 | "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", 667 | "dev": true 668 | }, 669 | "ignore": { 670 | "version": "3.3.3", 671 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", 672 | "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", 673 | "dev": true 674 | }, 675 | "js-tokens": { 676 | "version": "3.0.1", 677 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", 678 | "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", 679 | "dev": true 680 | }, 681 | "mkdirp": { 682 | "version": "0.5.5", 683 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 684 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 685 | "dev": true, 686 | "requires": { 687 | "minimist": "^1.2.5" 688 | }, 689 | "dependencies": { 690 | "minimist": { 691 | "version": "1.2.5", 692 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 693 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 694 | "dev": true 695 | } 696 | } 697 | }, 698 | "optionator": { 699 | "version": "0.8.2", 700 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 701 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 702 | "dev": true, 703 | "requires": { 704 | "deep-is": "~0.1.3", 705 | "fast-levenshtein": "~2.0.4", 706 | "levn": "~0.3.0", 707 | "prelude-ls": "~1.1.2", 708 | "type-check": "~0.3.2", 709 | "wordwrap": "~1.0.0" 710 | } 711 | }, 712 | "shelljs": { 713 | "version": "0.7.7", 714 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz", 715 | "integrity": "sha1-svXHfvlxSPS09uImguELuoZnz/E=", 716 | "dev": true, 717 | "requires": { 718 | "glob": "^7.0.0", 719 | "interpret": "^1.0.0", 720 | "rechoir": "^0.6.2" 721 | } 722 | }, 723 | "strip-json-comments": { 724 | "version": "2.0.1", 725 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 726 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 727 | "dev": true 728 | } 729 | } 730 | }, 731 | "eslint-config-airbnb-base": { 732 | "version": "9.0.0", 733 | "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-9.0.0.tgz", 734 | "integrity": "sha1-A+E1ViqmxNDZ8bvaltkBMmv1itI=", 735 | "dev": true 736 | }, 737 | "eslint-import-resolver-node": { 738 | "version": "0.2.3", 739 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", 740 | "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", 741 | "dev": true, 742 | "requires": { 743 | "debug": "^2.2.0", 744 | "object-assign": "^4.0.1", 745 | "resolve": "^1.1.6" 746 | } 747 | }, 748 | "eslint-module-utils": { 749 | "version": "2.6.0", 750 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", 751 | "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", 752 | "dev": true, 753 | "requires": { 754 | "debug": "^2.6.9", 755 | "pkg-dir": "^2.0.0" 756 | } 757 | }, 758 | "eslint-plugin-import": { 759 | "version": "2.3.0", 760 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.3.0.tgz", 761 | "integrity": "sha1-N8gB4K2g4pbL3yDD85OstbUq82s=", 762 | "dev": true, 763 | "requires": { 764 | "builtin-modules": "^1.1.1", 765 | "contains-path": "^0.1.0", 766 | "debug": "^2.2.0", 767 | "doctrine": "1.5.0", 768 | "eslint-import-resolver-node": "^0.2.0", 769 | "eslint-module-utils": "^2.0.0", 770 | "has": "^1.0.1", 771 | "lodash.cond": "^4.3.0", 772 | "minimatch": "^3.0.3", 773 | "read-pkg-up": "^2.0.0" 774 | }, 775 | "dependencies": { 776 | "doctrine": { 777 | "version": "1.5.0", 778 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", 779 | "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", 780 | "dev": true, 781 | "requires": { 782 | "esutils": "^2.0.2", 783 | "isarray": "^1.0.0" 784 | } 785 | } 786 | } 787 | }, 788 | "esprima": { 789 | "version": "4.0.1", 790 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 791 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 792 | "dev": true 793 | }, 794 | "esquery": { 795 | "version": "1.0.0", 796 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", 797 | "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", 798 | "dev": true, 799 | "requires": { 800 | "estraverse": "^4.0.0" 801 | } 802 | }, 803 | "esrecurse": { 804 | "version": "4.1.0", 805 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz", 806 | "integrity": "sha1-RxO2U2rffyrE8yfVWed1a/9kgiA=", 807 | "dev": true, 808 | "requires": { 809 | "estraverse": "~4.1.0", 810 | "object-assign": "^4.0.1" 811 | }, 812 | "dependencies": { 813 | "estraverse": { 814 | "version": "4.1.1", 815 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz", 816 | "integrity": "sha1-9srKcokzqFDvkGYdDheYK6RxEaI=", 817 | "dev": true 818 | } 819 | } 820 | }, 821 | "estraverse": { 822 | "version": "4.2.0", 823 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 824 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", 825 | "dev": true 826 | }, 827 | "esutils": { 828 | "version": "2.0.2", 829 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 830 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 831 | "dev": true 832 | }, 833 | "etch": { 834 | "version": "0.8.0", 835 | "resolved": "https://registry.npmjs.org/etch/-/etch-0.8.0.tgz", 836 | "integrity": "sha1-VPYZV0NG+KPueXP1T7vQG1YnItY=", 837 | "requires": { 838 | "virtual-dom": "^2.0.1" 839 | } 840 | }, 841 | "ev-store": { 842 | "version": "7.0.0", 843 | "resolved": "https://registry.npmjs.org/ev-store/-/ev-store-7.0.0.tgz", 844 | "integrity": "sha1-GrDH+CE2UF3XSzHRdwHLK+bSZVg=", 845 | "requires": { 846 | "individual": "^3.0.0" 847 | } 848 | }, 849 | "event-emitter": { 850 | "version": "0.3.4", 851 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.4.tgz", 852 | "integrity": "sha1-jWPd+0z+H647MsomXExyAiIIC7U=", 853 | "dev": true, 854 | "requires": { 855 | "d": "~0.1.1", 856 | "es5-ext": "~0.10.7" 857 | } 858 | }, 859 | "exit-hook": { 860 | "version": "1.1.1", 861 | "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", 862 | "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", 863 | "dev": true 864 | }, 865 | "figures": { 866 | "version": "1.7.0", 867 | "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", 868 | "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", 869 | "dev": true, 870 | "requires": { 871 | "escape-string-regexp": "^1.0.5", 872 | "object-assign": "^4.1.0" 873 | } 874 | }, 875 | "file-entry-cache": { 876 | "version": "2.0.0", 877 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 878 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 879 | "dev": true, 880 | "requires": { 881 | "flat-cache": "^1.2.1", 882 | "object-assign": "^4.0.1" 883 | } 884 | }, 885 | "find-up": { 886 | "version": "2.1.0", 887 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 888 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 889 | "dev": true, 890 | "requires": { 891 | "locate-path": "^2.0.0" 892 | } 893 | }, 894 | "findit": { 895 | "version": "2.0.0", 896 | "resolved": "https://registry.npmjs.org/findit/-/findit-2.0.0.tgz", 897 | "integrity": "sha1-ZQnwEmr0wXhVHPqZOU4DLhOk1W4=" 898 | }, 899 | "flat-cache": { 900 | "version": "1.2.1", 901 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.1.tgz", 902 | "integrity": "sha1-bIN9YiWn3lZZMjdAs21TYfcWkf8=", 903 | "dev": true, 904 | "requires": { 905 | "circular-json": "^0.3.0", 906 | "del": "^2.0.2", 907 | "graceful-fs": "^4.1.2", 908 | "write": "^0.2.1" 909 | } 910 | }, 911 | "fs-extra": { 912 | "version": "9.0.1", 913 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", 914 | "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", 915 | "requires": { 916 | "at-least-node": "^1.0.0", 917 | "graceful-fs": "^4.2.0", 918 | "jsonfile": "^6.0.1", 919 | "universalify": "^1.0.0" 920 | }, 921 | "dependencies": { 922 | "graceful-fs": { 923 | "version": "4.2.4", 924 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 925 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" 926 | } 927 | } 928 | }, 929 | "fs-plus": { 930 | "version": "2.8.1", 931 | "resolved": "https://registry.npmjs.org/fs-plus/-/fs-plus-2.8.1.tgz", 932 | "integrity": "sha1-YLyuDSBm9LtHJvI63VJdragGMPY=", 933 | "requires": { 934 | "async": "~0.2.9", 935 | "mkdirp": "~0.3.5", 936 | "rimraf": "~2.2.2", 937 | "underscore-plus": "1.x" 938 | } 939 | }, 940 | "fs.realpath": { 941 | "version": "1.0.0", 942 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 943 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 944 | "dev": true 945 | }, 946 | "function-bind": { 947 | "version": "1.1.0", 948 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", 949 | "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", 950 | "dev": true 951 | }, 952 | "fuzzaldrin": { 953 | "version": "2.1.0", 954 | "resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz", 955 | "integrity": "sha1-kCBMPi/appQbso0WZF1BgGOpDps=" 956 | }, 957 | "generate-function": { 958 | "version": "2.3.1", 959 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", 960 | "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", 961 | "dev": true, 962 | "requires": { 963 | "is-property": "^1.0.2" 964 | } 965 | }, 966 | "generate-object-property": { 967 | "version": "1.2.0", 968 | "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", 969 | "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", 970 | "dev": true, 971 | "requires": { 972 | "is-property": "^1.0.0" 973 | } 974 | }, 975 | "glob": { 976 | "version": "7.0.6", 977 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", 978 | "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", 979 | "dev": true, 980 | "requires": { 981 | "fs.realpath": "^1.0.0", 982 | "inflight": "^1.0.4", 983 | "inherits": "2", 984 | "minimatch": "^3.0.2", 985 | "once": "^1.3.0", 986 | "path-is-absolute": "^1.0.0" 987 | } 988 | }, 989 | "global": { 990 | "version": "4.3.0", 991 | "resolved": "https://registry.npmjs.org/global/-/global-4.3.0.tgz", 992 | "integrity": "sha1-737EvurVebRU9evV5/MD21T0Kis=", 993 | "requires": { 994 | "min-document": "^2.6.1", 995 | "process": "~0.5.1" 996 | } 997 | }, 998 | "globby": { 999 | "version": "5.0.0", 1000 | "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", 1001 | "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", 1002 | "dev": true, 1003 | "requires": { 1004 | "array-union": "^1.0.1", 1005 | "arrify": "^1.0.0", 1006 | "glob": "^7.0.3", 1007 | "object-assign": "^4.0.1", 1008 | "pify": "^2.0.0", 1009 | "pinkie-promise": "^2.0.0" 1010 | } 1011 | }, 1012 | "graceful-fs": { 1013 | "version": "4.1.6", 1014 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz", 1015 | "integrity": "sha1-UUw4dysxvuLgi+3CGgrrOr9UwZ4=" 1016 | }, 1017 | "has": { 1018 | "version": "1.0.1", 1019 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", 1020 | "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", 1021 | "dev": true, 1022 | "requires": { 1023 | "function-bind": "^1.0.2" 1024 | } 1025 | }, 1026 | "has-ansi": { 1027 | "version": "2.0.0", 1028 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 1029 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 1030 | "dev": true, 1031 | "requires": { 1032 | "ansi-regex": "^2.0.0" 1033 | } 1034 | }, 1035 | "hosted-git-info": { 1036 | "version": "2.8.9", 1037 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", 1038 | "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", 1039 | "dev": true 1040 | }, 1041 | "imurmurhash": { 1042 | "version": "0.1.4", 1043 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1044 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1045 | "dev": true 1046 | }, 1047 | "individual": { 1048 | "version": "3.0.0", 1049 | "resolved": "https://registry.npmjs.org/individual/-/individual-3.0.0.tgz", 1050 | "integrity": "sha1-58pPhfiVewGHNPKFdQ3CLsL5hi0=" 1051 | }, 1052 | "inflight": { 1053 | "version": "1.0.5", 1054 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", 1055 | "integrity": "sha1-2zIEzVqd4ubNiQuFxuL2a89PYgo=", 1056 | "dev": true, 1057 | "requires": { 1058 | "once": "^1.3.0", 1059 | "wrappy": "1" 1060 | } 1061 | }, 1062 | "inherits": { 1063 | "version": "2.0.1", 1064 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 1065 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", 1066 | "dev": true 1067 | }, 1068 | "inquirer": { 1069 | "version": "0.12.0", 1070 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", 1071 | "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", 1072 | "dev": true, 1073 | "requires": { 1074 | "ansi-escapes": "^1.1.0", 1075 | "ansi-regex": "^2.0.0", 1076 | "chalk": "^1.0.0", 1077 | "cli-cursor": "^1.0.1", 1078 | "cli-width": "^2.0.0", 1079 | "figures": "^1.3.5", 1080 | "lodash": "^4.3.0", 1081 | "readline2": "^1.0.1", 1082 | "run-async": "^0.1.0", 1083 | "rx-lite": "^3.1.2", 1084 | "string-width": "^1.0.1", 1085 | "strip-ansi": "^3.0.0", 1086 | "through": "^2.3.6" 1087 | } 1088 | }, 1089 | "interpret": { 1090 | "version": "1.0.3", 1091 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", 1092 | "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", 1093 | "dev": true 1094 | }, 1095 | "invariant": { 1096 | "version": "2.2.1", 1097 | "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", 1098 | "integrity": "sha1-sJcBBUdmjH4zcCjr6Bbr42yKjVQ=", 1099 | "dev": true, 1100 | "requires": { 1101 | "loose-envify": "^1.0.0" 1102 | } 1103 | }, 1104 | "is-arrayish": { 1105 | "version": "0.2.1", 1106 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 1107 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 1108 | "dev": true 1109 | }, 1110 | "is-builtin-module": { 1111 | "version": "1.0.0", 1112 | "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", 1113 | "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", 1114 | "dev": true, 1115 | "requires": { 1116 | "builtin-modules": "^1.0.0" 1117 | } 1118 | }, 1119 | "is-fullwidth-code-point": { 1120 | "version": "1.0.0", 1121 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 1122 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 1123 | "dev": true, 1124 | "requires": { 1125 | "number-is-nan": "^1.0.0" 1126 | } 1127 | }, 1128 | "is-lower-case": { 1129 | "version": "1.1.3", 1130 | "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", 1131 | "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=", 1132 | "requires": { 1133 | "lower-case": "^1.1.0" 1134 | } 1135 | }, 1136 | "is-my-ip-valid": { 1137 | "version": "1.0.0", 1138 | "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", 1139 | "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", 1140 | "dev": true 1141 | }, 1142 | "is-my-json-valid": { 1143 | "version": "2.20.5", 1144 | "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.5.tgz", 1145 | "integrity": "sha512-VTPuvvGQtxvCeghwspQu1rBgjYUT6FGxPlvFKbYuFtgc4ADsX3U5ihZOYN0qyU6u+d4X9xXb0IT5O6QpXKt87A==", 1146 | "dev": true, 1147 | "requires": { 1148 | "generate-function": "^2.0.0", 1149 | "generate-object-property": "^1.1.0", 1150 | "is-my-ip-valid": "^1.0.0", 1151 | "jsonpointer": "^4.0.0", 1152 | "xtend": "^4.0.0" 1153 | } 1154 | }, 1155 | "is-object": { 1156 | "version": "1.0.1", 1157 | "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", 1158 | "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" 1159 | }, 1160 | "is-path-cwd": { 1161 | "version": "1.0.0", 1162 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 1163 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", 1164 | "dev": true 1165 | }, 1166 | "is-path-in-cwd": { 1167 | "version": "1.0.0", 1168 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", 1169 | "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", 1170 | "dev": true, 1171 | "requires": { 1172 | "is-path-inside": "^1.0.0" 1173 | } 1174 | }, 1175 | "is-path-inside": { 1176 | "version": "1.0.0", 1177 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", 1178 | "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", 1179 | "dev": true, 1180 | "requires": { 1181 | "path-is-inside": "^1.0.1" 1182 | } 1183 | }, 1184 | "is-property": { 1185 | "version": "1.0.2", 1186 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 1187 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", 1188 | "dev": true 1189 | }, 1190 | "is-resolvable": { 1191 | "version": "1.0.0", 1192 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", 1193 | "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", 1194 | "dev": true, 1195 | "requires": { 1196 | "tryit": "^1.0.1" 1197 | } 1198 | }, 1199 | "is-upper-case": { 1200 | "version": "1.1.2", 1201 | "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", 1202 | "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=", 1203 | "requires": { 1204 | "upper-case": "^1.1.0" 1205 | } 1206 | }, 1207 | "isarray": { 1208 | "version": "1.0.0", 1209 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1210 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1211 | "dev": true 1212 | }, 1213 | "js-tokens": { 1214 | "version": "2.0.0", 1215 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz", 1216 | "integrity": "sha1-eZA/VWPud4zBFi5tzxoAJ8l/nLU=", 1217 | "dev": true 1218 | }, 1219 | "js-yaml": { 1220 | "version": "3.14.0", 1221 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", 1222 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", 1223 | "dev": true, 1224 | "requires": { 1225 | "argparse": "^1.0.7", 1226 | "esprima": "^4.0.0" 1227 | } 1228 | }, 1229 | "json-stable-stringify": { 1230 | "version": "1.0.1", 1231 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 1232 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 1233 | "dev": true, 1234 | "requires": { 1235 | "jsonify": "~0.0.0" 1236 | } 1237 | }, 1238 | "jsonfile": { 1239 | "version": "6.0.1", 1240 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", 1241 | "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", 1242 | "requires": { 1243 | "graceful-fs": "^4.1.6", 1244 | "universalify": "^1.0.0" 1245 | } 1246 | }, 1247 | "jsonify": { 1248 | "version": "0.0.0", 1249 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 1250 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", 1251 | "dev": true 1252 | }, 1253 | "jsonpointer": { 1254 | "version": "4.1.0", 1255 | "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.1.0.tgz", 1256 | "integrity": "sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg==", 1257 | "dev": true 1258 | }, 1259 | "levn": { 1260 | "version": "0.3.0", 1261 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 1262 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 1263 | "dev": true, 1264 | "requires": { 1265 | "prelude-ls": "~1.1.2", 1266 | "type-check": "~0.3.2" 1267 | } 1268 | }, 1269 | "load-json-file": { 1270 | "version": "2.0.0", 1271 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", 1272 | "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", 1273 | "dev": true, 1274 | "requires": { 1275 | "graceful-fs": "^4.1.2", 1276 | "parse-json": "^2.2.0", 1277 | "pify": "^2.0.0", 1278 | "strip-bom": "^3.0.0" 1279 | } 1280 | }, 1281 | "locate-path": { 1282 | "version": "2.0.0", 1283 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 1284 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 1285 | "dev": true, 1286 | "requires": { 1287 | "p-locate": "^2.0.0", 1288 | "path-exists": "^3.0.0" 1289 | }, 1290 | "dependencies": { 1291 | "path-exists": { 1292 | "version": "3.0.0", 1293 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1294 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1295 | "dev": true 1296 | } 1297 | } 1298 | }, 1299 | "lodash": { 1300 | "version": "4.17.21", 1301 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1302 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 1303 | "dev": true 1304 | }, 1305 | "lodash.cond": { 1306 | "version": "4.5.2", 1307 | "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", 1308 | "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", 1309 | "dev": true 1310 | }, 1311 | "lodash.pickby": { 1312 | "version": "4.6.0", 1313 | "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", 1314 | "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=", 1315 | "dev": true 1316 | }, 1317 | "loose-envify": { 1318 | "version": "1.2.0", 1319 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", 1320 | "integrity": "sha1-aaZarT3lQs9O4PT+dOjjPHCcyw8=", 1321 | "dev": true, 1322 | "requires": { 1323 | "js-tokens": "^1.0.1" 1324 | }, 1325 | "dependencies": { 1326 | "js-tokens": { 1327 | "version": "1.0.3", 1328 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz", 1329 | "integrity": "sha1-FOVutoyPGpLEPVn1AU7CncIPKuE=", 1330 | "dev": true 1331 | } 1332 | } 1333 | }, 1334 | "lower-case": { 1335 | "version": "1.1.3", 1336 | "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz", 1337 | "integrity": "sha1-ySOT2XZ5Pu5bpO21g8+OrjW9m/s=" 1338 | }, 1339 | "lower-case-first": { 1340 | "version": "1.0.2", 1341 | "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz", 1342 | "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=", 1343 | "requires": { 1344 | "lower-case": "^1.1.2" 1345 | } 1346 | }, 1347 | "min-document": { 1348 | "version": "2.18.1", 1349 | "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.18.1.tgz", 1350 | "integrity": "sha1-YQHhcjT7EqgZX0Bvqttp2FlSM7I=", 1351 | "requires": { 1352 | "dom-walk": "^0.1.0" 1353 | } 1354 | }, 1355 | "minimatch": { 1356 | "version": "3.0.3", 1357 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", 1358 | "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", 1359 | "dev": true, 1360 | "requires": { 1361 | "brace-expansion": "^1.0.0" 1362 | } 1363 | }, 1364 | "mkdirp": { 1365 | "version": "0.3.5", 1366 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", 1367 | "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" 1368 | }, 1369 | "mobx": { 1370 | "version": "2.6.0", 1371 | "resolved": "https://registry.npmjs.org/mobx/-/mobx-2.6.0.tgz", 1372 | "integrity": "sha1-Cug6IEiLktENTKMm4Y/nilq3yzY=" 1373 | }, 1374 | "ms": { 1375 | "version": "2.0.0", 1376 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1377 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1378 | "dev": true 1379 | }, 1380 | "mute-stream": { 1381 | "version": "0.0.5", 1382 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", 1383 | "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", 1384 | "dev": true 1385 | }, 1386 | "natural-compare": { 1387 | "version": "1.4.0", 1388 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1389 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1390 | "dev": true 1391 | }, 1392 | "next-tick": { 1393 | "version": "0.2.2", 1394 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", 1395 | "integrity": "sha1-ddpKkn7liH45BliABltzNkE7MQ0=" 1396 | }, 1397 | "no-case": { 1398 | "version": "2.3.2", 1399 | "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", 1400 | "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", 1401 | "requires": { 1402 | "lower-case": "^1.1.1" 1403 | } 1404 | }, 1405 | "normalize-package-data": { 1406 | "version": "2.3.8", 1407 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", 1408 | "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=", 1409 | "dev": true, 1410 | "requires": { 1411 | "hosted-git-info": "^2.1.4", 1412 | "is-builtin-module": "^1.0.0", 1413 | "semver": "2 || 3 || 4 || 5", 1414 | "validate-npm-package-license": "^3.0.1" 1415 | } 1416 | }, 1417 | "number-is-nan": { 1418 | "version": "1.0.0", 1419 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", 1420 | "integrity": "sha1-wCD1KcUoKt/dIz2R1LGBw9aG3Es=", 1421 | "dev": true 1422 | }, 1423 | "object-assign": { 1424 | "version": "4.1.0", 1425 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", 1426 | "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", 1427 | "dev": true 1428 | }, 1429 | "once": { 1430 | "version": "1.3.3", 1431 | "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", 1432 | "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", 1433 | "dev": true, 1434 | "requires": { 1435 | "wrappy": "1" 1436 | } 1437 | }, 1438 | "onetime": { 1439 | "version": "1.1.0", 1440 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", 1441 | "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", 1442 | "dev": true 1443 | }, 1444 | "os-homedir": { 1445 | "version": "1.0.1", 1446 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz", 1447 | "integrity": "sha1-DWK99EuRb9O73PLKsZGUj7CU8Ac=" 1448 | }, 1449 | "p-limit": { 1450 | "version": "1.1.0", 1451 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", 1452 | "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", 1453 | "dev": true 1454 | }, 1455 | "p-locate": { 1456 | "version": "2.0.0", 1457 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 1458 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 1459 | "dev": true, 1460 | "requires": { 1461 | "p-limit": "^1.1.0" 1462 | } 1463 | }, 1464 | "parse-json": { 1465 | "version": "2.2.0", 1466 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 1467 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 1468 | "dev": true, 1469 | "requires": { 1470 | "error-ex": "^1.2.0" 1471 | } 1472 | }, 1473 | "path-is-absolute": { 1474 | "version": "1.0.0", 1475 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", 1476 | "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=", 1477 | "dev": true 1478 | }, 1479 | "path-is-inside": { 1480 | "version": "1.0.1", 1481 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.1.tgz", 1482 | "integrity": "sha1-mNjx0DC/BL167uShulSF1AMY/Yk=", 1483 | "dev": true 1484 | }, 1485 | "path-type": { 1486 | "version": "2.0.0", 1487 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", 1488 | "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", 1489 | "dev": true, 1490 | "requires": { 1491 | "pify": "^2.0.0" 1492 | } 1493 | }, 1494 | "pify": { 1495 | "version": "2.3.0", 1496 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1497 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1498 | "dev": true 1499 | }, 1500 | "pinkie": { 1501 | "version": "2.0.4", 1502 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1503 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 1504 | "dev": true 1505 | }, 1506 | "pinkie-promise": { 1507 | "version": "2.0.1", 1508 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1509 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1510 | "dev": true, 1511 | "requires": { 1512 | "pinkie": "^2.0.0" 1513 | } 1514 | }, 1515 | "pkg-dir": { 1516 | "version": "2.0.0", 1517 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", 1518 | "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", 1519 | "dev": true, 1520 | "requires": { 1521 | "find-up": "^2.1.0" 1522 | } 1523 | }, 1524 | "pluralize": { 1525 | "version": "1.2.1", 1526 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", 1527 | "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", 1528 | "dev": true 1529 | }, 1530 | "prelude-ls": { 1531 | "version": "1.1.2", 1532 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1533 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1534 | "dev": true 1535 | }, 1536 | "process": { 1537 | "version": "0.5.2", 1538 | "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", 1539 | "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" 1540 | }, 1541 | "process-nextick-args": { 1542 | "version": "1.0.7", 1543 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 1544 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", 1545 | "dev": true 1546 | }, 1547 | "progress": { 1548 | "version": "1.1.8", 1549 | "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", 1550 | "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", 1551 | "dev": true 1552 | }, 1553 | "read-pkg": { 1554 | "version": "2.0.0", 1555 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", 1556 | "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", 1557 | "dev": true, 1558 | "requires": { 1559 | "load-json-file": "^2.0.0", 1560 | "normalize-package-data": "^2.3.2", 1561 | "path-type": "^2.0.0" 1562 | } 1563 | }, 1564 | "read-pkg-up": { 1565 | "version": "2.0.0", 1566 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", 1567 | "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", 1568 | "dev": true, 1569 | "requires": { 1570 | "find-up": "^2.0.0", 1571 | "read-pkg": "^2.0.0" 1572 | }, 1573 | "dependencies": { 1574 | "find-up": { 1575 | "version": "2.1.0", 1576 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 1577 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 1578 | "dev": true, 1579 | "requires": { 1580 | "locate-path": "^2.0.0" 1581 | } 1582 | } 1583 | } 1584 | }, 1585 | "readable-stream": { 1586 | "version": "2.0.6", 1587 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", 1588 | "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", 1589 | "dev": true, 1590 | "requires": { 1591 | "core-util-is": "~1.0.0", 1592 | "inherits": "~2.0.1", 1593 | "isarray": "~1.0.0", 1594 | "process-nextick-args": "~1.0.6", 1595 | "string_decoder": "~0.10.x", 1596 | "util-deprecate": "~1.0.1" 1597 | } 1598 | }, 1599 | "readline2": { 1600 | "version": "1.0.1", 1601 | "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", 1602 | "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", 1603 | "dev": true, 1604 | "requires": { 1605 | "code-point-at": "^1.0.0", 1606 | "is-fullwidth-code-point": "^1.0.0", 1607 | "mute-stream": "0.0.5" 1608 | } 1609 | }, 1610 | "rechoir": { 1611 | "version": "0.6.2", 1612 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 1613 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 1614 | "dev": true, 1615 | "requires": { 1616 | "resolve": "^1.1.6" 1617 | } 1618 | }, 1619 | "regenerator-runtime": { 1620 | "version": "0.9.5", 1621 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz", 1622 | "integrity": "sha1-QD1tQKS9/5wzDdk5Lcuy2ai7ofw=", 1623 | "dev": true 1624 | }, 1625 | "require-uncached": { 1626 | "version": "1.0.2", 1627 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.2.tgz", 1628 | "integrity": "sha1-Z9rTtzMInncDASRnikWVifr2p+w=", 1629 | "dev": true, 1630 | "requires": { 1631 | "caller-path": "^0.1.0", 1632 | "resolve-from": "^1.0.0" 1633 | } 1634 | }, 1635 | "resolve": { 1636 | "version": "1.1.7", 1637 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", 1638 | "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", 1639 | "dev": true 1640 | }, 1641 | "resolve-from": { 1642 | "version": "1.0.1", 1643 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 1644 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 1645 | "dev": true 1646 | }, 1647 | "restore-cursor": { 1648 | "version": "1.0.1", 1649 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", 1650 | "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", 1651 | "dev": true, 1652 | "requires": { 1653 | "exit-hook": "^1.0.0", 1654 | "onetime": "^1.0.0" 1655 | } 1656 | }, 1657 | "rimraf": { 1658 | "version": "2.2.8", 1659 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", 1660 | "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" 1661 | }, 1662 | "run-async": { 1663 | "version": "0.1.0", 1664 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", 1665 | "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", 1666 | "dev": true, 1667 | "requires": { 1668 | "once": "^1.3.0" 1669 | } 1670 | }, 1671 | "rx-lite": { 1672 | "version": "3.1.2", 1673 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", 1674 | "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", 1675 | "dev": true 1676 | }, 1677 | "season": { 1678 | "version": "5.4.1", 1679 | "resolved": "https://registry.npmjs.org/season/-/season-5.4.1.tgz", 1680 | "integrity": "sha1-S9baYVKn8tbwixQzzi2SBmmFPQ0=", 1681 | "requires": { 1682 | "cson-parser": "1.0.9", 1683 | "fs-plus": "2.x", 1684 | "optimist": "~0.4.0" 1685 | }, 1686 | "dependencies": { 1687 | "cson-parser": { 1688 | "version": "1.0.9", 1689 | "resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-1.0.9.tgz", 1690 | "integrity": "sha1-t5/BuCp3V0NoDw7/uL+tMRNNrHQ=", 1691 | "requires": { 1692 | "coffee-script": "1.9.0" 1693 | }, 1694 | "dependencies": { 1695 | "coffee-script": { 1696 | "version": "1.9.0", 1697 | "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.9.0.tgz", 1698 | "integrity": "sha1-dJLLvD8DYcxdiGWv9yN1Uv8z4fc=" 1699 | } 1700 | } 1701 | }, 1702 | "optimist": { 1703 | "version": "0.4.0", 1704 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.4.0.tgz", 1705 | "integrity": "sha1-y47Dfy/jqphky2eidSUOfhliCiU=", 1706 | "requires": { 1707 | "wordwrap": "~0.0.2" 1708 | }, 1709 | "dependencies": { 1710 | "wordwrap": { 1711 | "version": "0.0.3", 1712 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 1713 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" 1714 | } 1715 | } 1716 | } 1717 | } 1718 | }, 1719 | "semver": { 1720 | "version": "5.3.0", 1721 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 1722 | "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", 1723 | "dev": true 1724 | }, 1725 | "slice-ansi": { 1726 | "version": "0.0.4", 1727 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", 1728 | "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", 1729 | "dev": true 1730 | }, 1731 | "space-pen-plus": { 1732 | "version": "6.0.3", 1733 | "resolved": "https://registry.npmjs.org/space-pen-plus/-/space-pen-plus-6.0.3.tgz", 1734 | "integrity": "sha512-iqPZAQYP3xPDGxT6MxIwm4GQks91p2H4QeUUcjjzPyr2FEmpaqVLX6cDwjzf8HWMQ0r9fa3hSB9CzMODXVBe6g==", 1735 | "requires": { 1736 | "jquery": "^3.5.1" 1737 | }, 1738 | "dependencies": { 1739 | "jquery": { 1740 | "version": "3.5.1", 1741 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", 1742 | "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==" 1743 | } 1744 | } 1745 | }, 1746 | "spdx-correct": { 1747 | "version": "1.0.2", 1748 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", 1749 | "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", 1750 | "dev": true, 1751 | "requires": { 1752 | "spdx-license-ids": "^1.0.2" 1753 | } 1754 | }, 1755 | "spdx-expression-parse": { 1756 | "version": "1.0.4", 1757 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", 1758 | "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", 1759 | "dev": true 1760 | }, 1761 | "spdx-license-ids": { 1762 | "version": "1.2.2", 1763 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", 1764 | "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", 1765 | "dev": true 1766 | }, 1767 | "sprintf-js": { 1768 | "version": "1.0.3", 1769 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1770 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1771 | "dev": true 1772 | }, 1773 | "string-template": { 1774 | "version": "0.2.1", 1775 | "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", 1776 | "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" 1777 | }, 1778 | "string-width": { 1779 | "version": "1.0.2", 1780 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1781 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1782 | "dev": true, 1783 | "requires": { 1784 | "code-point-at": "^1.0.0", 1785 | "is-fullwidth-code-point": "^1.0.0", 1786 | "strip-ansi": "^3.0.0" 1787 | } 1788 | }, 1789 | "string_decoder": { 1790 | "version": "0.10.31", 1791 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1792 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", 1793 | "dev": true 1794 | }, 1795 | "strip-ansi": { 1796 | "version": "3.0.1", 1797 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1798 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1799 | "dev": true, 1800 | "requires": { 1801 | "ansi-regex": "^2.0.0" 1802 | } 1803 | }, 1804 | "strip-bom": { 1805 | "version": "3.0.0", 1806 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 1807 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 1808 | "dev": true 1809 | }, 1810 | "supports-color": { 1811 | "version": "2.0.0", 1812 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1813 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 1814 | "dev": true 1815 | }, 1816 | "swap-case": { 1817 | "version": "1.1.2", 1818 | "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz", 1819 | "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=", 1820 | "requires": { 1821 | "lower-case": "^1.1.1", 1822 | "upper-case": "^1.1.1" 1823 | } 1824 | }, 1825 | "table": { 1826 | "version": "3.7.8", 1827 | "resolved": "https://registry.npmjs.org/table/-/table-3.7.8.tgz", 1828 | "integrity": "sha1-tCRDPvWWhRkisv13IkppoZUWGOs=", 1829 | "dev": true, 1830 | "requires": { 1831 | "bluebird": "^3.1.1", 1832 | "chalk": "^1.1.1", 1833 | "lodash": "^4.0.0", 1834 | "slice-ansi": "0.0.4", 1835 | "string-width": "^1.0.1", 1836 | "strip-ansi": "^3.0.0", 1837 | "tv4": "^1.2.7", 1838 | "xregexp": "^3.0.0" 1839 | } 1840 | }, 1841 | "text-table": { 1842 | "version": "0.2.0", 1843 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1844 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1845 | "dev": true 1846 | }, 1847 | "through": { 1848 | "version": "2.3.8", 1849 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1850 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1851 | "dev": true 1852 | }, 1853 | "tildify": { 1854 | "version": "1.2.0", 1855 | "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", 1856 | "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", 1857 | "requires": { 1858 | "os-homedir": "^1.0.0" 1859 | } 1860 | }, 1861 | "to-fast-properties": { 1862 | "version": "1.0.2", 1863 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz", 1864 | "integrity": "sha1-8/XAw7pymafvmUJ+RGMyV63kMyA=", 1865 | "dev": true 1866 | }, 1867 | "tryit": { 1868 | "version": "1.0.2", 1869 | "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.2.tgz", 1870 | "integrity": "sha1-wZawBz5rHFldk8nIMIVbeswypFM=", 1871 | "dev": true 1872 | }, 1873 | "tv4": { 1874 | "version": "1.2.7", 1875 | "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.2.7.tgz", 1876 | "integrity": "sha1-vSk4mvxzreSa5fSBQrXVRL9o0SA=", 1877 | "dev": true 1878 | }, 1879 | "type-check": { 1880 | "version": "0.3.2", 1881 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1882 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1883 | "dev": true, 1884 | "requires": { 1885 | "prelude-ls": "~1.1.2" 1886 | } 1887 | }, 1888 | "typedarray": { 1889 | "version": "0.0.6", 1890 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1891 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1892 | "dev": true 1893 | }, 1894 | "underscore-plus": { 1895 | "version": "1.6.6", 1896 | "resolved": "https://registry.npmjs.org/underscore-plus/-/underscore-plus-1.6.6.tgz", 1897 | "integrity": "sha1-ZezeG9xEGjXYnmUP1w3PE65Dmn0=", 1898 | "requires": { 1899 | "underscore": "~1.6.0" 1900 | }, 1901 | "dependencies": { 1902 | "underscore": { 1903 | "version": "1.6.0", 1904 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", 1905 | "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" 1906 | } 1907 | } 1908 | }, 1909 | "universalify": { 1910 | "version": "1.0.0", 1911 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", 1912 | "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" 1913 | }, 1914 | "untildify": { 1915 | "version": "3.0.2", 1916 | "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz", 1917 | "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=" 1918 | }, 1919 | "upper-case": { 1920 | "version": "1.1.3", 1921 | "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", 1922 | "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" 1923 | }, 1924 | "upper-case-first": { 1925 | "version": "1.1.2", 1926 | "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", 1927 | "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", 1928 | "requires": { 1929 | "upper-case": "^1.1.1" 1930 | } 1931 | }, 1932 | "user-home": { 1933 | "version": "2.0.0", 1934 | "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", 1935 | "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", 1936 | "dev": true, 1937 | "requires": { 1938 | "os-homedir": "^1.0.0" 1939 | } 1940 | }, 1941 | "util-deprecate": { 1942 | "version": "1.0.2", 1943 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1944 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1945 | "dev": true 1946 | }, 1947 | "validate-npm-package-license": { 1948 | "version": "3.0.1", 1949 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", 1950 | "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", 1951 | "dev": true, 1952 | "requires": { 1953 | "spdx-correct": "~1.0.0", 1954 | "spdx-expression-parse": "~1.0.0" 1955 | } 1956 | }, 1957 | "virtual-dom": { 1958 | "version": "2.1.1", 1959 | "resolved": "https://registry.npmjs.org/virtual-dom/-/virtual-dom-2.1.1.tgz", 1960 | "integrity": "sha1-gO2i1IG57eDASRGM78tKBfIdE3U=", 1961 | "requires": { 1962 | "browser-split": "0.0.1", 1963 | "error": "^4.3.0", 1964 | "ev-store": "^7.0.0", 1965 | "global": "^4.3.0", 1966 | "is-object": "^1.0.1", 1967 | "next-tick": "^0.2.2", 1968 | "x-is-array": "0.1.0", 1969 | "x-is-string": "0.1.0" 1970 | } 1971 | }, 1972 | "wordwrap": { 1973 | "version": "1.0.0", 1974 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1975 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1976 | "dev": true 1977 | }, 1978 | "wrappy": { 1979 | "version": "1.0.2", 1980 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1981 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1982 | "dev": true 1983 | }, 1984 | "write": { 1985 | "version": "0.2.1", 1986 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 1987 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 1988 | "dev": true, 1989 | "requires": { 1990 | "mkdirp": "^0.5.1" 1991 | }, 1992 | "dependencies": { 1993 | "mkdirp": { 1994 | "version": "0.5.5", 1995 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1996 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1997 | "dev": true, 1998 | "requires": { 1999 | "minimist": "^1.2.5" 2000 | }, 2001 | "dependencies": { 2002 | "minimist": { 2003 | "version": "1.2.5", 2004 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 2005 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 2006 | "dev": true 2007 | } 2008 | } 2009 | } 2010 | } 2011 | }, 2012 | "x-is-array": { 2013 | "version": "0.1.0", 2014 | "resolved": "https://registry.npmjs.org/x-is-array/-/x-is-array-0.1.0.tgz", 2015 | "integrity": "sha1-3lIBcdR7P0FvVYfWKbidJrEtwp0=" 2016 | }, 2017 | "x-is-string": { 2018 | "version": "0.1.0", 2019 | "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", 2020 | "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" 2021 | }, 2022 | "xregexp": { 2023 | "version": "3.1.1", 2024 | "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.1.1.tgz", 2025 | "integrity": "sha1-juGNde9cfLP5ln+NKUFKbKWxoYQ=", 2026 | "dev": true 2027 | }, 2028 | "xtend": { 2029 | "version": "4.0.1", 2030 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 2031 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" 2032 | } 2033 | } 2034 | } 2035 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-manager", 3 | "main": "./lib/project-manager", 4 | "version": "3.3.8", 5 | "description": "Project Manager for easy access and switching between projects in Atom.", 6 | "repository": "https://github.com/danielbrodin/atom-project-manager", 7 | "license": "MIT", 8 | "keywords": [ 9 | "project", 10 | "manager", 11 | "settings", 12 | "workflow", 13 | "productivity" 14 | ], 15 | "engines": { 16 | "atom": ">1.4.0" 17 | }, 18 | "scripts": { 19 | "test": "apm test && ./node_modules/.bin/eslint lib/**" 20 | }, 21 | "dependencies": { 22 | "atom-project-util": "^4.2.0", 23 | "atom-space-pen-views-plus": "^3.0.4", 24 | "change-case": "^3.0.0", 25 | "etch": "^0.8.0", 26 | "findit": "^2.0.0", 27 | "mobx": "^2.6.0", 28 | "season": "^5.4.1", 29 | "tildify": "^1.2.0", 30 | "underscore-plus": "^1.6.6", 31 | "untildify": "^3.0.2" 32 | }, 33 | "providedServices": { 34 | "project-manager": { 35 | "description": "Get access to all saved projects", 36 | "versions": { 37 | "3.1.0": "provideProjects" 38 | } 39 | } 40 | }, 41 | "configSchema": { 42 | "showPath": { 43 | "type": "boolean", 44 | "default": true 45 | }, 46 | "environmentSpecificProjects": { 47 | "type": "boolean", 48 | "default": false 49 | }, 50 | "prettifyTitle": { 51 | "type": "boolean", 52 | "default": true, 53 | "description": "Will suggest a prettified project title on save." 54 | }, 55 | "savePathsRelativeToHome": { 56 | "type": "boolean", 57 | "default": false, 58 | "description": "Will save paths relative to home path if possible." 59 | }, 60 | "sortBy": { 61 | "type": "string", 62 | "description": "Default sorting is the order in which the projects are", 63 | "default": "default", 64 | "enum": [ 65 | "default", 66 | "title", 67 | "group", 68 | "last modified" 69 | ] 70 | }, 71 | "includeGitRepositories": { 72 | "type": "boolean", 73 | "default": false, 74 | "description": "Will search for directories in your `Project Home` that include `.git` and list them." 75 | }, 76 | "ignoreDirectories": { 77 | "type": "string", 78 | "default": "node_modules, vendor", 79 | "description": "Comma separated list of directories to skip when looking for git repositories." 80 | }, 81 | "alwaysOpenInSameWindow": { 82 | "type": "boolean", 83 | "default": false, 84 | "description": "Will reverse `shift+enter` in the list view to open in a new window." 85 | } 86 | }, 87 | "devDependencies": { 88 | "babel-eslint": "^7.0.0", 89 | "eslint": "^3.19.0", 90 | "eslint-config-airbnb-base": "^9.0.0", 91 | "eslint-plugin-import": "^2.3.0" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /project-manager.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielbrodin/atom-project-manager/828730db9e20b07b0a44ca59dcbd243017fc16b3/project-manager.gif -------------------------------------------------------------------------------- /spec/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jasmine": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /spec/file-store-spec.js: -------------------------------------------------------------------------------- 1 | const FileStore = require('../lib/stores/FileStore'); 2 | const path = require('path'); 3 | 4 | const storesPath = path.resolve(__dirname, 'stores'); 5 | 6 | describe('FileStore', () => { 7 | it('lets you know when it is done fetching', () => { 8 | spyOn(FileStore, 'getPath').andCallFake(() => path.resolve(storesPath, 'array-structure.cson')); 9 | const fileStore = new FileStore(); 10 | 11 | expect(fileStore.fetching).toBe(false); 12 | fileStore.fetch(); 13 | expect(fileStore.fetching).toBe(true); 14 | 15 | waitsFor(() => fileStore.fetching === false); 16 | 17 | runs(() => { 18 | expect(fileStore.fetching).toBe(false); 19 | }); 20 | }); 21 | 22 | it('manages empty files', () => { 23 | spyOn(FileStore, 'getPath').andCallFake(() => path.resolve(storesPath, 'empty.cson')); 24 | const fileStore = new FileStore(); 25 | 26 | fileStore.fetch(); 27 | expect(fileStore.fetching).toBe(true); 28 | 29 | waitsFor(() => fileStore.fetching === false); 30 | 31 | runs(() => { 32 | expect(fileStore.fetching).toBe(false); 33 | expect(fileStore.data.length).toBe(0); 34 | }); 35 | }); 36 | 37 | it('manages the 1.x object structure', () => { 38 | spyOn(FileStore, 'getPath').andCallFake(() => path.resolve(storesPath, 'object-structure.cson')); 39 | const fileStore = new FileStore(); 40 | 41 | fileStore.fetch(); 42 | 43 | waitsFor(() => fileStore.fetching === false); 44 | 45 | runs(() => { 46 | expect(fileStore.data.length).toBe(1); 47 | expect(fileStore.data[0].title).toBe('bar'); 48 | }); 49 | }); 50 | 51 | it('manages if no file exists', () => { 52 | spyOn(FileStore, 'getPath').andCallFake(() => path.resolve(storesPath, 'a-file-that-doesnt-exist.cson')); 53 | const fileStore = new FileStore(); 54 | spyOn(fileStore, 'store').andCallFake(() => false); 55 | 56 | fileStore.fetch(); 57 | 58 | waitsFor(() => fileStore.fetching === false); 59 | 60 | runs(() => { 61 | expect(fileStore.data.length).toBe(0); 62 | }); 63 | }); 64 | 65 | it('manages the 2.x structure', () => { 66 | spyOn(FileStore, 'getPath').andCallFake(() => path.resolve(storesPath, 'array-structure.cson')); 67 | const fileStore = new FileStore(); 68 | 69 | fileStore.fetch(); 70 | 71 | waitsFor(() => fileStore.fetching === false); 72 | 73 | runs(() => { 74 | expect(fileStore.data.length).toBe(2); 75 | }); 76 | }); 77 | 78 | it('separates projects and templates', () => { 79 | spyOn(FileStore, 'getPath').andCallFake(() => path.resolve(storesPath, 'with-template-and-project.cson')); 80 | const fileStore = new FileStore(); 81 | 82 | fileStore.fetch(); 83 | 84 | waitsFor(() => fileStore.fetching === false); 85 | 86 | runs(() => { 87 | expect(fileStore.data.length).toBe(1); 88 | expect(fileStore.templates.length).toBe(1); 89 | }); 90 | }); 91 | 92 | it('merges the project with the template', () => { 93 | spyOn(FileStore, 'getPath').andCallFake(() => path.resolve(storesPath, 'with-template-and-project.cson')); 94 | const fileStore = new FileStore(); 95 | 96 | fileStore.fetch(); 97 | 98 | waitsFor(() => fileStore.fetching === false); 99 | 100 | runs(() => { 101 | expect(fileStore.data[0].group).toBe('foobar'); 102 | }); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /spec/project-spec.js: -------------------------------------------------------------------------------- 1 | const Project = require('../lib/models/Project'); 2 | 3 | const packagePaths = atom.packages.getPackageDirPaths(); 4 | const packagePath = `${packagePaths}/project-manager`; 5 | 6 | describe('Project', () => { 7 | describe('properties', () => { 8 | it('return all props including defaults when calling getProps', () => { 9 | const project = new Project({ 10 | title: 'text', 11 | paths: [packagePath], 12 | group: 'test', 13 | someThingNew: 'awesome', 14 | }); 15 | 16 | const props = project.getProps(); 17 | const defaultProps = Project.defaultProps; 18 | 19 | expect(props.someThingNew).toBeDefined(); 20 | 21 | Object.keys(defaultProps).forEach((key) => { 22 | expect(props[key]).toBeDefined(); 23 | }); 24 | }); 25 | 26 | it('only returns changed props when calling getChangedProps', () => { 27 | const project = new Project({ 28 | title: 'text', 29 | paths: [packagePath], 30 | group: 'test', 31 | }); 32 | 33 | const changedProps = project.getChangedProps(); 34 | 35 | expect(changedProps.group).toBe('test'); 36 | expect(changedProps.icon).not.toBeDefined(); 37 | expect(changedProps.color).not.toBeDefined(); 38 | }); 39 | 40 | it('can update its properties', () => { 41 | const project = new Project({ 42 | title: 'text', 43 | paths: [packagePath], 44 | }); 45 | 46 | expect(project.getProps().group).toBe(''); 47 | expect(project.someThingNew).not.toBeDefined(); 48 | 49 | project.updateProps({ 50 | group: 'test', 51 | someThingNew: 'awesome', 52 | }); 53 | 54 | expect(project.getProps().group).toBe('test'); 55 | expect(project.getProps().someThingNew).toBeDefined(); 56 | }); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /spec/settings-spec.js: -------------------------------------------------------------------------------- 1 | const Settings = require('../lib/Settings'); 2 | 3 | const settings = new Settings(); 4 | 5 | describe('Settings', () => { 6 | it('loads settings without scope', () => { 7 | const config = { 8 | 'foo.bar': 'baz', 9 | 'bar.foo': 'baz', 10 | }; 11 | 12 | settings.load(config); 13 | 14 | expect(atom.config.get('foo.bar')).toBe('baz'); 15 | expect(atom.config.get('bar.foo')).toBe('baz'); 16 | }); 17 | 18 | it('loads settings with scope', () => { 19 | const config = { 20 | '*': { 21 | 'foo.bar': 'baz', 22 | }, 23 | '.js.source': { 24 | 'foo.bar': 'not-baz', 25 | }, 26 | }; 27 | 28 | settings.load(config); 29 | 30 | expect(atom.config.get('foo.bar')).toBe('baz'); 31 | expect(atom.config.get('foo.bar', { scope: ['.js.source'] })).toBe('not-baz'); 32 | }); 33 | 34 | it('loads settings with duplicate keys', () => { 35 | const config = { 36 | foo: { 37 | bar: { 38 | baz: 'overwritten', 39 | boo: 'not-duplicate', 40 | }, 41 | }, 42 | 'foo.bar': { 43 | baz: 'duplicate', 44 | }, 45 | }; 46 | 47 | settings.load(config); 48 | 49 | expect(atom.config.get('foo.bar.boo')).toBe('not-duplicate'); 50 | expect(atom.config.get('foo.bar.baz')).toBe('duplicate'); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /spec/stores/array-structure.cson: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | title: 'foo' 4 | paths: ['bar'] 5 | } 6 | { 7 | title: 'bar' 8 | paths: ['baz'] 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /spec/stores/empty.cson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danielbrodin/atom-project-manager/828730db9e20b07b0a44ca59dcbd243017fc16b3/spec/stores/empty.cson -------------------------------------------------------------------------------- /spec/stores/object-structure.cson: -------------------------------------------------------------------------------- 1 | foo: 2 | title: 'bar' 3 | paths: ['baz'] 4 | -------------------------------------------------------------------------------- /spec/stores/with-template-and-project.cson: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | title: 'foo' 4 | template: 'bar' 5 | paths: ['baz'] 6 | } 7 | { 8 | title: 'bar' 9 | group: 'foobar' 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /styles/project-manager.less: -------------------------------------------------------------------------------- 1 | // The ui-variables file is provided by base themes provided by Atom. 2 | // 3 | // See https://github.com/atom/atom-dark-ui/blob/master/stylesheets/ui-variables.less 4 | // for a full listing of what's available. 5 | @import "ui-variables"; 6 | 7 | @dev-mode-icon: "\f065"; 8 | 9 | // Edit View 10 | .project-manager-edit { 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | background: @base-background-color; 15 | 16 | h1 { 17 | color: #d7dae0; 18 | } 19 | 20 | .input-label { 21 | font-size: 1.2em; 22 | display: inline-block; 23 | width: 35%; 24 | } 25 | 26 | .input-text { 27 | display: inline-block; 28 | width: 65%; 29 | } 30 | } 31 | 32 | .project-manager {} 33 | 34 | .project-manager input { width: 100%; } 35 | 36 | .project-manager [data-path-missing="true"] { 37 | .primary-line, 38 | .secondary-line { 39 | opacity: 0.4; 40 | } 41 | 42 | .secondary-line .icon:before { 43 | color: @text-color-warning; 44 | } 45 | } 46 | 47 | .project-manager-title { 48 | color: @text-color; 49 | } 50 | 51 | .project-manager-list-group { 52 | color: @text-color-subtle; 53 | text-shadow: none; 54 | padding: 1px 2px; 55 | margin-left: 10px; 56 | background: @background-color-highlight; 57 | border-radius: 1px; 58 | 59 | .selected & { 60 | color: @text-color; 61 | } 62 | 63 | 64 | } 65 | 66 | .project-manager-devmode { 67 | float: right; 68 | 69 | &:before { 70 | content: @dev-mode-icon; 71 | color: @text-color-error; 72 | font-family: 'Octicons Regular'; 73 | font-weight: normal; 74 | font-style: normal; 75 | text-shadow: none; 76 | font-size: 14px; 77 | line-height: 1; 78 | display: inline-block; 79 | } 80 | } 81 | --------------------------------------------------------------------------------