diff --git a/client/build.js b/client/build.js
index b8843e12..eaf28a54 100755
--- a/client/build.js
+++ b/client/build.js
@@ -59,6 +59,9 @@ const util = require('util');
const execSync = require('child_process').execSync;
const browserify = require('browserify');
const chokidar = require('chokidar');
+const WebSocket = require('ws');
+var PrettyError = require('pretty-error');
+var pe = new PrettyError();
function readTextFile(path) {
return fs.readFileSync(path, 'utf-8');
@@ -157,7 +160,7 @@ function minifyJs(path) {
function writeJsBundle(b, path, compress, callback) {
let outputFile = fs.createWriteStream(path);
- b.bundle().on('error', console.error).pipe(outputFile);
+ b.bundle().on('error', (e) => console.error(pe.render(e))).pipe(outputFile);
outputFile.on('finish', () => {
if (compress) {
fs.writeFileSync(path, minifyJs(path));
@@ -211,6 +214,8 @@ function bundleJs() {
}
}
+const environment = process.argv.includes('--watch') ? "development" : "production";
+
function bundleConfig() {
function getVersion() {
let build_info = process.env.BUILD_INFO;
@@ -228,7 +233,8 @@ function bundleConfig() {
meta: {
version: getVersion(),
buildDate: new Date().toUTCString()
- }
+ },
+ environment: environment
};
fs.writeFileSync('./js/.config.autogen.json', JSON.stringify(config));
@@ -309,16 +315,59 @@ function makeOutputDirs() {
}
function watch() {
- chokidar.watch('./fonts/**/*').on('change', bundleBinaryAssets);
- chokidar.watch('./img/**/*').on('change', bundleWebAppFiles);
- chokidar.watch('./html/**/*.tpl').on('change', bundleHtml);
- chokidar.watch('./css/**/*.styl').on('change', bundleCss);
+ let wss = new WebSocket.Server({ port: 8080 });
+ const liveReload = !process.argv.includes('--no-live-reload');
+
+ function emitReload() {
+ if (liveReload) {
+ console.log("Requesting live reload.")
+ wss.clients.forEach((client) => {
+ if (client.readyState === WebSocket.OPEN) {
+ client.send("reload");
+ }
+ });
+ }
+ }
+
+ chokidar.watch('./fonts/**/*').on('change', () => {
+ try {
+ bundleBinaryAssets();
+ emitReload();
+ } catch (e) {
+ console.error(pe.render(e));
+ }
+ });
+ chokidar.watch('./img/**/*').on('change', () => {
+ try {
+ bundleWebAppFiles();
+ emitReload();
+ } catch (e) {
+ console.error(pe.render(e));
+ }
+ });
+ chokidar.watch('./html/**/*.tpl').on('change', () => {
+ try {
+ bundleHtml();
+ } catch (e) {
+ console.error(pe.render(e));
+ }
+ });
+ chokidar.watch('./css/**/*.styl').on('change', () => {
+ try {
+ bundleCss()
+ emitReload();
+ } catch (e) {
+ console.error(pe.render(e));
+ }
+ });
bundleBinaryAssets();
bundleWebAppFiles();
bundleCss();
bundleHtml();
+ bundleVendorJs(true);
+
let watchify = require('watchify');
let b = browserify({
debug: process.argv.includes('--debug'),
@@ -341,6 +390,7 @@ function watch() {
bundleAppJs(b, compress, () => {
let end = new Date() - start;
console.info('Rebundled in %ds.', end / 1000)
+ emitReload();
});
}
@@ -350,6 +400,7 @@ function watch() {
// -------------------------------------------------
+console.log("Building for '" + environment + "' environment.");
makeOutputDirs();
bundleConfig();
if (process.argv.includes('--watch')) {
diff --git a/client/html/home_footer.tpl b/client/html/home_footer.tpl
index 8f9cb10a..85e71c96 100644
--- a/client/html/home_footer.tpl
+++ b/client/html/home_footer.tpl
@@ -1,7 +1,7 @@
- <%- ctx.postCount %> posts
- <%= ctx.makeFileSize(ctx.diskUsage) %>
- - Build <%- ctx.version %> from <%= ctx.makeRelativeTime(ctx.buildDate) %>
+ - Build <%- ctx.version %><%- ctx.isDevelopmentMode ? " (DEV MODE)" : "" %> from <%= ctx.makeRelativeTime(ctx.buildDate) %>
<% if (ctx.canListSnapshots) { %>- '>History
<% } %>
diff --git a/client/js/controllers/home_controller.js b/client/js/controllers/home_controller.js
index cf56e27a..ea2a411c 100644
--- a/client/js/controllers/home_controller.js
+++ b/client/js/controllers/home_controller.js
@@ -17,6 +17,7 @@ class HomeController {
buildDate: config.meta.buildDate,
canListSnapshots: api.hasPrivilege("snapshots:list"),
canListPosts: api.hasPrivilege("posts:list"),
+ isDevelopmentMode: config.environment == "development"
});
Info.get().then(
diff --git a/client/js/main.js b/client/js/main.js
index b9435744..2be2cd53 100644
--- a/client/js/main.js
+++ b/client/js/main.js
@@ -1,5 +1,20 @@
"use strict";
+const config = require("./config.js");
+
+if (config.environment == "development") {
+ var ws = new WebSocket("ws://" + location.hostname + ":8080");
+ ws.addEventListener('open', function (event) {
+ console.log("Live-reloading websocket connected.");
+ });
+ ws.addEventListener('message', (event) => {
+ console.log(event);
+ if (event.data == 'reload'){
+ location.reload();
+ }
+ });
+}
+
require("./util/polyfill.js");
const misc = require("./util/misc.js");
const views = require("./util/views.js");
diff --git a/client/package-lock.json b/client/package-lock.json
index 2334369e..4c72ec4c 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -26,10 +26,12 @@
"glob": "^7.1.2",
"html-minifier": "^3.5.18",
"jimp": "^0.13.0",
+ "pretty-error": "^3.0.3",
"stylus": "^0.54.5",
"terser": "^3.7.7",
"underscore": "^1.9.1",
- "watchify": "^4.0.0"
+ "watchify": "^4.0.0",
+ "ws": "^7.4.5 "
}
},
"node_modules/@babel/runtime": {
@@ -1252,6 +1254,12 @@
"integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
"dev": true
},
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+ "dev": true
+ },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1751,6 +1759,18 @@
"integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=",
"dev": true
},
+ "node_modules/css-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
+ "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^3.2.1",
+ "domutils": "^1.7.0",
+ "nth-check": "^1.0.2"
+ }
+ },
"node_modules/css-tree": {
"version": "1.0.0-alpha.29",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz",
@@ -1764,6 +1784,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/css-what": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz",
+ "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
"node_modules/csso": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz",
@@ -1881,6 +1913,37 @@
"randombytes": "^2.0.0"
}
},
+ "node_modules/dom-converter": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
+ "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
+ "dev": true,
+ "dependencies": {
+ "utila": "~0.4"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+ "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ }
+ },
+ "node_modules/dom-serializer/node_modules/domelementtype": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+ "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
"node_modules/dom-walk": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
@@ -1897,11 +1960,36 @@
"npm": ">=1.2"
}
},
+ "node_modules/domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "node_modules/domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "1"
+ }
+ },
"node_modules/dompurify": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.17.tgz",
"integrity": "sha512-nNwwJfW55r8akD8MSFz6k75bzyT2y6JEa1O3JrZFBf+Y5R9JXXU4OsRl0B9hKoPgHTw2b7ER5yJ5Md97MMUJPg=="
},
+ "node_modules/domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "dependencies": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
"node_modules/duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
@@ -1944,6 +2032,15 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
+ "node_modules/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/es-abstract": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz",
@@ -2342,6 +2439,40 @@
"node": ">=0.10"
}
},
+ "node_modules/htmlparser2": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^1.3.1",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.1.1"
+ }
+ },
+ "node_modules/htmlparser2/node_modules/entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "node_modules/htmlparser2/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/https-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
@@ -2797,9 +2928,9 @@
}
},
"node_modules/lodash": {
- "version": "4.17.19",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
- "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/lodash.memoize": {
@@ -3032,6 +3163,15 @@
"resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz",
"integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E="
},
+ "node_modules/nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "~1.0.0"
+ }
+ },
"node_modules/number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
@@ -3275,6 +3415,16 @@
"node": ">=4.0.0"
}
},
+ "node_modules/pretty-error": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-3.0.3.tgz",
+ "integrity": "sha512-nFB0BMeWNJA4YfmrgqPhOH3UQjMQZASZ2ueBfmlyqpVy9+ExLcmwXL/Iu4Wb9pbt/cubQXK4ir8IZUnE8EwFnw==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.20",
+ "renderkid": "^2.0.5"
+ }
+ },
"node_modules/private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@@ -3467,6 +3617,19 @@
"node": ">= 0.10"
}
},
+ "node_modules/renderkid": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz",
+ "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==",
+ "dev": true,
+ "dependencies": {
+ "css-select": "^2.0.2",
+ "dom-converter": "^0.2",
+ "htmlparser2": "^3.10.1",
+ "lodash": "^4.17.20",
+ "strip-ansi": "^3.0.0"
+ }
+ },
"node_modules/repeating": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
@@ -4038,6 +4201,12 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
+ "node_modules/utila": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
+ "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
+ "dev": true
+ },
"node_modules/vm-browserify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz",
@@ -4297,6 +4466,27 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
+ "node_modules/ws": {
+ "version": "7.4.5",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
+ "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/xhr": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz",
@@ -5555,6 +5745,12 @@
"integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
"dev": true
},
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+ "dev": true
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -6017,6 +6213,18 @@
"integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=",
"dev": true
},
+ "css-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
+ "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
+ "dev": true,
+ "requires": {
+ "boolbase": "^1.0.0",
+ "css-what": "^3.2.1",
+ "domutils": "^1.7.0",
+ "nth-check": "^1.0.2"
+ }
+ },
"css-tree": {
"version": "1.0.0-alpha.29",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz",
@@ -6027,6 +6235,12 @@
"source-map": "^0.5.3"
}
},
+ "css-what": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz",
+ "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==",
+ "dev": true
+ },
"csso": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz",
@@ -6123,6 +6337,33 @@
"randombytes": "^2.0.0"
}
},
+ "dom-converter": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
+ "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
+ "dev": true,
+ "requires": {
+ "utila": "~0.4"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+ "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+ "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+ "dev": true
+ }
+ }
+ },
"dom-walk": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
@@ -6135,11 +6376,36 @@
"integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
"dev": true
},
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
"dompurify": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.17.tgz",
"integrity": "sha512-nNwwJfW55r8akD8MSFz6k75bzyT2y6JEa1O3JrZFBf+Y5R9JXXU4OsRl0B9hKoPgHTw2b7ER5yJ5Md97MMUJPg=="
},
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
"duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
@@ -6184,6 +6450,12 @@
}
}
},
+ "entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "dev": true
+ },
"es-abstract": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz",
@@ -6496,6 +6768,39 @@
"integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=",
"dev": true
},
+ "htmlparser2": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.1",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.1.1"
+ },
+ "dependencies": {
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
"https-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
@@ -6844,9 +7149,9 @@
}
},
"lodash": {
- "version": "4.17.19",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
- "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"lodash.memoize": {
@@ -7039,6 +7344,15 @@
"resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz",
"integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E="
},
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0"
+ }
+ },
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
@@ -7240,6 +7554,16 @@
"integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==",
"dev": true
},
+ "pretty-error": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-3.0.3.tgz",
+ "integrity": "sha512-nFB0BMeWNJA4YfmrgqPhOH3UQjMQZASZ2ueBfmlyqpVy9+ExLcmwXL/Iu4Wb9pbt/cubQXK4ir8IZUnE8EwFnw==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.20",
+ "renderkid": "^2.0.5"
+ }
+ },
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@@ -7407,6 +7731,19 @@
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
"dev": true
},
+ "renderkid": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz",
+ "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==",
+ "dev": true,
+ "requires": {
+ "css-select": "^2.0.2",
+ "dom-converter": "^0.2",
+ "htmlparser2": "^3.10.1",
+ "lodash": "^4.17.20",
+ "strip-ansi": "^3.0.0"
+ }
+ },
"repeating": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
@@ -7901,6 +8238,12 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
+ "utila": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
+ "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
+ "dev": true
+ },
"vm-browserify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz",
@@ -8137,6 +8480,13 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
+ "ws": {
+ "version": "7.4.5",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
+ "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
+ "dev": true,
+ "requires": {}
+ },
"xhr": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz",
diff --git a/client/package.json b/client/package.json
index 0209c76f..1df649ad 100644
--- a/client/package.json
+++ b/client/package.json
@@ -3,8 +3,7 @@
"private": true,
"scripts": {
"build": "node build.js",
- "watch": "bash watch.sh",
- "watchify": "watchify ./js/**/*.js -o ./public/js/app.min.js -d -v"
+ "watch": "node build.js --watch"
},
"dependencies": {
"dompurify": "^2.0.17",
@@ -27,9 +26,11 @@
"glob": "^7.1.2",
"html-minifier": "^3.5.18",
"jimp": "^0.13.0",
+ "pretty-error": "^3.0.3",
"stylus": "^0.54.5",
"terser": "^3.7.7",
"underscore": "^1.9.1",
- "watchify": "^4.0.0"
+ "watchify": "^4.0.0",
+ "ws": "^7.4.5"
}
}
diff --git a/client/watch.sh b/client/watch.sh
deleted file mode 100644
index 09e422ba..00000000
--- a/client/watch.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-npm run watchify &
-
-c1="";
-while :; do
- c2=$(find html css img -type f -and -not -iname '*autogen*'|sort|xargs cat|md5sum);
- [[ $c1 != $c2 ]] && npm run build -- --debug --no-js --no-binary-assets --no-web-app-files
- c1=$c2;
- sleep 1;
-done
-
-wait