├── .eslintrc
├── .gitignore
├── README.md
├── example
├── app.js
├── index.html
├── index.js
└── package.json
├── lib
└── index.js
└── package.json
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends" : "eslint:recommended",
3 | "env": {
4 | "node": true,
5 | "browser": true
6 | },
7 | "rules": {
8 | "quotes": [2, "single"],
9 | "strict": [2, "never"],
10 | "semi": 2
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # node.js
2 | node_modules/
3 | npm-debug.log
4 |
5 | # osx
6 | .DS_Store
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Electron Hot Loader
2 |
3 | Live reload Scripts in Electron Applications. Under the hood it uses Chrome's remote debugger protocol, and reloads scripts after each change. The state of the application is maintained.
4 |
5 | ## INSTALLATION
6 |
7 | ```sh
8 | $ npm install electron-hot
9 | ```
10 |
11 | ## USAGE
12 |
13 | In index.js:
14 |
15 | ```js
16 | require('electron-hot')();
17 | ```
18 |
19 | ### Options
20 | * port: Port for the debugger
21 |
--------------------------------------------------------------------------------
/example/app.js:
--------------------------------------------------------------------------------
1 | var canvas = document.createElement('canvas');
2 | canvas.style.position = 'absolute';
3 | canvas.style.top = '0';
4 | canvas.style.left = '0';
5 | canvas.style.background = '#222222';
6 |
7 | window.addEventListener('resize', function () {
8 | canvas.width = window.innerWidth;
9 | canvas.height = window.innerHeight;
10 | });
11 |
12 | canvas.width = window.innerWidth;
13 | canvas.height = window.innerHeight;
14 |
15 | document.body.appendChild(canvas);
16 |
17 | var ctx = canvas.getContext('2d');
18 |
19 | var balls = [];
20 | var start = null;
21 |
22 | function render(now) {
23 | window.requestAnimationFrame(render);
24 |
25 | if (!start) {
26 | start = now;
27 | }
28 |
29 | var seconds = (now - start) / 1000;
30 |
31 | ctx.clearRect(0, 0, canvas.width, canvas.height);
32 |
33 | ctx.fillStyle = '#ffffff';
34 | ctx.font = '16px Helvetica Neue';
35 | ctx.textAlign = 'center';
36 |
37 | ctx.fillText(seconds.toFixed(1) + 's', canvas.width / 2, 32);
38 |
39 | var gravity = [0, 1];
40 |
41 | balls.forEach(function(ball) {
42 | ball.position[0] += ball.velocity[0];
43 | ball.position[1] += ball.velocity[1];
44 |
45 | ball.velocity[0] += gravity[0];
46 | ball.velocity[1] += gravity[1];
47 |
48 | if (ball.position[1] + ball.radius > canvas.height) {
49 | ball.position[1] = canvas.height - ball.radius;
50 | ball.velocity[1] *= -ball.elasticity;
51 | if (Math.abs(ball.velocity[1]) < gravity[1]*2) {
52 | ball.velocity[1] = 0;
53 | }
54 | }
55 | ctx.beginPath();
56 | ctx.arc(ball.position[0], ball.position[1], ball.radius, 0, 2 * Math.PI, false);
57 | ctx.fillStyle = '#ffffff';
58 | ctx.fill();
59 | ctx.closePath();
60 | });
61 | }
62 |
63 | window.requestAnimationFrame(render);
64 |
65 | window.addEventListener('click', function (evt) {
66 | balls.push({
67 | position: [evt.x, evt.y],
68 | velocity: [0, 0],
69 | radius: 25,
70 | elasticity: 0.5
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Electron Hot Example
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | var app = require('app');
2 | var BrowserWindow = require('browser-window');
3 | var path = require('path');
4 |
5 | require('crash-reporter').start();
6 |
7 | require('..')();
8 |
9 | var mainWindow;
10 |
11 | app.on('window-all-closed', function() {
12 | app.quit();
13 | });
14 |
15 | app.on('ready', function() {
16 | mainWindow = new BrowserWindow({
17 | width: 800,
18 | height: 600
19 | });
20 | mainWindow.loadUrl('file://' + path.join(__dirname, '/index.html'));
21 | mainWindow.on('close', function() {
22 | mainWindow = null;
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-hot",
3 | "version": "0.1.0",
4 | "description": "Hot loader for Electron",
5 | "main": "index.js",
6 | "author": "Calvin Bulla ",
7 | "license": "MIT"
8 | }
9 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | var app = require('app');
2 | var remote = require('chrome-remote-interface');
3 | var chokidar = require('chokidar');
4 | var fs = require('fs');
5 |
6 | var scriptIds = {};
7 | var watcher;
8 |
9 | function connectToClient(port) {
10 | return new Promise(function(resolve, reject) {
11 | remote({
12 | port: port
13 | }, function(client) {
14 | resolve(client);
15 | }).on('error', function() {
16 | reject(Error('Unable to connect to client'));
17 | });
18 | });
19 | }
20 |
21 | module.exports = function(options) {
22 | options = options || {};
23 | options.port = options.port || 9222;
24 |
25 | app.commandLine.appendSwitch('remote-debugging-port', options.port.toString());
26 |
27 | app.on('quit', function() {
28 | if (watcher) {
29 | watcher.close();
30 | watcher = null;
31 | }
32 | });
33 |
34 | app.on('ready', function() {
35 | connectToClient(options.port).then(function(client) {
36 | client.Debugger.scriptParsed(function(script) {
37 | if (script.url.indexOf('file://') === -1) return;
38 | var url = script.url.replace('file://', '');
39 | if (scriptIds[url]) return;
40 | scriptIds[url] = script.scriptId;
41 | if (!watcher) {
42 | watcher = chokidar.watch(url);
43 | watcher.on('change', function(path) {
44 | var scriptId = scriptIds[path];
45 | fs.readFile(path, {
46 | encoding: 'utf-8'
47 | }, function(err, data) {
48 | if (err) throw err;
49 | client.Debugger.setScriptSource({
50 | scriptId: scriptId,
51 | scriptSource: data
52 | }, function(err) {
53 | if (err) throw err;
54 | });
55 | });
56 | });
57 | } else {
58 | watcher.add(url);
59 | }
60 | });
61 | client.Debugger.enable();
62 | });
63 | });
64 |
65 | };
66 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-hot",
3 | "version": "0.2.0",
4 | "description": "Electron hot loader",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "example": "electron example"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/cabul/electron-hot.git"
12 | },
13 | "keywords": [
14 | "electron",
15 | "hot",
16 | "loader"
17 | ],
18 | "author": "Calvin Bulla ",
19 | "license": "MIT",
20 | "bugs": {
21 | "url": "https://github.com/cabul/electron-hot/issues"
22 | },
23 | "homepage": "https://github.com/cabul/electron-hot#readme",
24 | "dependencies": {
25 | "chokidar": "^1.0.5",
26 | "chrome-remote-interface": "^0.9.0"
27 | },
28 | "devDependencies": {
29 | "electron-prebuilt": "^0.30.2",
30 | "webpack": "^1.11.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------