├── .babelrc
├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── README.md
├── app
├── App.vue
├── assets
│ └── logo.png
├── background.js
├── components
│ └── Hello.vue
├── main.html
├── main.js
└── package.json
├── build
├── css-loaders.js
├── dev-client.js
├── dev-runner.js
├── dev-server.js
├── package.js
├── resources
│ ├── icon.icns
│ ├── icon.ico
│ └── icon.png
├── webpack.base.conf.js
├── webpack.dev-background.conf.js
├── webpack.dev-main.conf.js
└── webpack.prod.conf.js
├── config.js
├── package.json
├── static
├── .gitkeep
└── electron_boilerplate
│ ├── context_menu.js
│ ├── dev_helper.js
│ ├── env_config.js
│ ├── external_links.js
│ └── window_state.js
├── test
├── e2e
│ ├── custom-assertions
│ │ └── elementCount.js
│ ├── nightwatch.conf.js
│ ├── runner.js
│ └── specs
│ │ └── test.js
└── unit
│ ├── .eslintrc
│ ├── index.js
│ ├── karma.conf.js
│ └── specs
│ └── Hello.spec.js
└── tools
└── vue-devtools
├── backend.js
├── devtools.js
├── hook.js
└── index.html
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-2"],
3 | "plugins": ["transform-runtime"],
4 | "comments": false
5 | }
6 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 4
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.json]
13 | indent_size = 2
14 |
15 | [*.md]
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
4 | extends: 'standard',
5 | // required to lint *.vue files
6 | plugins: [
7 | 'html'
8 | ],
9 | // add your custom rules here
10 | 'rules': {
11 | // allow paren-less arrow functions
12 | 'arrow-parens': 0,
13 | // allow debugger during development
14 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
15 | },
16 | 'env': {
17 | 'browser': true,
18 | 'node': true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | node_modules/
4 | app/dist/
5 | dist/
6 | releases/
7 | npm-debug.log*
8 | selenium-debug.log
9 | test/unit/coverage
10 | test/e2e/reports
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | electron-boilerplate-vue
2 | ==============
3 | Comprehensive boilerplate application for [Electron runtime](http://electron.atom.io) and [Vue.js](http://vuejs.org). This project is based on [vue-templates/webpack](https://github.com/vuejs-templates/webpack) and the awesome work by @szwacz on [electron-boilerplate](https://github.com/szwacz/electron-boilerplate).
4 |
5 | **This README is a work in progress.** This version is a large departure from the previous iteration. If you're looking for the old version, see [this branch](https://github.com/bradstewart/electron-boilerplate-vue/tree/legacy).
6 |
7 | Scope of this project:
8 |
9 | - Provide basic structure of the application so you can much easier grasp what should go where.
10 | - Give you cross-platform development environment, which works the same way on OSX, Windows and Linux.
11 | - Build scripts for the application using .vue components for production and development with Hot Module Reload.
12 | - Package scripts to generate executable files (.app, .exe).
13 | - Test scripts for both unit and end-to-end testing.
14 | - Generate ready for distribution installers of your app for all supported operating systems.
15 |
16 | Note: Installer generation is currently NOT implemented. Once electron-builder stablizes, I will add that to the project.
17 |
18 |
19 | # Quick start
20 | The only development dependency of this project is [Node.js](https://nodejs.org). So just make sure you have it installed.
21 | Then type few commands known to every Node developer...
22 | ```
23 | git clone https://github.com/bradstewart/electron-boilerplate-vue.git
24 | cd electron-boilerplate-vue
25 | npm install
26 | npm start
27 | ```
28 | ... and boom! You have running desktop application on your screen.
29 |
30 | # Structure of the project
31 |
32 | There are **two** `package.json` files:
33 |
34 | #### 1. For development
35 | Sits on path: `electron-boilerplate-vue/package.json`. Here you declare dependencies for your development environment and build scripts. **This file is not distributed with real application!**
36 |
37 | Also here you declare the version of Electron runtime you want to use:
38 | ```json
39 | "devDependencies": {
40 | "electron-prebuilt": "^0.34.0"
41 | }
42 | ```
43 |
44 | #### 2. For your application
45 | Sits on path: `electron-boilerplate-vue/app/package.json`. This is **real** manifest of your application. Declare your app dependencies here.
46 |
47 | #### OMG, but seriously why there are two `package.json`?
48 | 1. Native npm modules (those written in C, not JavaScript) need to be compiled, and here we have two different compilation targets for them. Those used in application need to be compiled against electron runtime, and all `devDependencies` need to be compiled against your locally installed node.js. Thanks to having two files this is trivial.
49 | 2. When you package the app for distribution there is no need to add up to size of the app with your `devDependencies`. Here those are always not included (because reside outside the `app` directory).
50 |
51 | ### Project's folders
52 |
53 | - `app` - code of your application goes here.
54 | - `static` - static files which are not processed by webpack.
55 | - `build` - build scripts, configuration files, and resources.
56 | - `dist` - webpacked and runnable Electron app.
57 | - `releases` - ready for distribution installers and executables.
58 | - `test` - test configuration, runners, and specs.
59 |
60 |
61 | # Development
62 |
63 | #### Installation
64 |
65 | ```
66 | npm install
67 | ```
68 | It will also download Electron runtime, and install dependencies for second `package.json` file inside `app` folder.
69 |
70 | #### Starting the app
71 |
72 | ```
73 | npm start
74 | ```
75 |
76 | #### Adding pure-js npm modules to your app
77 |
78 | Remember to add your dependency to `app/package.json` file, so do:
79 | ```
80 | cd app
81 | npm install name_of_npm_module --save
82 | ```
83 |
84 |
85 | # Making a release
86 |
87 | **Note:** There are various icon and bitmap files in the `build/resources` directory. Those are used in installers and are intended to be replaced by your own graphics.
88 |
89 | To make ready for distribution installer use command:
90 | ```
91 | npm run release
92 | ```
93 | This process uses [electron-packager](https://github.com/electron-userland/electron-packager). See their documentation on packaging for various operating systems.
94 |
95 |
96 | # License
97 |
98 | The MIT License (MIT)
99 |
100 | Copyright (c) 2015 Jakub Szwacz, 2016 Brad Stewart
101 |
102 | Permission is hereby granted, free of charge, to any person obtaining a copy
103 | of this software and associated documentation files (the "Software"), to deal
104 | in the Software without restriction, including without limitation the rights
105 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
106 | copies of the Software, and to permit persons to whom the Software is
107 | furnished to do so, subject to the following conditions:
108 |
109 | The above copyright notice and this permission notice shall be included in all
110 | copies or substantial portions of the Software.
111 |
112 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
113 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
114 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
115 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
116 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
117 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
118 | SOFTWARE.
119 |
--------------------------------------------------------------------------------
/app/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 | Welcome to your Electron + Vue.js app. To get started, take a look at the
7 | README
8 | of this template. If you have any issues with the setup, please file an issue at this template's repository.
9 |
10 |
11 | For advanced configurations, checkout the docs for
12 | Webpack and
13 | vue-loader.
14 |
15 |
16 | You may also want to checkout
17 | vue-router for routing and
18 | vuex for state management.
19 |
20 |
21 |
22 |
23 |
32 |
33 |
--------------------------------------------------------------------------------
/app/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradstewart/electron-boilerplate-vue/87afc09847431644cb86a5a14c52a0faa5007b4f/app/assets/logo.png
--------------------------------------------------------------------------------
/app/background.js:
--------------------------------------------------------------------------------
1 | // This is main process of Electron, started as first thing when your
2 | // app starts. This script is running through entire life of your application.
3 | // It doesn't have any windows which you can see on screen, but we can open
4 | // window from here.
5 |
6 | import { app, BrowserWindow } from 'electron'
7 | import path from 'path'
8 |
9 | let mainWindow
10 |
11 | app.on('ready', () => {
12 | mainWindow = new BrowserWindow({
13 | width: 1024,
14 | height: 768
15 | })
16 |
17 | // Load the HTML file directly from the webpack dev server if
18 | // hot reload is enabled, otherwise load the local file.
19 | const mainURL = process.env.HOT
20 | ? `http://localhost:${process.env.PORT}/main.html`
21 | : 'file://' + path.join(__dirname, 'main.html')
22 |
23 | mainWindow.loadURL(mainURL)
24 |
25 | if (process.env.NODE_ENV !== 'production') {
26 | mainWindow.openDevTools()
27 | }
28 |
29 | mainWindow.on('closed', () => {
30 | mainWindow = null
31 | })
32 | })
33 |
34 | app.on('window-all-closed', () => {
35 | app.quit()
36 | })
37 |
--------------------------------------------------------------------------------
/app/components/Hello.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 | from {{ appName }} running on {{ platform }}
5 |
6 |
7 |
8 |
26 |
--------------------------------------------------------------------------------
/app/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Electron Boilerplate Vue
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App'
3 |
4 | /* eslint-disable no-new */
5 | new Vue({
6 | el: 'body',
7 | components: { App }
8 | })
9 |
--------------------------------------------------------------------------------
/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-boilerplate-vue",
3 | "productName": "Electron Boilerplate Vue",
4 | "version": "0.1.0",
5 | "description": "An Electron + Vue.js project.",
6 | "author": "Brad Stewart ",
7 | "main": "background.js",
8 | "dependencies": {
9 | "jquery": "2.2.2"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/build/css-loaders.js:
--------------------------------------------------------------------------------
1 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
2 |
3 | module.exports = function (options) {
4 | options = options || {}
5 | // generate loader string to be used with extract text plugin
6 | function generateLoaders (loaders) {
7 | var sourceLoader = loaders.map(function (loader) {
8 | var extraParamChar
9 | if (/\?/.test(loader)) {
10 | loader = loader.replace(/\?/, '-loader?')
11 | extraParamChar = '&'
12 | } else {
13 | loader = loader + '-loader'
14 | extraParamChar = '?'
15 | }
16 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
17 | }).join('!')
18 |
19 | if (options.extract) {
20 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
21 | } else {
22 | return ['vue-style-loader', sourceLoader].join('!')
23 | }
24 | }
25 |
26 | // http://vuejs.github.io/vue-loader/configurations/extract-css.html
27 | return {
28 | css: generateLoaders(['css']),
29 | postcss: generateLoaders(['css']),
30 | less: generateLoaders(['css', 'less']),
31 | sass: generateLoaders(['css', 'sass?indentedSyntax']),
32 | scss: generateLoaders(['css', 'sass']),
33 | stylus: generateLoaders(['css', 'stylus']),
34 | styl: generateLoaders(['css', 'stylus'])
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/build/dev-client.js:
--------------------------------------------------------------------------------
1 | /* global __resourceQuery */
2 |
3 | // We need to explicity set the client's path to http://localhost:PORT
4 | // for it to work with Electron. In order to read the port from config.js,
5 | // we need to supply it as a compile-time constant through resourceQuery.
6 | var hotClient = require('webpack-hot-middleware/client' + __resourceQuery)
7 | // var hotClient = require('webpack-hot-middleware/client')
8 |
9 | hotClient.subscribe(function (event) {
10 | if (event.action === 'reload') {
11 | window.location.reload()
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/build/dev-runner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Runs both the express dev server and the electron client with
3 | * a single command. When one process exits, all processes exit.
4 | * Stdout and stderr from both processes is logged to the same console.
5 | */
6 | var exec = require('child_process').exec
7 | var config = require('../config')
8 |
9 | var kill = require('tree-kill')
10 |
11 | var YELLOW = '\x1b[33m'
12 | var BLUE = '\x1b[34m'
13 | var END = '\x1b[0m'
14 |
15 | function format (command, data, color) {
16 | return color + command + END +
17 | ' ' + // Two space offset
18 | String(data).trim().replace(/\n/g, '\n' + repeat(' ', command.length + 2)) +
19 | '\n'
20 | }
21 |
22 | function repeat (str, times) {
23 | return (new Array(times + 1)).join(str)
24 | }
25 |
26 | var children = []
27 |
28 | function run (command, color) {
29 | var child = exec(command)
30 |
31 | child.stdout.on('data', function (data) {
32 | console.log(format(command.split(' ')[2], data, color))
33 | })
34 |
35 | child.stderr.on('data', function (data) {
36 | console.error(format(command.split(' ')[2], data, color))
37 | })
38 |
39 | child.on('exit', function (code) {
40 | exit(code)
41 | })
42 |
43 | children.push(child)
44 | }
45 |
46 | function exit (code) {
47 | children.forEach(function (child) {
48 | kill(child.pid)
49 | })
50 | }
51 |
52 | // Run the client and the server
53 | run('npm run dev:server', YELLOW)
54 | run('npm run dev:client -- ' + config.build.outputRoot, BLUE)
55 |
--------------------------------------------------------------------------------
/build/dev-server.js:
--------------------------------------------------------------------------------
1 | var express = require('express')
2 | var webpack = require('webpack')
3 | var proxyMiddleware = require('http-proxy-middleware')
4 | var webpackConfig = require('./webpack.dev-main.conf')
5 | var config = require('../config')
6 |
7 | var app = express()
8 | var compiler = webpack(webpackConfig)
9 |
10 | var port = process.env.PORT || config.dev.port
11 | // Define HTTP proxies to your custom API backend
12 | // https://github.com/chimurai/http-proxy-middleware
13 | var proxyTable = config.dev.proxyTable
14 |
15 | var devMiddleware = require('webpack-dev-middleware')(compiler, {
16 | publicPath: webpackConfig.output.publicPath,
17 | stats: {
18 | colors: true,
19 | chunks: false
20 | }
21 | })
22 |
23 | var hotMiddleware = require('webpack-hot-middleware')(compiler)
24 | // force page reload when html-webpack-plugin template changes
25 | compiler.plugin('compilation', function (compilation) {
26 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
27 | hotMiddleware.publish({ action: 'reload' })
28 | cb()
29 | })
30 | })
31 |
32 | // proxy api requests
33 | Object.keys(proxyTable).forEach(function (context) {
34 | var options = proxyTable[context]
35 | if (typeof options === 'string') {
36 | options = { target: options }
37 | }
38 | app.use(proxyMiddleware(context, options))
39 | })
40 |
41 | // handle fallback for HTML5 history API
42 | app.use(require('connect-history-api-fallback')())
43 |
44 | // serve webpack bundle output
45 | app.use(devMiddleware)
46 |
47 | // enable hot-reload and state-preserving
48 | // compilation error display
49 | app.use(hotMiddleware)
50 |
51 | // serve pure static assets
52 | app.use('/static', express.static('./static'))
53 |
54 | module.exports = app.listen(port, function (err) {
55 | if (err) {
56 | console.log(err)
57 | return
58 | }
59 | console.log('Listening at http://localhost:' + port)
60 | })
61 |
--------------------------------------------------------------------------------
/build/package.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Packages the application into executable .app and .exe files.
3 | * For more info, see https://github.com/electron-userland/electron-packager.
4 | */
5 | var argv = require('minimist')(process.argv.slice(2))
6 | var packager = require('electron-packager')
7 | var appManifest = require('../app/package.json')
8 | var devManifest = require('../package.json')
9 | var config = require('../config')
10 |
11 | function getElectronVersion () {
12 | var v = config.release.electronVersion ||
13 | (devManifest.devDependencies || {})['electron-prebuilt'] ||
14 | (devManifest.dependencies || {})['electron-prebuilt']
15 |
16 | if (v) {
17 | return v.replace(/^\D+/, '')
18 | } else {
19 | console.log(
20 | 'No electron version was found in config.js or package.json.'
21 | )
22 | }
23 | }
24 |
25 | var packagerConfig = {
26 | dir: config.build.outputRoot,
27 | out: config.build.releasesRoot,
28 | name: appManifest.productName,
29 | 'app-version': appManifest.version,
30 | version: getElectronVersion(),
31 | platform: argv.platform || config.release.platform,
32 | arch: argv.arch || 'all',
33 | prune: true,
34 | overwrite: true,
35 | ignore: Object.keys((appManifest.devDependencies || {})).map(function (name) {
36 | return '/node_modules/' + name + '($|/)'
37 | })
38 | }
39 |
40 | packager(packagerConfig, function (err, appPath) {
41 | if (err) {
42 | console.error(err)
43 | process.exit(1)
44 | }
45 |
46 | console.log('packaged to ' + appPath)
47 | })
48 |
--------------------------------------------------------------------------------
/build/resources/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradstewart/electron-boilerplate-vue/87afc09847431644cb86a5a14c52a0faa5007b4f/build/resources/icon.icns
--------------------------------------------------------------------------------
/build/resources/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradstewart/electron-boilerplate-vue/87afc09847431644cb86a5a14c52a0faa5007b4f/build/resources/icon.ico
--------------------------------------------------------------------------------
/build/resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradstewart/electron-boilerplate-vue/87afc09847431644cb86a5a14c52a0faa5007b4f/build/resources/icon.png
--------------------------------------------------------------------------------
/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 | var config = require('../config')
4 | var cssLoaders = require('./css-loaders')
5 | var projectRoot = path.resolve(__dirname, '../')
6 |
7 | module.exports = {
8 | // Note: entry points are added by environment-specific configs.
9 |
10 | output: {
11 | path: config.build.outputRoot,
12 | filename: '[name].js'
13 | },
14 | // Use target 'node' so that __dirname works properly. We then need
15 | // to manually specify the electron modules in the ExternalsPlugin
16 | // since we're not using target 'electron'.
17 | target: 'node',
18 | node: {
19 | __filename: false,
20 | __dirname: false
21 | },
22 | resolve: {
23 | extensions: ['', '.js', '.vue'],
24 | fallback: [path.join(__dirname, '../node_modules')],
25 | alias: {
26 | app: path.resolve(__dirname, '../app')
27 | }
28 | },
29 | resolveLoader: {
30 | fallback: [path.join(__dirname, '../node_modules')]
31 | },
32 | module: {
33 | preLoaders: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'eslint',
37 | include: projectRoot,
38 | exclude: /node_modules/
39 | },
40 | {
41 | test: /\.js$/,
42 | loader: 'eslint',
43 | include: projectRoot,
44 | exclude: /vue-devtools|node_modules/
45 | }
46 | ],
47 | loaders: [
48 | {
49 | test: /\.vue$/,
50 | loader: 'vue'
51 | },
52 | {
53 | test: /\.js$/,
54 | loader: 'babel',
55 | include: projectRoot,
56 | exclude: /vue-devtools|node_modules/
57 | },
58 | {
59 | test: /\.json$/,
60 | loader: 'json'
61 | },
62 | {
63 | test: /\.html$/,
64 | loader: 'vue-html'
65 | },
66 | {
67 | test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
68 | loader: 'url',
69 | query: {
70 | limit: 10000,
71 | name: path.join(config.build.assetsSubDirectory, '[name].[ext]').replace('\\', '/')
72 | }
73 | }
74 | ]
75 | },
76 | plugins: [
77 | new webpack.ExternalsPlugin('commonjs2', [
78 | 'desktop-capturer',
79 | 'electron',
80 | 'ipc',
81 | 'ipc-renderer',
82 | 'native-image',
83 | 'remote',
84 | 'web-frame',
85 | 'clipboard',
86 | 'crash-reporter',
87 | 'screen',
88 | 'shell'
89 | ])
90 | ],
91 | vue: {
92 | loaders: cssLoaders()
93 | },
94 | eslint: {
95 | formatter: require('eslint-friendly-formatter')
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/build/webpack.dev-background.conf.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var merge = require('webpack-merge')
3 | var CopyWebpackPlugin = require('copy-webpack-plugin')
4 | var webpackBaseConfig = require('./webpack.base.conf')
5 | var config = require('../config')
6 |
7 | // var cssLoaders = require('./css-loaders')
8 | // var HtmlWebpackPlugin = require('html-webpack-plugin')
9 |
10 | // add hot-reload related code to entry chunks
11 | // Object.keys(webpackBaseConfig.entry).forEach(function (name) {
12 | // webpackBaseConfig.entry[name] = ['./build/dev-client'].concat(webpackBaseConfig.entry[name])
13 | // })
14 |
15 | module.exports = merge(webpackBaseConfig, {
16 | entry: {
17 | background: './app/background.js'
18 | },
19 | // eval-source-map is faster for development
20 | devtool: '#eval-source-map',
21 | output: {
22 | // necessary for the html plugin to work properly
23 | // when serving the html from in-memory
24 | publicPath: '/'
25 | },
26 | plugins: [
27 | // Copy files from app to dist
28 | new CopyWebpackPlugin([
29 | { from: './app/package.json', to: '.'}
30 | ]),
31 |
32 | new webpack.DefinePlugin({
33 | 'process.env': {
34 | NODE_ENV: '"development"',
35 | HOT: JSON.stringify(process.env.HOT),
36 | PORT: JSON.stringify(process.env.PORT || config.dev.port)
37 | }
38 | }),
39 |
40 | new webpack.optimize.OccurenceOrderPlugin(),
41 | new webpack.NoErrorsPlugin()
42 | ],
43 | stats: {
44 | colors: true
45 | }
46 | })
47 |
--------------------------------------------------------------------------------
/build/webpack.dev-main.conf.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack')
2 | var merge = require('webpack-merge')
3 | var HtmlWebpackPlugin = require('html-webpack-plugin')
4 | var webpackBaseConfig = require('./webpack.base.conf')
5 | var config = require('../config')
6 | var cssLoaders = require('./css-loaders')
7 |
8 | var devServerUrl = 'http://localhost:' + config.dev.port + '/'
9 |
10 | var webpackConfig = merge(webpackBaseConfig, {
11 | entry: {
12 | app: [
13 | './build/dev-client?path=' + devServerUrl + '__webpack_hmr&noInfo=true&reload=true',
14 | './app/main.js'
15 | ]
16 | },
17 | // eval-source-map is faster for development
18 | devtool: '#eval-source-map',
19 | output: {
20 | // necessary for the html plugin to work properly
21 | // when serving the html from in-memory
22 | // need to explicitly set localhost to prevent
23 | // the hot updates from looking for local files
24 | publicPath: devServerUrl
25 | },
26 | vue: {
27 | loaders: cssLoaders({
28 | sourceMap: false,
29 | extract: false
30 | })
31 | },
32 | plugins: [
33 | new webpack.DefinePlugin({
34 | 'process.env': {
35 | NODE_ENV: '"development"'
36 | }
37 | }),
38 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
39 | new webpack.optimize.OccurenceOrderPlugin(),
40 | new webpack.HotModuleReplacementPlugin(),
41 | new webpack.NoErrorsPlugin(),
42 | // https://github.com/ampedandwired/html-webpack-plugin
43 | new HtmlWebpackPlugin({
44 | filename: 'main.html',
45 | template: './app/main.html',
46 | excludeChunks: ['devtools'],
47 | inject: true
48 | })
49 | ]
50 | })
51 |
52 | if (config.dev.vueDevTools) {
53 | webpackConfig.entry.app.unshift(
54 | './tools/vue-devtools/hook.js',
55 | './tools/vue-devtools/backend.js'
56 | )
57 | webpackConfig.entry.devtools = './tools/vue-devtools/devtools.js'
58 |
59 | webpackConfig.plugins.push(new HtmlWebpackPlugin({
60 | filename: 'devtools.html',
61 | template: './tools/vue-devtools/index.html',
62 | chunks: ['devtools'],
63 | inject: true
64 | }))
65 | }
66 |
67 | module.exports = webpackConfig
68 |
69 |
--------------------------------------------------------------------------------
/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var webpack = require('webpack')
3 | var merge = require('webpack-merge')
4 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | var HtmlWebpackPlugin = require('html-webpack-plugin')
6 | var CopyWebpackPlugin = require('copy-webpack-plugin')
7 | var config = require('../config')
8 | var baseWebpackConfig = require('./webpack.base.conf')
9 | var cssLoaders = require('./css-loaders')
10 |
11 | module.exports = merge(baseWebpackConfig, {
12 | entry: {
13 | app: './app/main.js',
14 | background: './app/background.js'
15 | },
16 | devtool: config.build.productionSourceMap ? '#source-map' : false,
17 | output: {
18 | filename: '[name].js',
19 | chunkFilename: '[id].js'
20 | },
21 | vue: {
22 | loaders: cssLoaders({
23 | sourceMap: config.build.productionSourceMap,
24 | extract: true
25 | })
26 | },
27 | plugins: [
28 | new CopyWebpackPlugin([
29 | { from: './app/package.json', to: '.' },
30 | { from: './static', to: 'static' }
31 | ]),
32 | // http://vuejs.github.io/vue-loader/workflow/production.html
33 | new webpack.DefinePlugin({
34 | 'process.env': {
35 | NODE_ENV: '"production"'
36 | }
37 | }),
38 | new webpack.optimize.UglifyJsPlugin({
39 | compress: {
40 | warnings: false
41 | }
42 | }),
43 | new webpack.optimize.OccurenceOrderPlugin(),
44 | // extract css into its own file
45 | new ExtractTextPlugin(path.join(config.build.assetsSubDirectory, '[name].css')),
46 | // generate dist index.html with correct asset hash for caching.
47 | // you can customize output by editing /index.html
48 | // see https://github.com/ampedandwired/html-webpack-plugin
49 | new HtmlWebpackPlugin({
50 | filename: 'main.html',
51 | template: './app/main.html',
52 | excludeChunks: ['background'],
53 | inject: true,
54 | minify: {
55 | removeComments: true,
56 | collapseWhitespace: true,
57 | removeAttributeQuotes: true
58 | // more options:
59 | // https://github.com/kangax/html-minifier#options-quick-reference
60 | }
61 | })
62 | ]
63 | })
64 |
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * General configuration for build and release scripts.
3 | *
4 | * This file as adapted from http://vuejs-templates.github.io/webpack.
5 | * Some options were removed or changed to simplify things and/or
6 | * make them more applicable to Electron apps.
7 | */
8 | var path = require('path')
9 |
10 | module.exports = {
11 | build: {
12 | // The directory which will contained packaged releases and installers
13 | // for various operation systems.
14 | releasesRoot: path.resolve(__dirname, 'releases'),
15 |
16 | // The target directory for your app's compiled assets. Must be an absolute path.
17 | // This is the directory which will contain a runnable electron app.
18 | outputRoot: path.resolve(__dirname, 'dist'),
19 |
20 | // Nest webpack-generated assets under this directory in `assetsRoot`.
21 | // This applies to all non-JavaScript assets processed by webpack.
22 | assetsSubDirectory: 'assets',
23 |
24 | // Whether to generate source maps for production builds.
25 | productionSourceMap: true
26 | },
27 | release: {
28 | // The Electron version to use for packaged releases. If blank, it defaults
29 | // to the version of electron-prebuilt in your development package.json.
30 | //
31 | // electronVersion: '0.37.2',
32 |
33 | // The target platforms for packaged releases. For options, see
34 | // https://github.com/electron-userland/electron-packager
35 | platform: 'all'
36 | },
37 | dev: {
38 | // Dev server port.
39 | port: 8080,
40 |
41 | // Proxy requests to different backend during development.
42 | // https://github.com/chimurai/http-proxy-middleware
43 | proxyTable: {
44 | // '/api': {
45 | // target: 'http://jsonplaceholder.typicode.com',
46 | // changeOrigin: true,
47 | // pathRewrite: {
48 | // '^/api': ''
49 | // }
50 | // }
51 | },
52 |
53 | // Whether or not open another Electron window with vue-devtools.
54 | vueDevTools: true
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "postinstall": "cd app && npm install",
4 | "start": "node build/dev-runner.js",
5 | "dev:server": "node build/dev-server.js",
6 | "dev:client": "cross-env HOT=1 webpack --hide-modules --config build/webpack.dev-background.conf.js && cross-env HOT=1 electron",
7 | "build": "rimraf dist && mkdirp dist && cross-env NODE_ENV=production webpack --progress --hide-modules --config build/webpack.prod.conf.js",
8 | "package": "node build/package.js",
9 | "package:osx": "node build/package.js --platform=darwin --arch=x64",
10 | "package:win": "node build/package.js --platform=win32",
11 | "package:linux": "node build/package.js --platform=linux",
12 | "release": "npm run build && npm run package",
13 | "unit": "karma start test/unit/karma.conf.js --single-run",
14 | "e2e": "node test/e2e/runner.js",
15 | "test": "npm run unit && npm run e2e"
16 | },
17 | "devDependencies": {
18 | "babel-core": "^6.0.0",
19 | "babel-loader": "^6.0.0",
20 | "babel-plugin-transform-runtime": "^6.0.0",
21 | "babel-preset-es2015": "^6.0.0",
22 | "babel-preset-stage-2": "^6.0.0",
23 | "babel-runtime": "^6.0.0",
24 | "chromedriver": "^2.21.2",
25 | "connect-history-api-fallback": "^1.1.0",
26 | "copy-webpack-plugin": "^1.1.1",
27 | "cross-env": "1.0.7",
28 | "cross-spawn": "^2.1.5",
29 | "css-loader": "^0.23.0",
30 | "debug-menu": "^0.3.0",
31 | "electron-packager": "^7.0.0",
32 | "electron-prebuilt": "1.1.0",
33 | "electron-rebuild": "^1.1.3",
34 | "eslint": "^2.0.0",
35 | "eslint-config-standard": "^5.1.0",
36 | "eslint-friendly-formatter": "^1.2.2",
37 | "eslint-loader": "^1.3.0",
38 | "eslint-plugin-html": "^1.3.0",
39 | "eslint-plugin-promise": "^1.0.8",
40 | "eslint-plugin-standard": "^1.3.2",
41 | "eventsource-polyfill": "^0.9.6",
42 | "express": "^4.13.3",
43 | "extract-text-webpack-plugin": "^1.0.1",
44 | "file-loader": "^0.8.4",
45 | "html-webpack-plugin": "^2.8.1",
46 | "http-proxy-middleware": "^0.11.0",
47 | "inject-loader": "^2.0.1",
48 | "isparta-loader": "^2.0.0",
49 | "jasmine-core": "^2.4.1",
50 | "json-loader": "^0.5.4",
51 | "karma": "^0.13.15",
52 | "karma-coverage": "^0.5.5",
53 | "karma-electron-launcher": "^0.1.0",
54 | "karma-jasmine": "^0.3.6",
55 | "karma-sourcemap-loader": "^0.3.7",
56 | "karma-spec-reporter": "^0.0.24",
57 | "karma-webpack": "^1.7.0",
58 | "mkdirp": "^0.5.1",
59 | "moment": "2.12.0",
60 | "ncp": "^2.0.0",
61 | "nightwatch": "^0.8.18",
62 | "phantomjs-prebuilt": "^2.1.3",
63 | "rimraf": "^2.5.0",
64 | "selenium-server": "2.52.0",
65 | "tree-kill": "^1.1.0",
66 | "url-loader": "^0.5.7",
67 | "vue": "^1.0.17",
68 | "vue-hot-reload-api": "^1.2.0",
69 | "vue-html-loader": "^1.0.0",
70 | "vue-loader": "^8.3.0",
71 | "vue-router": "^0.7.11",
72 | "vue-style-loader": "^1.0.0",
73 | "webpack": "^1.12.2",
74 | "webpack-dev-middleware": "^1.4.0",
75 | "webpack-externals-plugin": "1.0.0",
76 | "webpack-hot-middleware": "^2.6.0",
77 | "webpack-merge": "^0.8.3"
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bradstewart/electron-boilerplate-vue/87afc09847431644cb86a5a14c52a0faa5007b4f/static/.gitkeep
--------------------------------------------------------------------------------
/static/electron_boilerplate/context_menu.js:
--------------------------------------------------------------------------------
1 | // This gives you default context menu (cut, copy, paste)
2 | // in all input fields and textareas across your app.
3 |
4 | (function () {
5 | 'use strict';
6 |
7 | var remote = require('electron').remote;
8 | var Menu = remote.Menu;
9 | var MenuItem = remote.MenuItem;
10 |
11 | var cut = new MenuItem({
12 | label: "Cut",
13 | click: function () {
14 | document.execCommand("cut");
15 | }
16 | });
17 |
18 | var copy = new MenuItem({
19 | label: "Copy",
20 | click: function () {
21 | document.execCommand("copy");
22 | }
23 | });
24 |
25 | var paste = new MenuItem({
26 | label: "Paste",
27 | click: function () {
28 | document.execCommand("paste");
29 | }
30 | });
31 |
32 | var textMenu = new Menu();
33 | textMenu.append(cut);
34 | textMenu.append(copy);
35 | textMenu.append(paste);
36 |
37 | document.addEventListener('contextmenu', function(e) {
38 |
39 | switch (e.target.nodeName) {
40 | case 'TEXTAREA':
41 | case 'INPUT':
42 | e.preventDefault();
43 | textMenu.popup(remote.getCurrentWindow());
44 | break;
45 | }
46 |
47 | }, false);
48 |
49 | }());
50 |
--------------------------------------------------------------------------------
/static/electron_boilerplate/dev_helper.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var app = require('app');
4 | var Menu = require('menu');
5 | var BrowserWindow = require('browser-window');
6 |
7 | module.exports.setDevMenu = function () {
8 | var devMenu = Menu.buildFromTemplate([{
9 | label: 'Development',
10 | submenu: [{
11 | label: 'Reload',
12 | accelerator: 'CmdOrCtrl+R',
13 | click: function () {
14 | BrowserWindow.getFocusedWindow().reloadIgnoringCache();
15 | }
16 | },{
17 | label: 'Toggle DevTools',
18 | accelerator: 'Alt+CmdOrCtrl+I',
19 | click: function () {
20 | BrowserWindow.getFocusedWindow().toggleDevTools();
21 | }
22 | },{
23 | label: 'Quit',
24 | accelerator: 'CmdOrCtrl+Q',
25 | click: function () {
26 | app.quit();
27 | }
28 | }]
29 | }]);
30 | Menu.setApplicationMenu(devMenu);
31 | };
32 |
--------------------------------------------------------------------------------
/static/electron_boilerplate/env_config.js:
--------------------------------------------------------------------------------
1 | // Loads config/env_XXX.json file and puts it
2 | // in proper place for given Electron context.
3 |
4 | 'use strict';
5 |
6 | (function () {
7 | var jetpack = require('fs-jetpack');
8 | if (typeof window === 'object') {
9 | // Web browser context, __dirname points to folder where app.html file is.
10 | window.env = jetpack.read(__dirname + '/env_config.json', 'json');
11 | } else {
12 | // Node context
13 | module.exports = jetpack.read(__dirname + '/../../env_config.json', 'json');
14 | }
15 | }());
16 |
--------------------------------------------------------------------------------
/static/electron_boilerplate/external_links.js:
--------------------------------------------------------------------------------
1 | // Convenient way for opening links in external browser, not in the app.
2 | // Useful especially if you have a lot of links to deal with.
3 | //
4 | // Usage:
5 | //
6 | // Every link with class ".js-external-link" will be opened in external browser.
7 | // google
8 | //
9 | // The same behaviour for many links can be achieved by adding
10 | // this class to any parent tag of an anchor tag.
11 | //
12 | // google
13 | // bing
14 | //
15 |
16 | (function () {
17 | 'use strict';
18 | var shell = require('electron').shell;
19 |
20 | var supportExternalLinks = function (e) {
21 | var href;
22 | var isExternal = false;
23 |
24 | var checkDomElement = function (element) {
25 | if (element.nodeName === 'A') {
26 | href = element.getAttribute('href');
27 | }
28 | if (element.classList.contains('js-external-link')) {
29 | isExternal = true;
30 | }
31 | if (href && isExternal) {
32 | shell.openExternal(href);
33 | e.preventDefault();
34 | } else if (element.parentElement) {
35 | checkDomElement(element.parentElement);
36 | }
37 | }
38 |
39 | checkDomElement(e.target);
40 | }
41 |
42 | document.addEventListener('click', supportExternalLinks, false);
43 | }());
44 |
--------------------------------------------------------------------------------
/static/electron_boilerplate/window_state.js:
--------------------------------------------------------------------------------
1 | // Simple module to help you remember the size and position of windows.
2 | // Can be used for more than one window, just construct many
3 | // instances of it and give each different name.
4 |
5 | 'use strict';
6 |
7 | var app = require('app');
8 | var jetpack = require('fs-jetpack');
9 |
10 | module.exports = function (name, defaults) {
11 |
12 | var userDataDir = jetpack.cwd(app.getPath('userData'));
13 | var stateStoreFile = 'window-state-' + name +'.json';
14 |
15 | var state = userDataDir.read(stateStoreFile, 'json') || {
16 | width: defaults.width,
17 | height: defaults.height
18 | };
19 |
20 | var saveState = function (win) {
21 | if (!win.isMaximized() && !win.isMinimized()) {
22 | var position = win.getPosition();
23 | var size = win.getSize();
24 | state.x = position[0];
25 | state.y = position[1];
26 | state.width = size[0];
27 | state.height = size[1];
28 | }
29 | state.isMaximized = win.isMaximized();
30 | userDataDir.write(stateStoreFile, state, { atomic: true });
31 | };
32 |
33 | return {
34 | get x() { return state.x; },
35 | get y() { return state.y; },
36 | get width() { return state.width; },
37 | get height() { return state.height; },
38 | get isMaximized() { return state.isMaximized; },
39 | saveState: saveState
40 | };
41 | };
42 |
--------------------------------------------------------------------------------
/test/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // the name of the method is the filename.
3 | // can be used in tests like this:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // for how to write custom assertions see
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 | exports.assertion = function (selector, count) {
10 | this.message = 'Testing if element <' + selector + '> has count: ' + count
11 | this.expected = count
12 | this.pass = function (val) {
13 | return val === this.expected
14 | }
15 | this.value = function (res) {
16 | return res.value
17 | }
18 | this.command = function (cb) {
19 | var self = this
20 | return this.api.execute(function (selector) {
21 | return document.querySelectorAll(selector).length
22 | }, [selector], function (res) {
23 | cb.call(self, res)
24 | })
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/test/e2e/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | // http://nightwatchjs.org/guide#settings-file
2 |
3 | module.exports = {
4 | 'src_folders': ['test/e2e/specs'],
5 | 'output_folder': 'test/e2e/reports',
6 | 'custom_assertions_path': ['test/e2e/custom-assertions'],
7 |
8 | 'selenium': {
9 | 'start_process': true,
10 | 'server_path': 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.52.0.jar',
11 | 'host': '127.0.0.1',
12 | 'port': 4444,
13 | 'cli_args': {
14 | 'webdriver.chrome.driver': require('chromedriver').path
15 | }
16 | },
17 |
18 | 'test_settings': {
19 | 'default': {
20 | 'selenium_port': 4444,
21 | 'selenium_host': 'localhost',
22 | 'silent': true
23 | },
24 |
25 | 'electron': {
26 | 'desiredCapabilities': {
27 | 'browserName': 'chrome',
28 | 'javascriptEnabled': true,
29 | 'acceptSslCerts': true,
30 | chromeOptions: {
31 | binary: require('electron-prebuilt') // Path to your Electron binary.
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/test/e2e/runner.js:
--------------------------------------------------------------------------------
1 | // 1. start the dev server
2 | var server = require('../../build/dev-server.js')
3 |
4 | // 2. run the nightwatch test suite against it
5 | // to run in additional browsers:
6 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
7 | // 2. add it to the --env flag below
8 | // For more information on Nightwatch's config file, see
9 | // http://nightwatchjs.org/guide#settings-file
10 | var spawn = require('cross-spawn')
11 | var runner = spawn(
12 | './node_modules/.bin/nightwatch',
13 | [
14 | '--config', 'test/e2e/nightwatch.conf.js',
15 | '--env', 'electron'
16 | ],
17 | {
18 | stdio: 'inherit'
19 | }
20 | )
21 |
22 | runner.on('exit', function (code) {
23 | server.close()
24 | process.exit(code)
25 | })
26 |
27 | runner.on('error', function (err) {
28 | server.close()
29 | throw err
30 | })
31 |
--------------------------------------------------------------------------------
/test/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': function (browser) {
6 | browser
7 | .url('http://localhost:8080/main.html')
8 | .waitForElementVisible('#app', 5000)
9 | .assert.elementPresent('.logo')
10 | .assert.containsText('h1', 'Hello World')
11 | .assert.elementCount('p', 3)
12 | .end()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/test/unit/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "jasmine": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/unit/index.js:
--------------------------------------------------------------------------------
1 | // Add this to make Electron code run properly. To be perfectly
2 | // honest, I'm not sure why this is necessary.
3 | window.process = window.parent.process
4 | window.require = window.parent.require
5 |
6 | // require all test files (files that ends with .spec.js)
7 | var testsContext = require.context('./specs', true, /\.spec$/)
8 | testsContext.keys().forEach(testsContext)
9 |
10 | // require all src files except main.js for coverage.
11 | // you can also change this to match only the subset of files that
12 | // you want coverage for.
13 | var srcContext = require.context('../../app', true, /^\.\/(?!(background|main)(\.js)?$)/)
14 | srcContext.keys().forEach(srcContext)
15 |
--------------------------------------------------------------------------------
/test/unit/karma.conf.js:
--------------------------------------------------------------------------------
1 | // This is a karma config file. For more details see
2 | // http://karma-runner.github.io/0.13/config/configuration-file.html
3 | // we are also using it with karma-webpack
4 | // https://github.com/webpack/karma-webpack
5 |
6 | var path = require('path')
7 | var merge = require('webpack-merge')
8 | var baseConfig = require('../../build/webpack.base.conf')
9 | var projectRoot = path.resolve(__dirname, '../../')
10 |
11 | var webpackConfig = merge(baseConfig, {
12 | // use inline sourcemap for karma-sourcemap-loader
13 | devtool: '#inline-source-map',
14 | vue: {
15 | loaders: {
16 | js: 'isparta'
17 | }
18 | }
19 | })
20 |
21 | // make sure isparta loader is applied before eslint
22 | webpackConfig.module.preLoaders.unshift({
23 | test: /\.js$/,
24 | loader: 'isparta',
25 | include: projectRoot,
26 | exclude: /test\/unit|node_modules/
27 | })
28 |
29 | // only apply babel for test files when using isparta
30 | webpackConfig.module.loaders.some(function (loader, i) {
31 | if (loader.loader === 'babel') {
32 | loader.include = /test\/unit/
33 | return true
34 | }
35 | })
36 |
37 | module.exports = function (config) {
38 | config.set({
39 | // to run in additional browsers:
40 | // 1. install corresponding karma launcher
41 | // http://karma-runner.github.io/0.13/config/browsers.html
42 | // 2. add it to the `browsers` array below.
43 | browsers: ['Electron'],
44 | frameworks: ['jasmine'],
45 | reporters: ['spec', 'coverage'],
46 | files: ['./index.js'],
47 | preprocessors: {
48 | './index.js': ['webpack', 'sourcemap']
49 | },
50 | webpack: webpackConfig,
51 | webpackMiddleware: {
52 | noInfo: true
53 | },
54 | coverageReporter: {
55 | dir: './coverage',
56 | reporters: [
57 | { type: 'lcov', subdir: '.' },
58 | { type: 'text-summary' }
59 | ]
60 | }
61 | })
62 | }
63 |
--------------------------------------------------------------------------------
/test/unit/specs/Hello.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Hello from 'app/components/Hello'
3 |
4 | describe('Hello.vue', () => {
5 | it('should render correct contents', () => {
6 | const vm = new Vue({
7 | template: '
',
8 | components: { Hello }
9 | }).$mount()
10 | expect(vm.$el.querySelector('.hello h1').textContent).toBe('Hello World!')
11 | })
12 | })
13 |
14 | // also see example testing a component with mocks at
15 | // https://github.com/vuejs/vue-loader-example/blob/master/test/unit/a.spec.js#L24-L49
16 |
--------------------------------------------------------------------------------
/tools/vue-devtools/hook.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 |
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 |
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId])
10 | /******/ return installedModules[moduleId].exports;
11 |
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ exports: {},
15 | /******/ id: moduleId,
16 | /******/ loaded: false
17 | /******/ };
18 |
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 |
22 | /******/ // Flag the module as loaded
23 | /******/ module.loaded = true;
24 |
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 |
29 |
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 |
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 |
36 | /******/ // __webpack_public_path__
37 | /******/ __webpack_require__.p = "/build/";
38 |
39 | /******/ // Load entry module and return exports
40 | /******/ return __webpack_require__(0);
41 | /******/ })
42 | /************************************************************************/
43 | /******/ ({
44 |
45 | /***/ 0:
46 | /***/ function(module, exports, __webpack_require__) {
47 |
48 | eval("'use strict';\n\nvar _hook = __webpack_require__(162);\n\n(0, _hook.installHook)(window);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvaG9vay5qcz80YTAwIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7O0FBRUEsdUJBQVksTUFBWiIsImZpbGUiOiIwLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5zdGFsbEhvb2sgfSBmcm9tICcuLi8uLi8uLi9zcmMvYmFja2VuZC9ob29rJ1xuXG5pbnN0YWxsSG9vayh3aW5kb3cpXG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiAuL3NyYy9ob29rLmpzXG4gKiovIl0sInNvdXJjZVJvb3QiOiIifQ==");
49 |
50 | /***/ },
51 |
52 | /***/ 162:
53 | /***/ function(module, exports) {
54 |
55 | eval("'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.installHook = installHook;\n// this script is injected into every page.\n\n/**\n * Install the hook on window, which is an event emitter.\n * Note because Chrome content scripts cannot directly modify the window object,\n * we are evaling this function by inserting a script tag. That's why we have\n * to inline the whole event emitter implementation here.\n *\n * @param {Window} window\n */\n\nfunction installHook(window) {\n var listeners = {};\n\n var hook = {\n Vue: null,\n\n on: function on(event, fn) {\n event = '$' + event;(listeners[event] || (listeners[event] = [])).push(fn);\n },\n once: function once(event, fn) {\n event = '$' + event;\n function on() {\n this.off(event, on);\n fn.apply(this, arguments);\n }\n ;(listeners[event] || (listeners[event] = [])).push(on);\n },\n off: function off(event, fn) {\n event = '$' + event;\n if (!arguments.length) {\n listeners = {};\n } else {\n var cbs = listeners[event];\n if (cbs) {\n if (!fn) {\n listeners[event] = null;\n } else {\n for (var i = 0, l = cbs.length; i < l; i++) {\n var cb = cbs[i];\n if (cb === fn || cb.fn === fn) {\n cbs.splice(i, 1);\n break;\n }\n }\n }\n }\n }\n },\n emit: function emit(event) {\n event = '$' + event;\n var cbs = listeners[event];\n if (cbs) {\n var args = [].slice.call(arguments, 1);\n cbs = cbs.slice();\n for (var i = 0, l = cbs.length; i < l; i++) {\n cbs[i].apply(this, args);\n }\n }\n }\n };\n\n hook.once('init', function (Vue) {\n hook.Vue = Vue;\n });\n\n hook.once('vuex:init', function (store) {\n hook.store = store;\n });\n\n Object.defineProperty(window, '__VUE_DEVTOOLS_GLOBAL_HOOK__', {\n get: function get() {\n return hook;\n }\n });\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vL1VzZXJzL2Jyc3Rld2FyL1JlcG9zaXRvcmllcy9lbGVjdHJvbi1ib2lsZXJwbGF0ZS12dWUvdG9vbHMvdnVlLWRldnRvb2xzL3NyYy9iYWNrZW5kL2hvb2suanM/MjdkNSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztRQVdnQjs7Ozs7Ozs7Ozs7O0FBQVQsU0FBUyxXQUFULENBQXNCLE1BQXRCLEVBQThCO0FBQ25DLE1BQUksWUFBWSxFQUFaLENBRCtCOztBQUduQyxNQUFNLE9BQU87QUFDWCxTQUFLLElBQUw7O0FBRUEsb0JBQUksT0FBTyxJQUFJO0FBQ2IsY0FBUSxNQUFNLEtBQU4sQ0FESyxDQUVYLFVBQVUsS0FBVixNQUFxQixVQUFVLEtBQVYsSUFBbUIsRUFBbkIsQ0FBckIsQ0FBRCxDQUE4QyxJQUE5QyxDQUFtRCxFQUFuRCxFQUZZO0tBSEo7QUFRWCx3QkFBTSxPQUFPLElBQUk7QUFDZixjQUFRLE1BQU0sS0FBTixDQURPO0FBRWYsZUFBUyxFQUFULEdBQWU7QUFDYixhQUFLLEdBQUwsQ0FBUyxLQUFULEVBQWdCLEVBQWhCLEVBRGE7QUFFYixXQUFHLEtBQUgsQ0FBUyxJQUFULEVBQWUsU0FBZixFQUZhO09BQWY7QUFJQSxPQU5lLENBTWIsVUFBVSxLQUFWLE1BQXFCLFVBQVUsS0FBVixJQUFtQixFQUFuQixDQUFyQixDQUFELENBQThDLElBQTlDLENBQW1ELEVBQW5ELEVBTmM7S0FSTjtBQWlCWCxzQkFBSyxPQUFPLElBQUk7QUFDZCxjQUFRLE1BQU0sS0FBTixDQURNO0FBRWQsVUFBSSxDQUFDLFVBQVUsTUFBVixFQUFrQjtBQUNyQixvQkFBWSxFQUFaLENBRHFCO09BQXZCLE1BRU87QUFDTCxZQUFNLE1BQU0sVUFBVSxLQUFWLENBQU4sQ0FERDtBQUVMLFlBQUksR0FBSixFQUFTO0FBQ1AsY0FBSSxDQUFDLEVBQUQsRUFBSztBQUNQLHNCQUFVLEtBQVYsSUFBbUIsSUFBbkIsQ0FETztXQUFULE1BRU87QUFDTCxpQkFBSyxJQUFJLElBQUksQ0FBSixFQUFPLElBQUksSUFBSSxNQUFKLEVBQVksSUFBSSxDQUFKLEVBQU8sR0FBdkMsRUFBNEM7QUFDMUMsa0JBQUksS0FBSyxJQUFJLENBQUosQ0FBTCxDQURzQztBQUUxQyxrQkFBSSxPQUFPLEVBQVAsSUFBYSxHQUFHLEVBQUgsS0FBVSxFQUFWLEVBQWM7QUFDN0Isb0JBQUksTUFBSixDQUFXLENBQVgsRUFBYyxDQUFkLEVBRDZCO0FBRTdCLHNCQUY2QjtlQUEvQjthQUZGO1dBSEY7U0FERjtPQUpGO0tBbkJTO0FBdUNYLHdCQUFNLE9BQU87QUFDWCxjQUFRLE1BQU0sS0FBTixDQURHO0FBRVgsVUFBSSxNQUFNLFVBQVUsS0FBVixDQUFOLENBRk87QUFHWCxVQUFJLEdBQUosRUFBUztBQUNQLFlBQU0sT0FBTyxHQUFHLEtBQUgsQ0FBUyxJQUFULENBQWMsU0FBZCxFQUF5QixDQUF6QixDQUFQLENBREM7QUFFUCxjQUFNLElBQUksS0FBSixFQUFOLENBRk87QUFHUCxhQUFLLElBQUksSUFBSSxDQUFKLEVBQU8sSUFBSSxJQUFJLE1BQUosRUFBWSxJQUFJLENBQUosRUFBTyxHQUF2QyxFQUE0QztBQUMxQyxjQUFJLENBQUosRUFBTyxLQUFQLENBQWEsSUFBYixFQUFtQixJQUFuQixFQUQwQztTQUE1QztPQUhGO0tBMUNTO0dBQVAsQ0FINkI7O0FBdURuQyxPQUFLLElBQUwsQ0FBVSxNQUFWLEVBQWtCLGVBQU87QUFDdkIsU0FBSyxHQUFMLEdBQVcsR0FBWCxDQUR1QjtHQUFQLENBQWxCLENBdkRtQzs7QUEyRG5DLE9BQUssSUFBTCxDQUFVLFdBQVYsRUFBdUIsaUJBQVM7QUFDOUIsU0FBSyxLQUFMLEdBQWEsS0FBYixDQUQ4QjtHQUFULENBQXZCLENBM0RtQzs7QUErRG5DLFNBQU8sY0FBUCxDQUFzQixNQUF0QixFQUE4Qiw4QkFBOUIsRUFBOEQ7QUFDNUQsd0JBQU87QUFDTCxhQUFPLElBQVAsQ0FESztLQURxRDtHQUE5RCxFQS9EbUMiLCJmaWxlIjoiMTYyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdGhpcyBzY3JpcHQgaXMgaW5qZWN0ZWQgaW50byBldmVyeSBwYWdlLlxuXG4vKipcbiAqIEluc3RhbGwgdGhlIGhvb2sgb24gd2luZG93LCB3aGljaCBpcyBhbiBldmVudCBlbWl0dGVyLlxuICogTm90ZSBiZWNhdXNlIENocm9tZSBjb250ZW50IHNjcmlwdHMgY2Fubm90IGRpcmVjdGx5IG1vZGlmeSB0aGUgd2luZG93IG9iamVjdCxcbiAqIHdlIGFyZSBldmFsaW5nIHRoaXMgZnVuY3Rpb24gYnkgaW5zZXJ0aW5nIGEgc2NyaXB0IHRhZy4gVGhhdCdzIHdoeSB3ZSBoYXZlXG4gKiB0byBpbmxpbmUgdGhlIHdob2xlIGV2ZW50IGVtaXR0ZXIgaW1wbGVtZW50YXRpb24gaGVyZS5cbiAqXG4gKiBAcGFyYW0ge1dpbmRvd30gd2luZG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGluc3RhbGxIb29rICh3aW5kb3cpIHtcbiAgbGV0IGxpc3RlbmVycyA9IHt9XG5cbiAgY29uc3QgaG9vayA9IHtcbiAgICBWdWU6IG51bGwsXG5cbiAgICBvbiAoZXZlbnQsIGZuKSB7XG4gICAgICBldmVudCA9ICckJyArIGV2ZW50XG4gICAgICA7KGxpc3RlbmVyc1tldmVudF0gfHwgKGxpc3RlbmVyc1tldmVudF0gPSBbXSkpLnB1c2goZm4pXG4gICAgfSxcblxuICAgIG9uY2UgKGV2ZW50LCBmbikge1xuICAgICAgZXZlbnQgPSAnJCcgKyBldmVudFxuICAgICAgZnVuY3Rpb24gb24gKCkge1xuICAgICAgICB0aGlzLm9mZihldmVudCwgb24pXG4gICAgICAgIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbiAgICAgIH1cbiAgICAgIDsobGlzdGVuZXJzW2V2ZW50XSB8fCAobGlzdGVuZXJzW2V2ZW50XSA9IFtdKSkucHVzaChvbilcbiAgICB9LFxuXG4gICAgb2ZmIChldmVudCwgZm4pIHtcbiAgICAgIGV2ZW50ID0gJyQnICsgZXZlbnRcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICBsaXN0ZW5lcnMgPSB7fVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgY2JzID0gbGlzdGVuZXJzW2V2ZW50XVxuICAgICAgICBpZiAoY2JzKSB7XG4gICAgICAgICAgaWYgKCFmbikge1xuICAgICAgICAgICAgbGlzdGVuZXJzW2V2ZW50XSA9IG51bGxcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSBjYnMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgIGxldCBjYiA9IGNic1tpXVxuICAgICAgICAgICAgICBpZiAoY2IgPT09IGZuIHx8IGNiLmZuID09PSBmbikge1xuICAgICAgICAgICAgICAgIGNicy5zcGxpY2UoaSwgMSlcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcblxuICAgIGVtaXQgKGV2ZW50KSB7XG4gICAgICBldmVudCA9ICckJyArIGV2ZW50XG4gICAgICBsZXQgY2JzID0gbGlzdGVuZXJzW2V2ZW50XVxuICAgICAgaWYgKGNicykge1xuICAgICAgICBjb25zdCBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpXG4gICAgICAgIGNicyA9IGNicy5zbGljZSgpXG4gICAgICAgIGZvciAobGV0IGkgPSAwLCBsID0gY2JzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgIGNic1tpXS5hcHBseSh0aGlzLCBhcmdzKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaG9vay5vbmNlKCdpbml0JywgVnVlID0+IHtcbiAgICBob29rLlZ1ZSA9IFZ1ZVxuICB9KVxuXG4gIGhvb2sub25jZSgndnVleDppbml0Jywgc3RvcmUgPT4ge1xuICAgIGhvb2suc3RvcmUgPSBzdG9yZVxuICB9KVxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3csICdfX1ZVRV9ERVZUT09MU19HTE9CQUxfSE9PS19fJywge1xuICAgIGdldCAoKSB7XG4gICAgICByZXR1cm4gaG9va1xuICAgIH1cbiAgfSlcbn1cblxuXG5cbi8qKiBXRUJQQUNLIEZPT1RFUiAqKlxuICoqIC9Vc2Vycy9icnN0ZXdhci9SZXBvc2l0b3JpZXMvZWxlY3Ryb24tYm9pbGVycGxhdGUtdnVlL3Rvb2xzL3Z1ZS1kZXZ0b29scy9zcmMvYmFja2VuZC9ob29rLmpzXG4gKiovIl0sInNvdXJjZVJvb3QiOiIifQ==");
56 |
57 | /***/ }
58 |
59 | /******/ });
--------------------------------------------------------------------------------
/tools/vue-devtools/index.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 | Vue Devtools
13 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------