diff --git a/src/static/app.mjs b/src/static/app.mjs
index d17e279..e09f407 100644
--- a/src/static/app.mjs
+++ b/src/static/app.mjs
@@ -1,5 +1,3 @@
-import __INDEX__ from "./index.html";
-
import make_router from './js/routes_client.mjs';
window.addEventListener("load", (_event) => {
diff --git a/src/static/esbuild.mjs b/src/static/esbuild.mjs
index 2eacd88..189194e 100755
--- a/src/static/esbuild.mjs
+++ b/src/static/esbuild.mjs
@@ -1,21 +1,45 @@
#!/usr/bin/env node
"use strict";
+import fs from 'fs';
import path from 'path';
+import crypto from 'crypto';
import esbuild from 'esbuild';
const __dirname = import.meta.url.slice(7, import.meta.url.lastIndexOf("/"));
+/**
+ * Hashes the contents of a file.
+ * @ref https://stackoverflow.com/a/44643479/1460422
+ * @param {string} hashName The name of the hash algorithm to use.
+ * @param {string} path The path to the file to hash.
+ * @return {string} The resulting hash as a hexadecimal string.
+ */
+function hash_file(hashName, path) {
+ return new Promise((resolve, reject) => {
+ const hash = crypto.createHash(hashName);
+ const stream = fs.createReadStream(path);
+ stream.once("error", reject);
+ stream.on("data", chunk => hash.update(chunk));
+ stream.once("end", () => {
+ stream.off("error", reject);
+ resolve(hash.digest('base64'));
+ });
+ });
+}
+
(async () => {
- "use strict";
-
+ "use strict";
+
+ const outdir = path.resolve(__dirname, "../static-dist");
+
const result = await esbuild.build({
entryPoints: [
"./app.mjs",
"./app.css"
].map(filepath => path.resolve(__dirname, filepath)),
- outdir: path.resolve(__dirname, "../static-dist"),
+ outdir,
bundle: true,
minify: true,
sourcemap: true,
@@ -28,9 +52,23 @@ const __dirname = import.meta.url.slice(7, import.meta.url.lastIndexOf("/"));
".ttf": "file"
}
});
- console.log(result);
+ if(result.errors.length > 0 || result.warnings.length > 0)
+ console.log(result);
+ // We *would* use SHA3 here, but we need to use SHA2 for subresource integrity
+ let algorithm = "sha256";
+ let css_hash = await hash_file(algorithm, path.join(outdir, "app.css"));
+ let js_hash = await hash_file(algorithm, path.join(outdir, "app.js"));
+
+ let html = (await fs.promises.readFile(path.join(__dirname, "index.html"), "utf-8"))
+ .replace(/\{JS_HASH\}/g, js_hash)
+ .replace(/\{CSS_HASH\}/g, css_hash)
+ .replace(/\{JS_HASH_SHORT\}/g, js_hash.substring(0, 7).replace(/[+/=]/, ""))
+ .replace(/\{CSS_HASH_SHORT\}/g, css_hash.substring(0, 7).replace(/[+/=]/, ""))
+ .replace(/\{ALGO\}/g, algorithm);
// TODO: Use fs.promises.copyFile() for index.html here, and also maybe find & replace for css/js filenames that we can then randomise?
+ await fs.promises.writeFile(path.join(outdir, "index.html"), html);
+
// console.log(await esbuild.analyzeMetafile(result.metafile));
})();
diff --git a/src/static/index.html b/src/static/index.html
index 37a6d9d..cfd0afa 100644
--- a/src/static/index.html
+++ b/src/static/index.html
@@ -18,7 +18,7 @@
-
-
+
+