[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[package.json]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\nnpm-debug.log\n.idea\ndist\n"
  },
  {
    "path": ".travis.yml",
    "content": "osx_image: xcode7.3\n\nsudo: required\ndist: trusty\n\nlanguage: c\n\nmatrix:\n  include:\n    - os: osx\n    - os: linux\n      env: CC=clang CXX=clang++ npm_config_clang=1\n      compiler: clang\n\ncache:\n  directories:\n  - node_modules\n  - $HOME/.electron\n  - $HOME/.cache\n\naddons:\n  apt:\n    packages:\n      - libgnome-keyring-dev\n      - icnsutils\n\ninstall:\n  - nvm install 6\n  - npm install\n  - npm prune\n\nbefore_script:\n  - |\n    if [[ \"$TRAVIS_OS_NAME\" == \"linux\" ]]; then\n      export DISPLAY=:99.0\n      sh -e /etc/init.d/xvfb start\n      sleep 3\n    fi\n\nscript:\n  - npm test\n  - npm run dist\n\nbranches:\n  except:\n    - \"/^v\\\\d+\\\\.\\\\d+\\\\.\\\\d+$/\"\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Conductor\n\nAll forms of contribution are welcomed for Conductor: bug fixes, feature pull requests, bug reports, design concepts, documentation, or any kind of feedback.\n\n## How you can contribute\n\n1. Diagnose a bug by creating an issue\n1. Suggest an improvement by creating an issue\n1. Ask a question\n1. Answer a question\n1. Provide design/UI feedback and suggestions.\n1. Fix a bug/resolve an issue\n1. Support via Gratipay for maintenance and development: https://gratipay.com/Conductor/\n\n## Code Contributions\n\nCoding style should be `standard`: \n\n[![js-standard-style](https://raw.githubusercontent.com/feross/standard/master/badge.png)](https://github.com/feross/standard)\n\n@todo: More\n"
  },
  {
    "path": "Gruntfile.js",
    "content": "module.exports = function (grunt) {\n\t/** @var {Grunt} grunt */\n\t'use strict';\n\n\t// Force use of Unix newlines\n\tgrunt.util.linefeed = '\\n';\n\n\tRegExp.quote = function (string) {\n\t\treturn string.replace(/[-\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n\t};\n\n\tvar fs = require('fs');\n\tvar path = require('path');\n\n\t// Project configuration.\n\tgrunt.initConfig({\n\n\t\t// Metadata.\n\t\tpkg: grunt.file.readJSON('package.json'),\n\t\tbanner: '/*!\\n' +\n\t\t' * ForkdIn v<%= pkg.version %> (<%= pkg.homepage %>)\\n' +\n\t\t' */\\n',\n\n\t\t// Task configuration.\n\t\tclean: {\n\t\t\tdist: 'css'\n\t\t},\n\n\t\tsass: {\n\t\t\toptions: {\n\t\t\t\tincludePaths: ['scss'],\n\t\t\t\tprecision: 6,\n\t\t\t\tsourceComments: false,\n\t\t\t\tsourceMap: true,\n\t\t\t\toutputStyle: 'expanded'\n\t\t\t},\n\t\t\tcore: {\n\t\t\t\tfiles: {\n\t\t\t\t\t'css/<%= pkg.name %>.css': 'scss/styles.scss'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\twatch: {\n\t\t\tsass: {\n\t\t\t\tfiles: 'scss/**/*.scss',\n\t\t\t\ttasks: ['dist-css']\n\t\t\t}\n\t\t}\n\n\t});\n\n\n\t// These plugins provide necessary tasks.\n\trequire('load-grunt-tasks')(grunt);\n\n\tgrunt.registerTask('sass-compile', ['sass:core']);\n\tgrunt.registerTask('dist-css', ['sass-compile']);\n\n\t// Full distribution task.\n\tgrunt.registerTask('build', ['clean:dist', 'dist-css']);\n\tgrunt.registerTask('default', ['build', 'watch']);\n};\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License\n\nCopyright (c) 2016 Matt Glaman\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# ![Conductor](build/icons/24x24.png) Conductor [![Build Status](https://travis-ci.org/mglaman/conductor.svg?branch=master)](https://travis-ci.org/mglaman/conductor) [![Build status](https://ci.appveyor.com/api/projects/status/anprg1634xsqm7g3?svg=true)](https://ci.appveyor.com/project/mglaman/conductor) [![Gratipay Team](https://img.shields.io/gratipay/team/conductor.svg)](https://gratipay.com/Conductor/)\n\n\nA user interface for Composer, the dependency management tool for PHP.\n\n![Project page](docs/images/project-page.png)\n\nConductor provides a user interface for creating and managing PHP applications using Composer.\n\n## To Use\n\n### Documentation\n\nDocumentation can be found at https://mglaman.github.io/conductor/\n\n### Releases\n\nCompiled builds are available in the list of [releases](https://github.com/mglaman/conductor/releases/latest).\n\n### Developers\n\nTo use and preview, follow these instructions while still in early development.\n\nTo clone and run this repository you'll need [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line:\n\n```bash\n# Clone this repository\ngit clone https://github.com/mglaman/conductor.git\n# Go into the repository\ncd conductor\n# Install dependencies and run the app\nnpm install && npm start\n```\n\n## Icon license\n\n![Conductor](build/icons/128x128.png)\n\nConductor: [Created with Baton by Luis Prado from the Noun Project](https://thenounproject.com/term/baton/248063). This icon is licensed as Creative Commons – Attribution (CC BY 3.0)\n\n#### License [MIT](LICENSE.md)\n"
  },
  {
    "path": "appveyor.yml",
    "content": "version: \"{build}\"\n\nskip_tags: true\nclone_folder: c:\\projects\\conductor\nclone_depth: 5\n\nplatform:\n  - x64\n\ncache:\n  - node_modules\n  - '%APPDATA%\\npm-cache'\n  - '%USERPROFILE%\\.electron'\n\ninit:\n  - git config --global core.autocrlf input\n\ninstall:\n  - ps: Install-Product node 6 x64\n  - git reset --hard HEAD\n  - npm install npm -g\n  - npm install\n  - npm prune\n\ntest_script:\n  - node --version\n  - npm --version\n  - npm test\n\nbuild_script:\n  - node --version\n  - npm --version\n  - npm run dist\n\n#test: off\n"
  },
  {
    "path": "docs/index.md",
    "content": "**Conductor**: A user interface for Composer, the dependency management tool for PHP.\n\n![Project page](images/project-page.png)\n\nConductor provides a user interface for creating and managing PHP applications using Composer.\n"
  },
  {
    "path": "docs/installation/linux.md",
    "content": "* Find the latest release: https://github.com/mglaman/conductor/releases\n* Use the .deb\n"
  },
  {
    "path": "docs/installation/macos.md",
    "content": "* Find the latest release: https://github.com/mglaman/conductor/releases\n* Download the available *.dmg file, or mac.zip\n"
  },
  {
    "path": "docs/installation/windows.md",
    "content": "* Find latest release: https://github.com/mglaman/conductor/releases\n* Downloand and run .exe\n"
  },
  {
    "path": "main.js",
    "content": "const fs = require('fs');\nconst electron = require('electron');\nconst Project = require('./src/models/Project');\nconst ProjectList = require('./src/utils/ProjectList');\nconst BrowserWindowFactory = require('./src/utils/BrowserWindowFactory');\nconst AppMenu = require('./src/utils/AppMenu');\nconst AppUpdater = require('./src/utils/AppUpdater');\nconst app = electron.app;\nconst dialog = electron.dialog;\n\nlet windowIcon = __dirname + '/build/icons/icon.svg';\nlet windowSize = 1024;\nlet debug = false;\nlet projectList = new ProjectList();\nlet mainWindow = null;\nlet projectWindow = null;\n\n/**\n * @type {Project}\n */\nlet activeProject = null;\nlet viewingPackage = null;\n\n/**\n * Main window for the app\n */\nfunction createMainWindow() {\n\tmainWindow = BrowserWindowFactory.createWindow(`file://${__dirname}/src/windows/index.html`, windowSize, windowIcon);\n\tif (debug) mainWindow.webContents.openDevTools();\n\tmainWindow.on('closed', () => {\n\t\tmainWindow = null\n\t})\n}\n\n/**\n * Open a project in a new window\n *\n * @param folder\n */\nfunction createProjectWindow(folder) {\n\ttry {\n\t\tactiveProject = new Project(folder);\n\t\tprojectWindow = BrowserWindowFactory.createWindow(`file://${__dirname}/src/windows/project/project.html`, windowSize, windowIcon);\n\t\tif (debug) projectWindow.webContents.openDevTools();\n\n\t\tprojectWindow.on('show', () => {\n\t\t\tif (mainWindow !== null) {\n\t\t\t\tmainWindow.close();\n\t\t\t}\n\t\t});\n\t\tprojectWindow.on('closed', () => {\n\t\t\tactiveProject = null;\n\t\t\tprojectWindow = null;\n\t\t\tif (mainWindow === null) {\n\t\t\t\tcreateMainWindow();\n\t\t\t}\n\t\t});\n\t} catch (e) {\n\t\tconsole.error(e);\n\t\tdialog.showMessageBox({\n\t\t\t'type': 'error',\n\t\t\t'buttons': [],\n\t\t\t'message': 'There is was an error parsing the composer.json'\n\t\t});\n\t}\n}\n\n// This method will be called when Electron has finished\n// initialization and is ready to create browser windows.\n// Some APIs can only be used after this event occurs.\napp.on('ready', () => {\n\trefreshProjectList();\n\n\tAppMenu.setProjects(projectList.getList());\n\tAppMenu.setMenu();\n\tcreateMainWindow();\n\tnew AppUpdater();\n});\n\n// Quit when all windows are closed.\napp.on('window-all-closed', function () {\n\tif (process.platform !== 'darwin') {\n\t\tapp.quit()\n\t}\n});\n\napp.on('activate', function () {\n\tif (mainWindow === null && projectWindow === null) {\n\t\tcreateMainWindow()\n\t}\n});\n\n/**\n * Add a project to the ProjectsList from a chosen directory, then open that project\n * @param folder\n * @void\n */\nconst fromNewProject = function (folder) {\n\tconst composerJson = require(folder + '/composer.json');\n\tprojectList.addProject(folder, composerJson.name);\n\tcreateProjectWindow(folder);\n};\n\n/**\n * Open an existing project directory\n * @void\n */\nconst openDirectory = function () {\n\tlet folder = dialog.showOpenDialog(mainWindow, {\n\t\tproperties: ['openDirectory'],\n\t});\n\tif (!folder) {\n\t\treturn;\n\t}\n\tfs.exists(folder + '/composer.json', function (exists) {\n\t\tif (exists) {\n\t\t\tconst composerJson = require(folder + '/composer.json');\n\t\t\tprojectList.addProject(folder, composerJson.name);\n\t\t\tcreateProjectWindow(folder[0]);\n\t\t} else {\n\t\t\tdialog.showMessageBox(mainWindow, {\n\t\t\t\t'type': 'error',\n\t\t\t\t'buttons': [],\n\t\t\t\t'message': 'There is no composer.json in that directory'\n\t\t\t});\n\t\t}\n\t});\n};\n\n/**\n * Open a new window for a project\n * @param path\n * @void\n */\nconst openProject = function (path) {\n\tcreateProjectWindow(path);\n};\n\n/**\n * @returns {Project}\n */\nconst getActiveProject = () => {\n\treturn activeProject;\n};\n\n/**\n * @void\n */\nconst refreshProjectList = () => {\n\ttry {\n\t\tprojectList.refreshList();\n\t} catch (e) {\n\t\t// This has issues when first run, or JSON missing.\n\t}\n};\n\n/**\n * @returns {ProjectList}\n */\nconst getProjectList = () => {\n\treturn projectList;\n};\n\n/**\n * @returns {Package}\n */\nconst getViewingPackage = () => {\n\treturn viewingPackage;\n};\n\nmodule.exports = {\n\topenDirectory,\n\topenProject,\n\tgetActiveProject,\n\trefreshProjectList,\n\tgetProjectList,\n\tgetViewingPackage,\n\tfromNewProject\n}\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: Conductor Documentation\n\nrepo_url: https://github.com/mglaman/conductor\nsite_description: 'Conductor - A cross-platform Composer user interface'\ntheme: readthedocs\n\nmarkdown_extensions:\n  - toc:\n        permalink: True\n\npages:\n  - Home: 'index.md'\n  - Installation:\n    - 'macOS': 'installation/macos.md'\n    - 'Windows': 'installation/windows.md'\n    - 'Linux': 'installation/linux.md'\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"conductor\",\n  \"version\": \"0.1.6\",\n  \"description\": \"A Composer user interface\",\n  \"main\": \"main.js\",\n  \"scripts\": {\n    \"start\": \"electron .\",\n    \"pack\": \"build --dir\",\n    \"dist\": \"build\",\n    \"dist-all\": \"build -mwl\",\n    \"test\": \"mocha\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/mglaman/conductor.git\"\n  },\n  \"keywords\": [\n    \"composer\",\n    \"php\"\n  ],\n  \"author\": \"Matt Glaman <nmd.matt@gmail.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/mglaman/conductor/issues\"\n  },\n  \"homepage\": \"https://github.com/mglaman/conductor\",\n  \"build\": {\n    \"appId\": \"com.mglaman.conductor\",\n    \"asar\": false,\n    \"productName\": \"Conductor\",\n    \"copyright\": \"© Matt Glaman\",\n    \"extraResources\": [\n      \"composer.phar\"\n    ],\n    \"mac\": {\n      \"publish\": [\n        \"github\"\n      ],\n      \"target\": [\n        \"dmg\",\n        \"zip\"\n      ],\n      \"category\": \"public.app-category.developer-tools\"\n    },\n    \"win\": {\n      \"publish\": [\n        \"github\"\n      ],\n      \"target\": [\n        \"zip\",\n        \"nsis\"\n      ]\n    },\n    \"linux\": {\n      \"publish\": [\n        \"github\"\n      ],\n      \"target\": [\n        \"deb\",\n        \"rpm\",\n        \"zip\"\n      ],\n      \"category\": \"Utility\",\n      \"packageCategory\": \"Utility\",\n      \"synopsis\": \"A Composer user interface\"\n    }\n  },\n  \"devDependencies\": {\n    \"autoprefixer\": \"^6.0.3\",\n    \"chai\": \"^3.5.0\",\n    \"chai-as-promised\": \"^6.0.0\",\n    \"electron\": \"^9.4.0\",\n    \"electron-builder\": \"^7.14.2\",\n    \"grunt\": \"^1.0.1\",\n    \"grunt-contrib-clean\": \"^1.0.0\",\n    \"grunt-contrib-watch\": \"^1.0.0\",\n    \"grunt-sass\": \"^1.0.0\",\n    \"grunt-scss-lint\": \"^0.3.8\",\n    \"load-grunt-tasks\": \"^3.4.0\",\n    \"mocha\": \"^3.4.2\",\n    \"spectron\": \"^3.7.2\"\n  },\n  \"dependencies\": {\n    \"electron-config\": \"^0.2.1\",\n    \"electron-is-dev\": \"^0.1.2\",\n    \"electron-updater\": \"^1.16.0\",\n    \"font-awesome\": \"^4.6.3\",\n    \"vue\": \"^2.4.2\",\n    \"vue-router\": \"^2.7.0\",\n    \"vuetify\": \"^0.14.5\",\n    \"vuex\": \"^2.3.1\"\n  }\n}\n"
  },
  {
    "path": "public/css/conductor.css",
    "content": "/* Color definitions */\n/* Semantic definitions */\n.flex {\n  display: flex;\n}\n\n.flex--row {\n  flex-direction: row;\n}\n\n.flex--column {\n  flex-direction: column;\n}\n\n.flex--grow {\n  flex-grow: 1;\n}\n\nhtml, body {\n  margin: 0;\n  padding: 0;\n  height: 100%;\n  max-height: 100vh;\n  display: flex;\n  flex-direction: column;\n}\n\nhtml {\n  font-size: 16px;\n}\n\nbody {\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n  font-size: 1rem;\n  line-height: 1.5;\n  background: #fff;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  margin-top: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n}\n\np {\n  margin-top: 0;\n}\n\ninput {\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n  font-size: 1rem;\n  padding: 0.5rem;\n  margin: 0.25rem;\n  border-radius: 0.25rem;\n  border: 1px solid #d5d5d5;\n}\n\ndetails {\n  padding: 0 1rem;\n}\n\ndetails:focus {\n  outline: 0;\n}\n\ndetails summary {\n  background: #f5f5f5;\n  border: 1px solid #e5e5e5;\n  font-size: 1.25rem;\n  padding: 0.5rem 0;\n  margin: 0 -0.75rem;\n}\n\ndetails summary:focus {\n  outline: 0;\n}\n\nbutton {\n  cursor: pointer;\n  border: 0;\n  background: transparent;\n  font-size: 1rem;\n  padding: 0;\n}\n\nbutton:hover {\n  color: #4078c0;\n}\n\n.main__actions {\n  align-items: flex-start;\n}\n\n.main__actions button {\n  margin-bottom: 0.5rem;\n}\n\n.main__projects-list {\n  flex: 1;\n  background: #f5f5f5;\n  overflow: scroll;\n}\n\n.main__projects-list ::-webkit-details-marker {\n  display: none;\n}\n\n.main__projects-list summary {\n  border: 0;\n}\n\n.main__projects-list ul {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n\n.main__projects-list ul li {\n  display: block;\n  padding: 0.25rem 0.5rem 0.25rem 0;\n  border-bottom: solid 1px #e5e5e5;\n}\n\n.main__projects-list button {\n  border: 0;\n  background: transparent;\n  font-size: 1rem;\n  padding: 0;\n}\n\n.project__title {\n  padding: 0.5rem 0;\n}\n\n.project__title h1 {\n  flex: 1;\n}\n\n.project__sidebar {\n  flex: 0 0 35%;\n  max-width: 35%;\n  overflow-y: scroll;\n  background: white;\n  border-right: 1px solid #f5f5f5;\n}\n\n.project__sidebar ul {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n\n.project__sidebar ul li {\n  display: block;\n  padding: 0.25rem 0.5rem;\n  border-bottom: solid 1px #e5e5e5;\n  font-size: 90%;\n}\n\n.project__sidebar ul li:last-child {\n  border-bottom: 0;\n}\n\n.project__sidebar ul li:hover {\n  background: #4078c0;\n  color: #fff;\n}\n\n.button__actions button {\n  display: block;\n  padding: 0.5rem;\n  background-image: linear-gradient(#f5f5f5, #d5d5d5);\n  border: 1px solid #e5e5e5;\n  border-radius: 3px;\n  flex: 1;\n}\n\n.button__actions button:focus {\n  outline: 0;\n  border: 1px solid black;\n}\n\n.button__actions button:hover {\n  background: #e3e3e3;\n}\n\n.project__information {\n  padding: 0 1rem;\n}\n\n.project__output {\n  flex: 1;\n  border: 0;\n  display: flex;\n  flex-direction: column;\n  overflow: scroll;\n}\n\n.project__output p {\n  padding: 1px;\n}\n\n::-webkit-scrollbar {\n  display: none;\n}\n\n.hidden {\n  display: none;\n}\n\n.project__output {\n  font-family: monospace;\n  font-size: 80%;\n  background: #111;\n  color: #f5f5f5;\n}\n\n.project__dependencies-list li {\n  cursor: pointer;\n}\n\n.window__create-project .button__actions {\n  margin-top: 1rem;\n}\n\n.window__create-project button {\n  display: block;\n  padding: 0.35rem;\n  background-image: linear-gradient(#f5f5f5, #d5d5d5);\n  border: 1px solid #e5e5e5;\n  border-radius: 3px;\n}\n\n.window__create-project button:focus {\n  outline: 0;\n  border: 1px solid #aaa;\n}\n\n.window__create-project button:hover {\n  background: #e3e3e3;\n}\n\n.window__create-project #project-destination {\n  cursor: pointer;\n}\n\n.main__landing {\n  background: linear-gradient(135deg, #3700aa 0%, #4500d4 22%, #6c00e9 57%, #992aff 100%);\n  color: #fff;\n}\n\n.main__landing button {\n  color: #fff;\n  font-weight: normal;\n}\n\n.window__main--header {\n  margin-top: 2rem;\n  margin-bottom: 1rem;\n  align-items: center;\n}\n\n.window__main--header h1 {\n  margin-bottom: 0;\n  font-weight: normal;\n}\n\n.hidden {\n  display: none !important;\n}\n\n.log--error {\n  background: #A94443;\n  color: white;\n}\n\n.log--output {\n  color: #FFFF91;\n}\n\n/*# sourceMappingURL=conductor.css.map */"
  },
  {
    "path": "public/scss/_flex.scss",
    "content": ".flex {\n  display: flex;\n}\n.flex--row {\n  flex-direction: row;\n}\n.flex--column {\n  flex-direction: column;\n}\n.flex--grow {\n  flex-grow: 1;\n}\n"
  },
  {
    "path": "public/scss/_vars.scss",
    "content": "/* Color definitions */\n$light-gray: #f5f5f5;\n$middle-gray: #d5d5d5;\n$dark-gray: #e5e5e5;\n$blue: #4078c0;\n$white: #fff;\n$black: #111;\n\n/* Semantic definitions */\n$bg-color: $white;\n$details-summary-bg: $light-gray;\n\n$fontstack: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n"
  },
  {
    "path": "public/scss/styles.scss",
    "content": "@import \"vars\";\n@import \"flex\";\n\nhtml, body {\n  margin: 0;\n  padding: 0;\n  height: 100%;\n  max-height: 100vh;\n  display: flex;\n  flex-direction: column;\n}\n\nhtml {\n  font-size: 16px;\n}\n\nbody {\n  font-family: $fontstack;\n  font-size: 1rem;\n  line-height: 1.5;\n  background: $bg-color;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  margin-top: 0;\n  font-family: $fontstack;\n}\n\np {\n  margin-top: 0;\n}\n\ninput {\n  font-family: $fontstack;\n  font-size: 1rem;\n  padding: 0.5rem;\n  margin: 0.25rem;\n  border-radius: 0.25rem;\n  border: 1px solid $middle-gray;\n}\n\ndetails {\n  padding: 0 1rem;\n  &:focus {\n\toutline: 0;\n  }\n  summary {\n\tbackground: $details-summary-bg;\n\tborder: 1px solid $dark-gray;\n\tfont-size: 1.25rem;\n\tpadding: 0.5rem 0;\n\tmargin: 0 -0.75rem;\n\t&:focus {\n\t  outline: 0;\n\t}\n  }\n}\n\nbutton {\n  cursor: pointer;\n  border: 0;\n  background: transparent;\n  font-size: 1rem;\n  padding: 0;\n  &:hover {\n\tcolor: $blue;\n  }\n}\n\n.main__actions {\n  align-items: flex-start;\n  button {\n\tmargin-bottom: 0.5rem;\n  }\n}\n\n.main__projects-list {\n  flex: 1;\n  background: $light-gray;\n  overflow: scroll;\n  ::-webkit-details-marker { display:none; }\n  summary {\n\tborder:0;\n  }\n  ul {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n\tli {\n\t  display: block;\n\t  padding: 0.25rem 0.5rem 0.25rem 0;\n\t  border-bottom: solid 1px $dark-gray;\n\t}\n  }\n  button {\n\tborder: 0;\n\tbackground: transparent;\n\tfont-size: 1rem;\n\tpadding: 0;\n  }\n}\n\n.project__title {\n  padding: 0.5rem 0;\n  h1 {\n\tflex: 1;\n  }\n}\n\n.project__sidebar {\n  flex: 0 0 35%;\n  max-width: 35%;\n  overflow-y: scroll;\n  background: lighten($light-gray, 50%);\n  border-right: 1px solid $light-gray;\n  ul {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n\tli {\n\t  display: block;\n\t  padding: 0.25rem 0.5rem;\n\t  border-bottom: solid 1px $dark-gray;\n\t  font-size: 90%;\n\t  &:last-child {\n\t\tborder-bottom: 0;\n\t  }\n\t  &:hover {\n\t\tbackground: $blue;\n\t\tcolor: #fff;\n\t  }\n\t}\n  }\n}\n\n.button__actions {\n  button {\n\tdisplay: block;\n\tpadding: 0.5rem;\n\tbackground-image: linear-gradient($light-gray, $middle-gray);\n\tborder: 1px solid $dark-gray;\n\tborder-radius: 3px;\n\t&:focus {\n\t  outline: 0;\n\t  border: 1px solid darken($dark-gray, 100);\n\t}\n\tflex: 1;\n\t&:hover {\n\t  background: darken($dark-gray, .75);\n\t}\n  }\n}\n\n.project__information {\n  padding: 0 1rem;\n}\n\n.project__output {\n  flex: 1;\n  border: 0;\n  display: flex;\n  flex-direction: column;\n  overflow: scroll;\n  p {\n\tpadding: 1px;\n  }\n}\n\n::-webkit-scrollbar {\n  display: none;\n}\n\n.hidden {\n  display: none;\n}\n\n.project__output {\n  font-family: monospace;\n  font-size: 80%;\n  background: $black;\n  color: $light-gray;\n}\n\n.project__dependencies-list li {\n  cursor: pointer;\n}\n\n.window__create-project {\n  .button__actions {\n\tmargin-top: 1rem;\n  }\n  button {\n\tdisplay: block;\n\tpadding: 0.35rem;\n\tbackground-image: linear-gradient($light-gray, $middle-gray);\n\tborder: 1px solid $dark-gray;\n\tborder-radius: 3px;\n\t&:focus {\n\t  outline: 0;\n\t  border: 1px solid #aaa;\n\t}\n\t&:hover {\n\t  background: darken($dark-gray, .75);\n\t}\n  }\n  #project-destination {\n\tcursor: pointer;\n  }\n}\n.main__landing {\n  background: linear-gradient(135deg, #3700aa 0%,#4500d4 22%,#6c00e9 57%,#992aff 100%);\n  color: $white;\n  button {\n\tcolor: $white;\n\tfont-weight: normal;\n  }\n}\n\n.window__main--header {\n  margin-top: 2rem;\n  margin-bottom: 1rem;\n  align-items: center;\n  h1 {\n\tmargin-bottom: 0;\n\tfont-weight: normal;\n  }\n}\n\n.hidden {\n  display: none !important;\n}\n\n.log--error {\n  background: #A94443;\n  color: white;\n}\n.log--output {\n  color: #FFFF91;\n}\n"
  },
  {
    "path": "src/components/ComposerFrame.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst remote = require('electron').remote;\nconst dialog = remote.dialog;\nconst mainProcess = remote.require('./main');\nconst thisWindow = remote.getCurrentWindow();\nconst Composer = require('../utils/Composer');\n\nmodule.exports = {\n\ttemplate: `\n\t\t<v-card>\n\t\t\t<v-card-text>\n\t\t\t\t<v-btn light \n\t\t\t\t\tv-if=\"type == 'create'\"\n\t\t\t\t\t@click=\"composerExecute('create')\">\n\t\t\t\t\tCreate project!\n\t\t\t\t\t<i class=\"fa fa-spin fa-circle-o-notch\" v-if=\"doing == 'create'\"></i>\n\t\t\t\t</v-btn>\n\t\t\t\t<v-btn light\n\t\t\t\t\tv-if=\"type == 'project'\"\n\t\t\t\t  @click=\"composerExecute('install')\">\n\t\t\t\t\tInstall\n\t\t\t\t\t<i class=\"fa fa-spin fa-circle-o-notch\" v-if=\"doing == 'install'\"></i>\n\t\t\t\t</v-btn>\n\t\t\t\t<v-btn light \n\t\t\t\t\tv-if=\"type == 'project'\"\n\t\t\t\t\t@click=\"composerExecute('validate')\">\n\t\t\t\t\tValidate\n\t\t\t\t\t<i class=\"fa fa-spin fa-circle-o-notch\" v-if=\"doing == 'validate'\"></i>\n\t\t\t\t</v-btn>\n\t\t\t\t<v-btn light\n\t\t\t\t\tv-if=\"type == 'project'\"\n\t\t\t\t \t@click=\"composerExecute('updateProject')\">\n\t\t\t\t\tUpdate\n\t\t\t\t\t<i class=\"fa fa-spin fa-circle-o-notch\" v-if=\"doing == 'updateProject'\"></i>\n\t\t\t\t</v-btn>\n\t\t\t\t<v-btn light\n\t\t\t\t\tv-if=\"type == 'package'\"\n\t\t\t\t\t@click=\"composerExecute('show')\">\n\t\t\t\t\tShow\n\t\t\t\t\t<i class=\"fa fa-spin fa-circle-o-notch\" v-if=\"doing == 'show'\"></i>\n\t\t\t\t</v-btn>\n\t\t\t\t<v-btn light \n\t\t\t\t\tv-if=\"type == 'package'\"\n\t\t\t\t\t@click=\"composerExecute('updatePackage')\">\n\t\t\t\t\tUpdate\n\t\t\t\t\t<i class=\"fa fa-spin fa-circle-o-notch\" v-if=\"doing == 'updatePackage'\"></i>\n\t\t\t\t</v-btn>\n\t\t\t\t<v-btn light \n\t\t\t\t\tv-if=\"type == 'package'\"\n\t\t\t\t\t@click=\"composerExecute('remove')\">\n\t\t\t\t\tRemove\n\t\t\t\t\t<i class=\"fa fa-spin fa-circle-o-notch\" v-if=\"doing == 'remove'\"></i>\n\t\t\t\t</v-btn>\n\t\t\t\t<!--<button class=\"flex\" id=\"action-composer-add\">Add <i class=\"fa fa-spin fa-circle-o-notch hidden\"></i></button>-->\n\t\t\t</v-card-text>\n\t\t\t<div class=\"project__output\" id=\"composer-output\">\n\t\t\t\t<p v-for=\"line in composerOutLines\" :class=\"line.className\">\n\t\t\t\t\t{{ line.text }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</v-card>\n\t`,\n\n\tdata: function() {\n\t\treturn {\n\t\t\tdoing: '',\n\t\t\tcomposerOutLines: [],\n\t\t}\n\t},\n\tprops: {\n\t\ttype: {\n\t\t\tdefault: '', // project | package | create\n\t\t\ttype: String\n\t\t},\n\t\tproject: {\n\t\t\tdefault: null,\n\t\t\ttype: Object,\n\t\t},\n\t\tpackage: {\n\t\t\tdefault: null,\n\t\t\ttype: Object,\n\t\t},\n\t\tnewProjectDetails: {\n\t\t\tdefault: null,\n\t\t}\n\t},\n\tmethods: {\n\t\tcomposerExecute(command) {\n\t\t\tthis.doing = command;\n\t\t\tlet process = null;\n\t\t\tlet composer = null;\n\t\t\tlet activeProject = null;\n\t\t\tlet projectInstalled = null;\n\n\t\t\tswitch( this.type )\n\t\t\t{\n\t\t\t\t/*\n\t\t\t\t * Project actions\n\t\t\t\t */\n\t\t\t\tcase 'project':\n\t\t\t\t\tactiveProject = mainProcess.getActiveProject();\n\t\t\t\t\tprojectInstalled = activeProject.isInstalled();\n\t\t\t\t\tcomposer =  new Composer(activeProject.getPath());\n\n\t\t\t\t\tswitch( command ) {\n\t\t\t\t\t\tcase 'install':\n\t\t\t\t\t\t\tprocess = composer.install();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'updateProject':\n\t\t\t\t\t\t\tprocess = composer.update(null);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'validate':\n\t\t\t\t\t\t\tprocess = composer.validate();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t * Package actions\n\t\t\t\t */\n\t\t\t\tcase 'package':\n\t\t\t\t\tcomposer = new Composer(mainProcess.getActiveProject().getPath());\n\n\t\t\t\t\tswitch( command ){\n\t\t\t\t\t\t// package\n\t\t\t\t\t\tcase 'updatePackage':\n\t\t\t\t\t\t\tprocess = composer.update(this.package.__get('name'));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'remove':\n\t\t\t\t\t\t\tprocess = composer.remove(this.package.getName());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'show':\n\t\t\t\t\t\t\tprocess = composer.show(this.package.getName());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t * Create project actions\n\t\t\t\t */\n\t\t\t\tcase 'create':\n\t\t\t\t\tcomposer = new Composer(remote.app.getAppPath());\n\n\t\t\t\t\tswitch( command ){\n\t\t\t\t\t\t// create project\n\t\t\t\t\t\tcase 'create':\n\t\t\t\t\t\t\tprocess = composer.createProject(this.newProjectDetails.packageName, this.newProjectDetails.destination);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (composer && process){\n\t\t\t\tprocess.stdout.on('data', (data) => {\n\t\t\t\t\tthis.composerOutLines.push({\n\t\t\t\t\t\ttext: String(data),\n\t\t\t\t\t\tclassName: 'log--output'\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tprocess.stderr.on('data', (data) => {\n\t\t\t\t\tthis.composerOutLines.push({\n\t\t\t\t\t\ttext: String(data),\n\t\t\t\t\t\tclassName: 'log--output'\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tprocess.on('error', (data) => {\n\t\t\t\t\tthis.doing = '';\n\t\t\t\t\tthis.composerOutLines.push({\n\t\t\t\t\t\ttext: String(data),\n\t\t\t\t\t\tclassName: 'log--error'\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tprocess.on('close', (code) => {\n\t\t\t\t\tthis.doing = '';\n\n\t\t\t\t\t// From project\n\t\t\t\t\tif ( this.project && this.type === 'project' ){\n\t\t\t\t\t\tif (code === 0) {\n\t\t\t\t\t\t\tactiveProject.refreshData();\n\t\t\t\t\t\t\tprojectInstalled = activeProject.isInstalled();\n\t\t\t\t\t\t\t// @todo get some kind of binding to not need to do this.\n\t\t\t\t\t\t\t// thisWindow.reload();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// from Create project\n\t\t\t\t\tif ( this.type === 'create' ){\n\t\t\t\t\t\tif (code === 0 && fs.existsSync(this.newProjectDetails.destination + '/composer.json')) {\n\t\t\t\t\t\t\tmainProcess.fromNewProject(this.newProjectDetails.destination);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/CreateProjectForm.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst remote = require('electron').remote;\nconst dialog = remote.dialog;\nconst mainProcess = remote.require('./main');\nconst thisWindow = remote.getCurrentWindow();\nconst Composer = require('../utils/Composer');\nconst ComposerFrame = require('./ComposerFrame');\n\nmodule.exports = {\n\ttemplate: `\n\t\t<v-card>\n\t\t\t<v-card-text>\n\t\t\t\t<v-container fluid>\n\t\t\t\t\t<v-layout row>\n\t\t\t\t\t\t<v-text-field\n\t\t\t\t\t\t\tv-model=\"packageName\"\n\t\t\t\t\t\t\tname=\"packageName\"\n\t\t\t\t\t\t\tlabel=\"Package Name\"\n\t\t\t\t\t\t\thint=\"vendor/package\"\n\t\t\t\t\t\t\tpersistent-hint\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t></v-text-field>\n\t\t\t\t\t</v-layout>\n\t\t\t\t\t<v-layout row>\n\t\t\t\t\t\t<v-text-field\n\t\t\t\t\t\t\tv-model=\"projectName\"\n\t\t\t\t\t\t\tname=\"projectName\"\n\t\t\t\t\t\t\tlabel=\"Project Name\"\n\t\t\t\t\t\t\thint=\"some-dir\"\n\t\t\t\t\t\t\tpersistent-hint\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t></v-text-field>\n\t\t\t\t\t</v-layout>\n\t\t\t\t\t<v-layout row>\n\t\t\t\t\t\t<v-flex xs8>\n\t\t\t\t\t\t\t<v-text-field\n\t\t\t\t\t\t\t\tv-model=\"destinationFolder\"\n\t\t\t\t\t\t\t\tname=\"destinationFolder\"\n\t\t\t\t\t\t\t\tlabel=\"Destination Folder\"\n\t\t\t\t\t\t\t\tdisabled\n\t\t\t\t\t\t\t></v-text-field>\n\t\t\t\t\t\t</v-flex>\n\t\t\t\t\t\t<v-flex xs4>\n\t\t\t\t\t\t\t<v-btn light\n\t\t\t\t\t\t\t\t@click=\"projectDestinationBrowse\">Browse <i class=\"fa fa-search\"></i></v-btn>\n\t\t\t\t\t\t</v-flex>\n\t\t\t\t\t</v-layout>\n\t\t\t\t\t<v-layout row>\n\t\t\t\t\t\t<v-text-field\n\t\t\t\t\t\t\tv-model=\"destination\"\n\t\t\t\t\t\t\tlabel=\"Destination\" \n\t\t\t\t\t\t\tdisabled\n\t\t\t\t\t\t></v-text-field>\n\t\t\t\t\t</v-layout>\n\t\t\t\t</v-container>\n\t\t\t</v-card-text>\n\t\t\t<composer-frame :type=\"'create'\" :newProjectDetails=\"{packageName,projectName,description,destinationFolder,destination}\"></composer-frame>\n\t\t</v-card>\n\t`,\n\tcomponents: {\n\t\t'composer-frame': ComposerFrame\n\t},\n\tdata: function(){\n\t\treturn {\n\t\t\tpackageName: '',\n\t\t\tprojectName: '',\n\t\t\tdescription: '',\n\t\t\tdestinationFolder: '',\n\t\t}\n\t},\n\tcomputed: {\n\t\tdestination(){\n\t\t\treturn this.destinationFolder + '/' + this.projectName;\n\t\t}\n\t},\n\tmethods: {\n\t\tprojectDestinationBrowse (){\n\t\t\tlet folder = dialog.showOpenDialog(thisWindow, {\n\t\t\t\tproperties: ['openDirectory'],\n\t\t\t});\n\t\t\tif (!folder) {\n\t\t\t\tthis.destinationFolder = '';\n\t\t\t}\n\t\t\tthis.destinationFolder = folder;\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "src/components/MainLayout.js",
    "content": "'use strict';\n\nconst MainNavigation = require('./MainNavigation');\n\nmodule.exports = {\n\ttemplate: `\n\t\t<v-app standalone>\n\t\t\t<v-navigation-drawer permanent light>\n\t\t\t\t<v-toolbar flat class=\"transparent\">\n\t\t\t\t\t<v-list class=\"pa-0\">\n\t\t\t\t\t\t<v-list-tile avatar tag=\"ul\">Conductor</v-list-tile>\n\t\t\t\t\t</v-list>\n\t\t\t\t</v-toolbar>\n\t\t\t\t<v-divider></v-divider>\n\t\t\t\t<main-navigation></main-navigation>\n\t\t\t</v-navigation-drawer>\n\t\t\t<v-toolbar class=\"cyan\" dark>\n\t\t\t\t<v-toolbar-title>{{ pageTitle }}</v-toolbar-title>\n\t\t\t</v-toolbar>\n\t\t\t<main>\n\t\t\t\t<v-container fluid>\n\t\t\t\t\t<router-view></router-view>\n\t\t\t\t</v-container>\n\t\t\t</main>\n\t\t</v-app>\n\t`,\n\n\tcomponents: {\n\t\t'main-navigation': MainNavigation\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\t// settings for the vuetify layout\n\t\t\tdrawer: null,\n\t\t\tright: null,\n\t\t}\n\t},\n\tcomputed: {\n\t\tpageTitle() {\n\t\t\treturn this.$store.getters.pageTitle;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/MainNavigation.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst remote = require('electron').remote;\nconst mainProcess = remote.require('./main');\n\nmodule.exports = {\n\ttemplate: `\n\t\t<v-list dense class=\"pt-0\">\n\t\t\t<v-list-tile to=\"recent-projects\" :router=\"true\">\n\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t<v-icon>list</v-icon>\n\t\t\t\t</v-list-tile-action>\n\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t<v-list-tile-title id=\"recent-projects\">Recent projects</v-list-tile-title>\n\t\t\t\t</v-list-tile-content>\n\t\t\t</v-list-tile>\n\t\t\t<v-list-tile @click=\"existingProject\">\n\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t<v-icon>folder_open</v-icon>\n\t\t\t\t</v-list-tile-action>\n\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t<v-list-tile-title id=\"open-project\">Add existing project</v-list-tile-title>\n\t\t\t\t</v-list-tile-content>\n\t\t\t</v-list-tile>\n\t\t\t<v-list-tile to=\"create-project\" :router=\"true\">\n\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t<v-icon>create_new_folder</v-icon>\n\t\t\t\t</v-list-tile-action>\n\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t<v-list-tile-title id=\"create-project\">Create new project</v-list-tile-title>\n\t\t\t\t</v-list-tile-content>\n\t\t\t</v-list-tile>\n\t\t\t<v-list-tile @click=\"globalProject\" v-if=\"globalComposerFileExists\">\n\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t<v-icon>public</v-icon>\n\t\t\t\t</v-list-tile-action>\n\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t<v-list-tile-title id=\"global-composer\">Global composer</v-list-tile-title>\n\t\t\t\t</v-list-tile-content>\n\t\t\t</v-list-tile>\n\t\t\t<v-list-tile to=\"settings\" :router=\"true\">\n\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t<v-icon>settings</v-icon>\n\t\t\t\t</v-list-tile-action>\n\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t<v-list-tile-title id=\"open-settings\">Settings</v-list-tile-title>\n\t\t\t\t</v-list-tile-content>\n\t\t\t</v-list-tile>\n\t\t</v-list>\n\t`,\n\tcomputed: {\n\t\tglobalComposerFileExists() {\n\t\t\treturn fs.existsSync(remote.app.getPath('home') + '/.composer');\n\t\t}\n\t},\n\tmethods: {\n\t\texistingProject: () => {\n\t\t\tmainProcess.openDirectory();\n\t\t},\n\t\tglobalProject: () => {\n\t\t\tmainProcess.openProject(remote.app.getPath('home') + '/.composer');\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "src/components/PackageDetails.js",
    "content": "'use strict';\n\nconst ComposerFrame = require('./ComposerFrame');\n\nmodule.exports = {\n\ttemplate: `\n\t\t<v-card>\n\t\t\t<v-card-text>\n\t\t\t\t<ul class=\"package__details flex flex--column\">\n\t\t\t\t\t<li class=\"package__details--item\">\n\t\t\t\t\t\t<span class=\"package__details--label\">Version</span>\n\t\t\t\t\t\t<span class=\"package__details--value\">{{ package.json.version }}</span>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li class=\"package__details--item\" v-if=\"package.json.homepage\">\n\t\t\t\t\t\t<span class=\"package__details--label\">Homepage</span>\n\t\t\t\t\t\t<span class=\"package__details--value\">{{ package.json.homepage }}</span>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li class=\"package__details--item\">\n\t\t\t\t\t\t<span class=\"package__details--value\">{{ package.json.description }}</span>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li v-if=\"package.packages\">\n\t\t\t\t\t\t<span>Requirements</span>\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t<li v-for=\"(version, dependency) in package.packages\">\n\t\t\t\t\t\t\t\t{{ dependency }}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li v-if=\"package.packagesDev\">\n\t\t\t\t\t\t<span>Dev Requirements</span>\n\t\t\t\t\t\t<ul id=\"package-dev-dependencies\">\n\t\t\t\t\t\t\t<li v-for=\"(version, dependency) in package.packagesDev\">\n\t\t\t\t\t\t\t\t{{ dependency }}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</v-card-text>\n\t\t\t<composer-frame :type=\"'package'\" :package=\"package\"></composer-frame>\n\t\t</v-card>\n\t`,\n\tcomponents: {\n\t\t'composer-frame': ComposerFrame\n\t},\n\tcomputed: {\n\t\tpackage() {\n\t\t\treturn this.$store.getters.activeProject.getLock().getPackage(this.$route.params.packagePath);\n\t\t}\n\t},\n\tcreated() {\n\t\tthis.$store.commit('setPageTitle', this.package.json.name);\n\t},\n\twatch: {\n\t\t'$route' () {\n\t\t\tthis.$store.commit('setPageTitle', this.package.json.name);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/ProjectDetails.js",
    "content": "'use strict';\n\nconst ComposerFrame = require('./ComposerFrame');\n\nmodule.exports = {\n\ttemplate: `\n\t\t<v-card>\n\t\t\t<v-card-text>\n\t\t\t\t<div>\n\t\t\t\t\t<p v-if=\"project.json.homepage\">{{ project.json.homepage }}</p>\n\t\t\t\t\t<p>{{ project.json.description }}</p>\n\t\t\t\t</div>\n\t\t\t</v-card-text>\n\t\t\t<composer-frame :type=\"'project'\" :project=\"project\"></composer-frame>\n\t\t</v-card>\n\t`,\n\tcomponents: {\n\t\t'composer-frame': ComposerFrame\n\t},\n\tcomputed: {\n\t\tproject() {\n\t\t\treturn this.$store.getters.activeProject;\n\t\t},\n\t},\n}\n"
  },
  {
    "path": "src/components/ProjectLayout.js",
    "content": "'use strict';\n\nconst ProjectNavigation = require('../components/ProjectNavigation');\nconst mainProcess = require('electron').remote.require('./main');\n\nmodule.exports = {\n\ttemplate: `\n\t\t<v-app id=\"app\" standalone>\n\t\t\t<v-navigation-drawer permanent light>\n\t\t\t\t<v-toolbar flat class=\"transparent\">\n\t\t\t\t\t<v-list class=\"pa-0\">\n\t\t\t\t\t\t<v-list-tile avatar tag=\"ul\" :to=\"project\" :router=\"true\">{{ project.json.name }}</v-list-tile>\n\t\t\t\t\t</v-list>\n\t\t\t\t</v-toolbar>\n\t\t\t\t<v-divider></v-divider>\n\t\t\t\t<project-navigation></project-navigation>\n\t\t\t</v-navigation-drawer>\n\t\t\t<v-toolbar class=\"cyan\" dark>\n\t\t\t\t<v-toolbar-title>{{ pageTitle }}</v-toolbar-title>\n\t\t\t</v-toolbar>\n\t\t\t<main>\n\t\t\t\t<v-container fluid>\n\t\t\t\t\t<router-view></router-view>\n\t\t\t\t\t</v-card>\n\t\t\t\t</v-container>\n\t\t\t</main>\n\t\t</v-app>\n\t`,\n\tcreated() {\n\t\tthis.$store.commit('setActiveProject', mainProcess.getActiveProject());\n\t},\n\tmounted() {\n\t\tthis.$store.commit('setPageTitle', this.project.json.name);\n\t},\n\tdata() {\n\t\treturn {\n\t\t\t// settings for the vuetify layout\n\t\t\tdrawer: null,\n\t\t\tright: null,\n\t\t}\n\t},\n\tcomputed: {\n\t\tpageTitle() {\n\t\t\treturn this.$store.getters.pageTitle;\n\t\t},\n\t\tproject() {\n\t\t\treturn this.$store.getters.activeProject;\n\t\t}\n\t},\n\tcomponents: {\n\t\t'project-navigation': ProjectNavigation\n\t}\n}\n"
  },
  {
    "path": "src/components/ProjectNavigation.js",
    "content": "'use strict';\n\nconst mainProcess = require('electron').remote.require('./main')\n\nmodule.exports = {\n\ttemplate: `\n\t\t<v-list dense>\n\t\t\t<v-list-group>\n\t\t\t\t<v-list-tile slot=\"item\">\n\t\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t\t<v-icon>queue_music</v-icon>\n\t\t\t\t\t</v-list-tile-action>\n\t\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t\t<v-list-tile-title>Composer</v-list-tile-title>\n\t\t\t\t\t</v-list-tile-content>\n\t\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t\t<v-icon>keyboard_arrow_down</v-icon>\n\t\t\t\t\t</v-list-tile-action>\n\t\t\t\t</v-list-tile>\n\t\t\t\t<v-list-tile>\n\t\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t\t<v-list-tile-title>composer.json</v-list-tile-title>\n\t\t\t\t\t</v-list-tile-content>\n\t\t\t\t</v-list-tile>\n\t\t\t\t<v-list-tile>\n\t\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t\t<v-list-tile-title>composer.lock</v-list-tile-title>\n\t\t\t\t\t</v-list-tile-content>\n\t\t\t\t</v-list-tile>\n\t\t\t</v-list-group>\n\t\t\t<template v-if=\"list.items\" v-for=\"list in dependencies\" >\n\t\t\t\t<v-list-group :value=\"list.active\" :key=\"list.type\">\n\t\t\t\t\t<v-list-tile slot=\"item\">\n\t\t\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t\t\t<v-icon>{{ list.icon }}</v-icon>\n\t\t\t\t\t\t</v-list-tile-action>\n\t\t\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t\t\t<v-list-tile-title>{{ list.title }}</v-list-tile-title>\n\t\t\t\t\t\t</v-list-tile-content>\n\t\t\t\t\t\t<v-list-tile-action>\n\t\t\t\t\t\t\t<v-icon>keyboard_arrow_down</v-icon>\n\t\t\t\t\t\t</v-list-tile-action>\n\t\t\t\t\t</v-list-tile>\n\t\t\t\t\t<template v-for=\"(version,package) in list.items\">\n\t\t\t\t\t\t<v-list-tile \n\t\t\t\t\t\t\t:to=\"{name: 'package', params: { packagePath: package } }\" \n\t\t\t\t\t\t\t:router=\"true\"\n\t\t\t\t\t\t\tv-if=\"package != 'php' || package.indexOf('ext-') > -1\">\n\t\t\t\t\t\t\t<v-list-tile-content>\n\t\t\t\t\t\t\t\t<v-list-tile-title>{{ package }}</v-list-tile-title>\n\t\t\t\t\t\t\t</v-list-tile-content>\n\t\t\t\t\t\t</v-list-tile>\n\t\t\t\t\t</template>\n\t\t\t\t</v-list-group>\n\t\t\t</template>\n\t\t</v-list>\n\t`,\n\tcomputed: {\n\t\tproject() {\n\t\t\treturn this.$store.getters.activeProject;\n\t\t},\n\t\tdependencies() {\n\t\t\treturn {\n\t\t\t\trequired: {\n\t\t\t\t\ttitle: 'Requirements',\n\t\t\t\t\ticon: 'beenhere',\n\t\t\t\t\titems: this.project.getRequire(),\n\t\t\t\t\tactive: true,\n\t\t\t\t},\n\t\t\t\tdev: {\n\t\t\t\t\ttitle: 'Development Requirements',\n\t\t\t\t\ticon: 'build',\n\t\t\t\t\titems: this.project.getRequireDev(),\n\t\t\t\t\tactive: false,\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t},\n\tmethods: {\n\t\topenPackage: (packageName) => {\n\t\t\tmainProcess.openPackage(packageName);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/RecentProjects.js",
    "content": "'use strict';\n\nconst mainProcess = require('electron').remote.require('./main');\n\nmodule.exports = {\n\ttemplate: `\n    <v-list two-line subheader>\n      <v-list-tile avatar v-for=\"project in projects\">\n        <v-list-tile-avatar>\n          <v-icon class=\"grey lighten-1 white--text\">folder</v-icon>\n        </v-list-tile-avatar>\n        <v-list-tile-content @click=\"openProject(project.path)\">\n          <v-list-tile-title>{{ project.name }}</v-list-tile-title>\n          <v-list-tile-sub-title>{{ project.path }}</v-list-tile-sub-title>\n        </v-list-tile-content>\n        <v-list-tile-action>\n          <v-btn icon ripple @click=\"removeProject(project.path)\">\n            <v-icon class=\"grey--text text--lighten-1\">delete_forever</v-icon>\n          </v-btn>\n        </v-list-tile-action>\n      </v-list-tile>\n    </v-list>\n\t`,\n\tcomputed: {\n\t\tprojects() {\n\t\t\treturn this.$store.getters.projectsList;\n\t\t}\n\t},\n\tmounted() {\n\t\tthis.$store.commit('setPageTitle', 'Recent Projects');\n\t},\n\tmethods: {\n\t\tremoveProject(path) {\n\t\t\tthis.$store.dispatch('removeProjectAction', path);\n\t\t},\n\t\topenProject: (path) => {\n\t\t\tmainProcess.openProject(path);\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "src/components/SettingsForm.js",
    "content": "'use strict';\n\n\nmodule.exports = {\n\ttemplate: `\n    <v-card>TODO</v-card>\n\t`,\n\tmounted() {\n\t\tthis.$store.commit('setPageTitle', 'Settings');\n\t},\n\tmethods: {\n\t}\n}\n"
  },
  {
    "path": "src/models/Lock.js",
    "content": "'use strict';\nconst Package = require('./Package');\nconst Lock = function (json) {\n\tconst self = this;\n\tthis.json = json;\n\tthis.packages = [];\n\tthis.packagesDev = [];\n\n\tArray.from(json.packages).forEach(function (item) {\n\t\tself.packages[item.name] = new Package(item);\n\t});\n\tArray.from(json['packages-dev']).forEach(function (item) {\n\t\tself.packagesDev[item.name] = new Package(item);\n\t});\n\n\t/**\n\t *\n\t * @param name\n\t * @returns {Package}\n\t */\n\tthis.getPackage = (name) => {\n\t\tif (this.packages.hasOwnProperty(name)) {\n\t\t\treturn this.packages[name];\n\t\t}\n\t\telse if (this.packagesDev.hasOwnProperty(name)){\n\t\t\treturn this.packagesDev[name];\n\t\t}\n\t};\n};\nLock.prototype.json = {};\nLock.prototype.packages = {};\nmodule.exports = Lock;\n"
  },
  {
    "path": "src/models/Package.js",
    "content": "'use strict';\n\nvar Package = function (json) {\n\tthis.json = json;\n\tthis.__get = (key) => { return this.json[key]};\n\tthis.getVersion = () => { return this.json.version; };\n\tthis.getName = () => { return this.json.name };\n};\nPackage.prototype.json = {};\nmodule.exports = Package;\n"
  },
  {
    "path": "src/models/Project.js",
    "content": "'use strict';\nlet Lock = require('./Lock');\n/**\n *\n * @param {String} path\n * @constructor\n */\nlet Project = function (path) {\n\tthis.path = path;\n\n\tthis.getPath = () => { return this.path };\n\tthis.getName = () => { return this.json['name'] || '' };\n\tthis.getDescription = () => { return this.json['description'] || '' };\n\t/**\n\t * @returns {Object}\n\t */\n\tthis.getRequire = () => { return this.json['require'] };\n\t/**\n\t * @returns {Object}\n\t */\n\tthis.getRequireDev = () => { return this.json['require-dev'] };\n\t/**\n\t * @returns {*|string}\n\t */\n\tthis.getHomepage = () => { return this.json['homepage'] || '' };\n\t/**\n\t * @returns {null|Lock}\n\t */\n\tthis.getLock = () => { return this.lock };\n\n\tthis.refreshLock = () => {\n\t\tthis.lock = null;\n\t\tif (this.filesystem.existsSync(path + '/composer.lock')) {\n\t\t\ttry {\n\t\t\t\tthis.filesystem.readFile(path + '/composer.lock', (err, data) => {\n\t\t\t\t\tif (!err) {\n\t\t\t\t\t\tthis.lock = new Lock(JSON.parse(data));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log(e);\n\t\t\t}\n\t\t}\n\t};\n\n\tthis.isInstalled = () => {\n\t\treturn this.lock !== null;\n\t};\n\n\tthis.refreshData = () => {\n\t\tthis.json = require(this.path + '/composer.json');\n\t\tthis.refreshLock();\n\t};\n\tthis.refreshData();\n};\nProject.prototype.path = '';\nProject.prototype.json = {};\nProject.prototype.filesystem = require('fs');\nmodule.exports = Project;\n"
  },
  {
    "path": "src/store.js",
    "content": "'use strict';\n\nconst Vuex = require('vuex');\nconst projectList = require('electron').remote.require('./main').getProjectList();\n\nlet list = projectList.getList();\nlet projects = [];\nObject.keys(list).map((path) => {\n\tprojects.push({\n\t\tpath,\n\t\tname: list[path]\n\t});\n});\n\nconst store = new Vuex.Store({\n\tstate: {\n\t\tpageTitle: '',\n\t\tprojects: projects,\n\t\tactiveProject: {},\n\t},\n\tgetters: {\n\t\t/**\n\t\t * Get the current page title\n\t\t */\n\t\tpageTitle(state) {\n\t\t\treturn state.pageTitle;\n\t\t},\n\n\t\t/**\n\t\t * Get the formatted projects array\n\t\t */\n\t\tprojectsList(state) {\n\t\t\treturn state.projects;\n\t\t},\n\n\t\t/**\n\t\t * Get the active project being viewed\n\t\t */\n\t\tactiveProject(state) {\n\t\t\treturn state.activeProject;\n\t\t},\n\t},\n\t// no async\n\tmutations: {\n\t\tsetPageTitle(state, title) {\n\t\t\tstate.pageTitle = title;\n\t\t},\n\t\tsetActiveProject(state, project) {\n\t\t\tstate.activeProject = project;\n\t\t},\n\t\tremoveProject(state, path) {\n\t\t\t// remove project from the stored data file\n\t\t\tprojectList.removeProject(path);\n\t\t\t// remove project from the global state\n\t\t\tlet index = state.projects.findIndex((project) => project.path === path );\n\t\t\tstate.projects.splice(index, 1);\n\t\t}\n\t},\n\t// handles asynchronous\n\tactions: {\n\t\tremoveProjectAction(context, path) {\n\t\t\tcontext.commit('removeProject', path);\n\t\t}\n\t}\n});\n\nmodule.exports = {\n\tstore\n}\n"
  },
  {
    "path": "src/utils/AppMenu.js",
    "content": "'use strict';\n\nconst electron = require('electron');\nconst app = electron.app;\nconst menu = electron.Menu;\nconst shell = electron.shell;\nconst main = require('../../main');\n\nlet template = [\n\t{\n\t\tlabel: 'Projects',\n\t\tsubmenu: [],\n\t},\n\t{\n\t\tlabel: 'Help',\n\t\trole: 'help',\n\t\tsubmenu: [\n\t\t\t{\n\t\t\t\tlabel: 'Documentation',\n\t\t\t\tclick() {\n\t\t\t\t\tshell.openExternal('https://github.com/mglaman/conductor/wiki')\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Report an issue',\n\t\t\t\tclick() {\n\t\t\t\t\tshell.openExternal('https://github.com/mglaman/conductor/issues')\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t}\n];\n\nif (process.platform === 'darwin') {\n\tconst name = 'Conductor';\n\ttemplate.unshift({\n\t\tlabel: name,\n\t\tsubmenu: [\n\t\t\t{\n\t\t\t\tlabel: 'About ' + name,\n\t\t\t\trole: 'about'\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'separator'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Services',\n\t\t\t\trole: 'services',\n\t\t\t\tsubmenu: []\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'separator'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Hide ' + name,\n\t\t\t\taccelerator: 'Command+H',\n\t\t\t\trole: 'hide'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Hide Others',\n\t\t\t\taccelerator: 'Command+Alt+H',\n\t\t\t\trole: 'hideothers'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Show All',\n\t\t\t\trole: 'unhide'\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'separator'\n\t\t\t},\n\t\t\t{\n\t\t\t\tlabel: 'Quit',\n\t\t\t\taccelerator: 'Command+Q',\n\t\t\t\tclick() {\n\t\t\t\t\tapp.quit();\n\t\t\t\t}\n\t\t\t},\n\t\t]\n\t});\n}\n\n\nmodule.exports = {\n\tsetProjects: (projects) => {\n\t\tlet key = (process.platform === 'darwin') ? 1 : 0;\n\t\tfor (let path in projects) {\n\t\t\tif (!projects.hasOwnProperty(path)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttemplate[key].submenu.push({\n\t\t\t\tlabel: projects[path],\n\t\t\t\tclick() {\n\t\t\t\t\tmain.openProject(path)\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\tsetMenu: () => {\n\t\tlet appMenu = menu.buildFromTemplate(template);\n\t\tmenu.setApplicationMenu(appMenu);\n\t}\n};\n"
  },
  {
    "path": "src/utils/AppUpdater.js",
    "content": "const BrowserWindowElectron = require('electron').BrowserWindow;\nconst autoUpdater = require('electron-updater').autoUpdater;\nconst isDev = require('electron-is-dev');\nconst os = require('os');\n\n\nclass AppUpdater {\n\tconstructor() {\n\n\t\tif (isDev === true) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst platform = os.platform();\n\t\tif (platform === \"linux\") {\n\t\t\treturn\n\t\t}\n\n\t\tautoUpdater.signals.updateDownloaded(it => {\n\t\t\tnotify(\"A new update is ready to install\", `Version ${it.version} is downloaded and will be automatically installed on Quit`)\n\t\t});\n\t\tautoUpdater.checkForUpdates()\n\t}\n}\n\nfunction notify(title, message) {\n\tlet windows = BrowserWindowElectron.getAllWindows();\n\tif (windows.length === 0) {\n\t\treturn\n\t}\n\n\twindows[0].webContents.send(\"notify\", title, message)\n}\n\nmodule.exports = AppUpdater;\n"
  },
  {
    "path": "src/utils/BrowserWindowFactory.js",
    "content": "'use strict';\n\nlet BrowserWindow = require('electron').BrowserWindow;\nfunction getDefaultWindowHeight(w) {\n\treturn Math.round((w / 4) * 3);\n}\n\nmodule.exports = {\n\tcreateWindow: (url, width, icon) => {\n\t\tlet browserWindow = new BrowserWindow({\n\t\t\twidth: width,\n\t\t\theight: getDefaultWindowHeight(width),\n\t\t\ticon: icon,\n\t\t\tshow: false,\n\t\t});\n\t\tbrowserWindow.loadURL(url);\n\t\tbrowserWindow.on('ready-to-show', function() {\n\t\t\tbrowserWindow.show();\n\t\t\tbrowserWindow.focus();\n\t\t});\n\t\treturn browserWindow;\n\t}\n}\n;\n"
  },
  {
    "path": "src/utils/Composer.js",
    "content": "'use strict';\n\n/**\n *\n * @param {String} projectPath\n * @constructor\n */\nlet Composer = function(projectPath) {\n\tconst bin = this.binPath + '/composer.phar';\n\n\tthis.install = (opts) => {\n\t\treturn this._runCommand(['install', '--no-progress'], opts);\n\t};\n\tthis.update = (dependency, opts) => {\n\t\tlet command = ['update', '--no-progress'];\n\t\tif (typeof dependency === 'string') {\n\t\t\tcommand.push(dependency);\n\t\t}\n\t\treturn this._runCommand(command, opts);\n\t};\n\tthis.validate = (opts) => {\n\t\treturn this._runCommand(['validate'], opts);\n\t};\n\t/**\n\t *\n\t * @param dependency\n\t * @param opts\n\t * @returns {ChildProcess}\n\t */\n\tthis.show = (dependency, opts) => {\n\t\treturn this._runCommand(['show', dependency], opts);\n\t};\n\tthis.remove = (dependency, opts) => {\n\t\treturn this._runCommand(['remove', dependency], opts);\n\t};\n\tthis.createProject = (project, destination, opts) => {\n\t\treturn this._runCommand(['create-project', project, destination,'--stability', 'dev', '--no-interaction'], opts)\n\t};\n\tthis._normalizeOpts = (opts) => {\n\t\tif (typeof opts === 'undefined' || opts.length === 0) {\n\t\t\topts = {};\n\t\t}\n\t\topts['cwd'] = projectPath;\n\t\treturn opts;\n\t};\n\t/**\n\t *\n\t * @param command\n\t * @param opts\n\t * @returns {ChildProcess}\n\t * @private\n\t */\n\tthis._runCommand = (command, opts) => {\n\t\topts = this._normalizeOpts(opts);\n\t\treturn this.spawn(bin, command, opts);\n\t}\n};\n\nComposer.prototype.spawn = require('child_process').spawn;\nComposer.prototype.binPath = (process.mainModule.filename.indexOf('app.asar') !== -1) ? process.resourcesPath : process.cwd();\nmodule.exports = Composer;\n"
  },
  {
    "path": "src/utils/ProjectList.js",
    "content": "'use strict';\nconst Config = require('electron-config');\n\n/**\n * @constructor\n */\nlet ProjectList = function() {\n\t/** @type {ElectronConfig} */\n\tconst config = new Config();\n\n\tthis.setList = (list) => { this.list = list; };\n\tthis.getList = () => { return this.list; };\n\n\tthis.refreshList = () => {\n\t\tthis.setList({});\n\t\tif (config.has('projects')) {\n\t\t\tthis.setList(config.get('projects'));\n\t\t}\n\t};\n\n\tthis.addProject = (dir, name) => {\n\t\tthis.list[dir] = name;\n\t\tconfig.set('projects', this.list);\n\t};\n\n\tthis.removeProject = (dir) => {\n\t\tdelete this.list[dir];\n\t\tconfig.set('projects', this.list);\n\t}\n\n\tthis.refreshList();\n};\nProjectList.prototype.list = {};\nmodule.exports = ProjectList;\n"
  },
  {
    "path": "src/utils/misc.js",
    "content": "const readline = require('readline');\n\nexports.$addEventListener = (elId, event, callback) => {\n\tdocument.getElementById(elId).addEventListener(event, callback);\n};\nexports.$onClick = (elId, callback) => {\n\tthis.$addEventListener(elId, 'click', callback);\n};\n\nconst outputLogMessage = (message, lineClass) => {\n\tlet p = document.createElement('p');\n\tp.classList.add(lineClass);\n\tp.innerText = message;\n\treturn p;\n};\nexports.outputLogMessage = outputLogMessage;\n\nexports.outputReadLine = (stream, lineClass, elOutput) => {\n\treadline.createInterface({\n\t\tinput     : stream,\n\t\tterminal  : false\n\t}).on('line', line => {\n\t\telOutput.appendChild(outputLogMessage(line, lineClass));\n\t});\n};\n\nexports.findButtonicon = (el) => {\n\treturn el.childNodes[1];\n};\n"
  },
  {
    "path": "src/windows/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"UTF-8\">\n\t<title>Conductor - the Composer UI</title>\n\t<link href=\"../../node_modules/font-awesome/css/font-awesome.css\" rel=\"stylesheet\" type=\"text/css\" />\n\t<link href=\"../../public/css/conductor.css\" rel=\"stylesheet\" type=\"text/css\"/>\n\n\t<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel=\"stylesheet\" type=\"text/css\">\n\t<link href=\"../../node_modules/vuetify/dist/vuetify.min.css\" rel=\"stylesheet\" type=\"text/css\">\n\t<script src=\"../../node_modules/vue/dist/vue.js\"></script>\n\t<script src=\"../../node_modules/vuetify/dist/vuetify.min.js\"></script>\n</head>\n<body>\n<div id=\"app\"></div>\n</body>\n\n<script>\n\t// You can also require other files to run in this process\n\trequire('./mainWindow.js')\n</script>\n</html>\n"
  },
  {
    "path": "src/windows/mainWindow.js",
    "content": "'use strict';\n\nconst VueRouter = require('vue-router');\nconst Vuetify = require('vuetify');\n\nVue.use(Vuetify);\nVue.use(VueRouter);\n\n// components\nconst MainLayout = require('../components/MainLayout');\nconst RecentProjects = require('../components/RecentProjects');\nconst CreateProjectForm = require('../components/CreateProjectForm');\nconst SettingsForm = require('../components/SettingsForm');\n\nconst {store} = require('../store');\n\nconst routes = [\n\t{\n\t\tpath: '/recent-projects',\n\t\tname: 'recent-projects',\n\t\tcomponent: RecentProjects\n\t},\n\t{\n\t\tpath: '/create-project',\n\t\tname: 'create-project',\n\t\tcomponent: CreateProjectForm\n\t},\n\t{\n\t\tpath: '/settings',\n\t\tname: 'settings',\n\t\tcomponent: SettingsForm\n\t},\n\t{\n\t\tpath: '*',\n\t\tredirect: {\n\t\t\tname: 'recent-projects',\n\t\t},\n\t},\n];\n\nconst router = new VueRouter({\n\troutes: routes,\n\troot: '/recent-projects',\n\tmode: 'history',\n});\n\nnew Vue({\n\tel: '#app',\n\trouter: router,\n\tstore: store,\n\trender: h => h(MainLayout)\n})\n\n"
  },
  {
    "path": "src/windows/project/project.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"UTF-8\">\n\t<title>Conductor - the Composer UI</title>\n\t<link href=\"../../../node_modules/font-awesome/css/font-awesome.css\" rel=\"stylesheet\" type=\"text/css\" />\n\t<link href=\"../../../public/css/conductor.css\" rel=\"stylesheet\" type=\"text/css\"/>\n\n\t<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel=\"stylesheet\" type=\"text/css\">\n\t<link href=\"../../../node_modules/vuetify/dist/vuetify.min.css\" rel=\"stylesheet\" type=\"text/css\">\n\t<script src=\"../../../node_modules/vue/dist/vue.js\"></script>\n\t<script src=\"../../../node_modules/vuetify/dist/vuetify.min.js\"></script>\n</head>\n<body>\n<div id=\"app\"></div>\n</body>\n\n<script>\n\trequire('./projectWindow.js')\n</script>\n</html>\n"
  },
  {
    "path": "src/windows/project/projectWindow.js",
    "content": "'use strict';\n\nconst electron = require('electron');\nconst remote = electron.remote;\nconst mainProcess = remote.require('./main');\nconst thisWindow = remote.getCurrentWindow();\nlet activeProject = mainProcess.getActiveProject();\n\nthisWindow.setTitle(activeProject.getName());\n\nconst VueRouter = require('vue-router');\nconst Vuetify = require('vuetify');\nconst {store} = require('../../store');\n\nVue.use(Vuetify);\nVue.use(VueRouter);\n\n// Vue components\nconst ProjectLayout = require('../../components/ProjectLayout');\nconst ProjectDetails = require('../../components/ProjectDetails');\nconst PackageDetails = require('../../components/PackageDetails');\n\nconst routes = [\n\t{\n\t\tpath: '/project',\n\t\tname: 'project',\n\t\tcomponent: ProjectDetails\n\t},\n\t{\n\t\tpath: '/package/:packagePath',\n\t\tname: 'package',\n\t\tcomponent: PackageDetails\n\t},\n\t{\n\t\tpath: '*',\n\t\tredirect: {\n\t\t\tname: 'project',\n\t\t},\n\t},\n];\n\nconst router = new VueRouter({\n\troutes: routes,\n\troot: '/project',\n\tmode: 'history',\n});\n\n\nnew Vue({\n\tel: '#app',\n\trouter: router,\n\tstore: store,\n\trender: h => h(ProjectLayout)\n})\n"
  },
  {
    "path": "test/mainWindowTest.js",
    "content": "const Application = require('spectron').Application;\nconst path = require('path');\nconst chai = require('chai');\nconst chaiAsPromised = require('chai-as-promised');\nconst assert = require(\"assert\");\n\nlet electronPath = path.join(__dirname, '..', 'node_modules', '.bin', 'electron');\n\nif (process.platform === 'win32') {\n\telectronPath += '.cmd';\n}\n// Path to your application\nconst appPath = path.join(__dirname, '..');\n\nglobal.before(function () {\n\tchai.should();\n\tchai.use(chaiAsPromised)\n});\n\ndescribe('application launch', function () {\n\tthis.timeout(10000);\n\tlet app = null;\n\n\tbeforeEach(function () {\n\t\tapp = new Application({\n\t\t\tpath: electronPath,\n\t\t\tenv: { RUNNING_IN_SPECTRON: '1' },\n\t\t\targs: [appPath]\n\t\t});\n\t\treturn app.start().then(() => {\n\t\t\tassert.equal(app.isRunning(), true);\n\t\t\tchaiAsPromised.transferPromiseness = app.transferPromiseness;\n\t\t\treturn app;\n\t\t})\n\t});\n\n\tafterEach(function () {\n\t\treturn app.stop().then(() => {\n\t\t\tapp = null;\n\t\t})\n\t});\n\n\tit('loads project listing window', function () {\n\t\t/** @type WebdriverIO.Client**/\n\t\tconst client = app.client.waitUntilWindowLoaded();\n\n\t\treturn client\n\t\t\t.browserWindow.focus()\n\t\t\t.getWindowCount().should.eventually.equal(1)\n\t\t\t.browserWindow.isMinimized().should.eventually.be.false\n\t\t\t.browserWindow.isDevToolsOpened().should.eventually.be.false\n\t\t\t.browserWindow.isVisible().should.eventually.be.true\n\t\t\t.browserWindow.isFocused().should.eventually.be.true\n\t\t\t.getTitle().should.eventually.equal('Conductor - the Composer UI')\n\t\t\t.getText('#open-project').should.eventually.equal('Add existing project')\n\t\t\t.getText('#create-project').should.eventually.equal('Create new project')\n\t\t\t.getText('#open-settings').should.eventually.equal('Settings')\n\t});\n\t// @todo find a way to actually test dialogs.\n\tit('opens existing project window', function () {\n\t\t/** @type WebdriverIO.Client**/\n\t\tconst client = app.client.waitUntilWindowLoaded();\n\t\treturn client\n\t\t\t.browserWindow.focus()\n\t\t\t.getWindowCount().should.eventually.equal(1);\n\t});\n});\n"
  },
  {
    "path": "update-composer.sh",
    "content": "#!/usr/bin/env bash\n# See https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md\nEXPECTED_SIGNATURE=$(wget -q -O - https://composer.github.io/installer.sig)\nphp -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\"\nACTUAL_SIGNATURE=$(php -r \"echo hash_file('SHA384', 'composer-setup.php');\")\n\nif [ \"$EXPECTED_SIGNATURE\" != \"$ACTUAL_SIGNATURE\" ]\nthen\n    >&2 echo 'ERROR: Invalid installer signature'\n    rm composer-setup.php\n    exit 1\nfi\n\nphp composer-setup.php --quiet\nRESULT=$?\nrm composer-setup.php\nexit $RESULT\n"
  }
]