refactor: use handlebars template engine to render the index html conditionally

This commit is contained in:
Xymorot 2019-10-15 21:30:56 +02:00
parent 5237efb88c
commit a7d125bfaf
11 changed files with 62 additions and 26 deletions

1
.gitignore vendored
View File

@ -10,7 +10,6 @@ node_modules
/tests/**/*.js /tests/**/*.js
/tests/**/*.js.map /tests/**/*.js.map
/frontend /frontend
/index.html
# managed by application # managed by application
/database /database

View File

@ -9,3 +9,6 @@ overrides:
- files: '*.svelte' - files: '*.svelte'
options: options:
parser: html parser: html
- files: '*.handlebars'
options:
parser: html

View File

@ -7,6 +7,7 @@ const ignoreList = [
/^\/node_modules\/\.cache($|\/)/, /^\/node_modules\/\.cache($|\/)/,
/^\/src\/.*\.(ts|js\.map)/, /^\/src\/.*\.(ts|js\.map)/,
/^\/store($|\/)/, /^\/store($|\/)/,
/^\/templates($|\/)/,
/^\/tests($|\/)/, /^\/tests($|\/)/,
/^\/\.editorconfig/, /^\/\.editorconfig/,
/^\/\.eslintignore/, /^\/\.eslintignore/,
@ -17,7 +18,6 @@ const ignoreList = [
/^\/\.prettierrc\.yml/, /^\/\.prettierrc\.yml/,
/^\/forge.config\.js/, /^\/forge.config\.js/,
/^\/gulpfile\.js/, /^\/gulpfile\.js/,
/^\/index\..*\.html/,
/^\/package-lock\.json/, /^\/package-lock\.json/,
/^\/tsconfig\.json/, /^\/tsconfig\.json/,
/^\/tslint\.json/, /^\/tslint\.json/,

View File

@ -6,6 +6,7 @@ const minimist = require('minimist');
const tsConfig = require('./tsconfig.json'); const tsConfig = require('./tsconfig.json');
const webpack = require('webpack-stream'); const webpack = require('webpack-stream');
const webpackConfig = require('./webpack.config'); const webpackConfig = require('./webpack.config');
const templating = require('./templates');
const argv = minimist(process.argv); const argv = minimist(process.argv);
@ -23,12 +24,15 @@ function buildFrontend() {
.pipe(dest(config.output.path)); .pipe(dest(config.output.path));
} }
function copyIndexHtml(cb) { function buildIndexHtml(cb) {
let indexHtml = 'index.prod.html'; let isDev = false;
if (argv.dev) { if (argv.dev) {
indexHtml = 'index.dev.html'; isDev = true;
} }
fs.copyFileSync(indexHtml, 'index.html'); const html = templating.compile(isDev);
fs.writeFileSync(path.resolve(webpackConfig.output.path, 'index.html'), html);
cb(); cb();
} }
@ -48,10 +52,10 @@ function transpileTypescript(cb) {
function build(cb) { function build(cb) {
if (argv.watch) { if (argv.watch) {
watch(tsConfig.include, { ignoreInitial: false }, transpileTypescript); watch(tsConfig.include, { ignoreInitial: false }, transpileTypescript);
watch('index.*.html', { ignoreInitial: false }, copyIndexHtml); watch('./templates/**/*', { ignoreInitial: false }, buildIndexHtml);
buildFrontend(); buildFrontend();
} else { } else {
parallel(transpileTypescript, copyIndexHtml, buildFrontend)(cb); parallel(transpileTypescript, buildIndexHtml, buildFrontend)(cb);
} }
} }
build.flags = { build.flags = {

View File

@ -1,10 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'unsafe-inline'" />
<title>Renai</title>
</head>
<body id="app"></body>
<script src="./frontend/bundle.js"></script>
</html>

6
package-lock.json generated
View File

@ -10297,9 +10297,9 @@
"dev": true "dev": true
}, },
"uglify-js": { "uglify-js": {
"version": "3.6.1", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.1.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.2.tgz",
"integrity": "sha512-+dSJLJpXBb6oMHP+Yvw8hUgElz4gLTh82XuX68QiJVTXaE5ibl6buzhNkQdYhBlIhozWOC9ge16wyRmjG4TwVQ==", "integrity": "sha512-+gh/xFte41GPrgSMJ/oJVq15zYmqr74pY9VoM69UzMzq9NFk4YDylclb1/bhEzZSaUQjbW5RvniHeq1cdtRYjw==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {

View File

@ -20,8 +20,8 @@
"eslint": "eslint .", "eslint": "eslint .",
"tslint-check": "tslint-config-prettier-check ./tslint.json", "tslint-check": "tslint-config-prettier-check ./tslint.json",
"tslint": "tslint -t stylish -p tsconfig.json", "tslint": "tslint -t stylish -p tsconfig.json",
"prettier": "prettier --ignore-path .gitignore -c **/*.{html,json,{c,sc,sa,le}ss,yml,svelte,md,ts,js}", "prettier": "prettier --ignore-path .gitignore -c **/*.{html,handlebars,json,{c,sc,sa,le}ss,yml,svelte,md,ts,js}",
"prettier:write": "prettier --ignore-path .gitignore --write **/*.{html,json,{c,sc,sa,le}ss,yml,svelte,md,ts,js}", "prettier:write": "prettier --ignore-path .gitignore --write **/*.{html,handlebars,json,{c,sc,sa,le}ss,yml,svelte,md,ts,js}",
"forge:start": "electron-forge start", "forge:start": "electron-forge start",
"forge:make": "electron-forge --platform win32 --arch x64 make", "forge:make": "electron-forge --platform win32 --arch x64 make",
"forge": "npm run build && npm run forge:make", "forge": "npm run build && npm run forge:make",
@ -56,6 +56,7 @@
"fast-check": "^1.17.0", "fast-check": "^1.17.0",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-cli": "^2.2.0", "gulp-cli": "^2.2.0",
"handlebars": "^4.4.3",
"husky": "^3.0.8", "husky": "^3.0.8",
"minimist": "^1.2.0", "minimist": "^1.2.0",
"mocha": "^6.2.1", "mocha": "^6.2.1",

View File

@ -38,7 +38,7 @@ async function createWindow(): Promise<void> {
mainWindow = new BrowserWindow(options); mainWindow = new BrowserWindow(options);
// and load the index.html of the app. // and load the index.html of the app.
await mainWindow.loadFile('index.html'); await mainWindow.loadFile('frontend/index.html');
// Open the DevTools. // Open the DevTools.
mainWindow.webContents.openDevTools(); mainWindow.webContents.openDevTools();

17
templates/data.json Normal file
View File

@ -0,0 +1,17 @@
{
"prod": {
"csp": {
"default-src": ["self"],
"style-src": ["unsafe-inline"]
},
"appBundle": "./bundle.js"
},
"dev": {
"csp": {
"default-src": ["self"],
"style-src": ["unsafe-inline"],
"script-src": ["self", "unsafe-eval"]
},
"appBundle": "./bundle.js"
}
}

View File

@ -2,12 +2,14 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
{{#if csp}}
<meta <meta
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"
content="default-src 'self'; style-src 'unsafe-inline'; script-src 'self' 'unsafe-eval';" content="{{#each csp}}{{@key}}{{#each this}} '{{this}}'{{/each}};{{/each}}"
/> />
{{/if}}
<title>Renai</title> <title>Renai</title>
</head> </head>
<body id="app"></body> <body id="app"></body>
<script src="./frontend/bundle.js"></script> <script src="{{appBundle}}"></script>
</html> </html>

20
templates/index.js Normal file
View File

@ -0,0 +1,20 @@
const handlebars = require('handlebars');
const path = require('path');
const fs = require('fs');
const data = require('./data');
function compile(isDevMode = false) {
const templatePath = path.resolve(__dirname, 'index.html.handlebars');
const template = fs.readFileSync(templatePath).toString();
const compiled = handlebars.compile(template);
let result = '';
if (isDevMode) {
result = compiled(data.dev);
} else {
result = compiled(data.prod);
}
return result;
}
exports.compile = compile;