Use Benchpress (#5901)

* Use Benchpress

* Use Benchpress.compileParse

* Error for template load failure

* Use benchpressjs package

* Compile templates on demand

* Fix user settings page

* Fix admin search to exclude `.jst` files

* Fix 500-embed

So ajaxify can still show an error if the server goes down
This commit is contained in:
Peter Jaszkowiak
2017-08-24 17:26:50 -06:00
committed by Barış Soner Uşaklı
parent 864321f727
commit abffc29128
16 changed files with 128 additions and 55 deletions

View File

@@ -14,10 +14,12 @@ function filterDirectories(directories) {
// get the relative path
return dir.replace(/^.*(admin.*?).tpl$/, '$1');
}).filter(function (dir) {
// exclude .jst files
// exclude partials
// only include subpaths
// exclude category.tpl, group.tpl, category-analytics.tpl
return !dir.includes('/partials/') &&
return !dir.endsWith('.jst') &&
!dir.includes('/partials/') &&
/\/.*\//.test(dir) &&
!/manage\/(category|group|category-analytics)$/.test(dir);
});

View File

@@ -3,7 +3,7 @@
var async = require('async');
var winston = require('winston');
var nconf = require('nconf');
var templates = require('templates.js');
var Benchpress = require('benchpressjs');
var nodemailer = require('nodemailer');
var sendmailTransport = require('nodemailer-sendmail-transport');
var smtpTransport = require('nodemailer-smtp-transport');
@@ -173,9 +173,9 @@ Emailer.sendViaFallback = function (data, callback) {
};
function render(tpl, params, next) {
if (meta.config['email:custom:' + tpl.replace('emails/', '')]) {
var text = templates.parse(meta.config['email:custom:' + tpl.replace('emails/', '')], params);
next(null, text);
var customTemplate = meta.config['email:custom:' + tpl.replace('emails/', '')];
if (customTemplate) {
Benchpress.compileParse(customTemplate, params, next);
} else {
app.render(tpl, params, next);
}

View File

@@ -29,7 +29,7 @@ JS.scripts = {
'public/vendor/tinycon/tinycon.js',
'public/vendor/xregexp/xregexp.js',
'public/vendor/xregexp/unicode/unicode-base.js',
'node_modules/templates.js/lib/templates.js',
'node_modules/benchpressjs/build/benchpress.js',
'public/src/utils.js',
'public/src/sockets.js',
'public/src/app.js',

View File

@@ -11,6 +11,8 @@ var nconf = require('nconf');
var plugins = require('../plugins');
var file = require('../file');
var viewsPath = nconf.get('views_dir');
var Templates = module.exports;
Templates.compile = function (callback) {
@@ -18,7 +20,6 @@ Templates.compile = function (callback) {
var themeConfig = require(nconf.get('theme_config'));
var baseTemplatesPaths = themeConfig.baseTheme ? getBaseTemplates(themeConfig.baseTheme) : [nconf.get('base_templates_path')];
var viewsPath = nconf.get('views_dir');
function processImports(paths, relativePath, source, callback) {
var regex = /<!-- IMPORT (.+?) -->/;
@@ -63,9 +64,9 @@ Templates.compile = function (callback) {
var source = file.toString();
processImports(paths, relativePath, source, next);
},
function (compiled, next) {
function (source, next) {
mkdirp(path.join(viewsPath, path.dirname(relativePath)), function (err) {
next(err, compiled);
next(err, source);
});
},
function (compiled, next) {
@@ -74,6 +75,9 @@ Templates.compile = function (callback) {
], next);
}, next);
},
function (next) {
rimraf(path.join(viewsPath, '*.jst'), next);
},
function (next) {
winston.verbose('[meta/templates] Successfully compiled templates.');
next();
@@ -99,7 +103,6 @@ function getBaseTemplates(theme) {
function preparePaths(baseTemplatesPaths, callback) {
var coreTemplatesPath = nconf.get('core_templates_path');
var viewsPath = nconf.get('views_dir');
var pluginTemplates;
async.waterfall([
function (next) {

View File

@@ -2,11 +2,13 @@
var async = require('async');
var path = require('path');
var fs = require('fs');
var csrf = require('csurf');
var validator = require('validator');
var nconf = require('nconf');
var ensureLoggedIn = require('connect-ensure-login');
var toobusy = require('toobusy-js');
var Benchpress = require('benchpressjs');
var plugins = require('../plugins');
var meta = require('../meta');
@@ -186,3 +188,33 @@ middleware.delayLoading = function (req, res, next) {
// Introduces an artificial delay during load so that brute force attacks are effectively mitigated
setTimeout(next, 1000);
};
var viewsDir = nconf.get('views_dir');
middleware.templatesOnDemand = function (req, res, next) {
var filePath = req.filePath || path.join(viewsDir, req.path);
if (!filePath.endsWith('.jst')) {
return next();
}
async.waterfall([
function (cb) {
file.exists(filePath, cb);
},
function (exists, cb) {
if (exists) {
return next();
}
fs.readFile(filePath.replace(/\.jst$/, '.tpl'), cb);
},
function (source, cb) {
Benchpress.precompile({
source: source.toString(),
minify: global.env !== 'development',
}, cb);
},
function (compiled, cb) {
fs.writeFile(filePath, compiled, cb);
},
], next);
};

View File

@@ -4,11 +4,12 @@ var nconf = require('nconf');
var winston = require('winston');
var path = require('path');
var async = require('async');
var express = require('express');
var meta = require('../meta');
var controllers = require('../controllers');
var plugins = require('../plugins');
var user = require('../user');
var express = require('express');
var accountRoutes = require('./accounts');
var metaRoutes = require('./meta');
@@ -147,6 +148,7 @@ module.exports = function (app, middleware, hotswapIds, callback) {
}
app.use(middleware.privateUploads);
app.use(relativePath + '/assets/templates', middleware.templatesOnDemand);
var statics = [
{ route: '/assets', path: path.join(__dirname, '../../build/public') },

View File

@@ -1,8 +1,12 @@
<script type="text/tpl" data-template="500">
&#x3C;div class=&#x22;alert alert-danger&#x22;&#x3E;
&#x9;&#x3C;strong&#x3E;[[global:500.title]]&#x3C;/strong&#x3E;
&#x9;&#x3C;p&#x3E;[[global:500.message]]&#x3C;/p&#x3E;
&#x9;&#x3C;p&#x3E;{path}&#x3C;/p&#x3E;
&#x9;&#x3C;!-- IF error --&#x3E;&#x3C;p&#x3E;{error}&#x3C;/p&#x3E;&#x3C;!-- ENDIF error --&#x3E;
&#x3C;/div&#x3E;
<script>
define('/assets/templates/500.jst', function () {
function compiled(helpers, context, get, iter, helper) {
return '<div class="alert alert-danger">\n\t<strong>[[global:500.title]]</strong>\n\t<p>[[global:500.message]]</p>\n\t<p>' +
helpers.__escape(get(context && context['path'])) + '</p>\n\t' +
(get(context && context['error']) ? '<p>' + helpers.__escape(get(context && context['error'])) + '</p>' : '') + '\n\n\t' +
(get(context && context['returnLink']) ? '\n\t<p>[[error:goback]]</p>\n\t' : '') + '\n</div>\n';
}
return compiled;
});
</script>

View File

@@ -27,7 +27,7 @@ var plugins = require('./plugins');
var flags = require('./flags');
var routes = require('./routes');
var auth = require('./routes/authentication');
var templates = require('templates.js');
var Benchpress = require('benchpressjs');
var helpers = require('../public/src/modules/helpers');
@@ -119,11 +119,24 @@ function setupExpressApp(app, callback) {
var middleware = require('./middleware');
var relativePath = nconf.get('relative_path');
var viewsDir = nconf.get('views_dir');
app.engine('tpl', templates.__express);
app.engine('tpl', function (filepath, data, next) {
filepath = filepath.replace(/\.tpl$/, '.jst');
middleware.templatesOnDemand({
filePath: filepath,
}, null, function (err) {
if (err) {
return next(err);
}
Benchpress.__express(filepath, data, next);
});
});
app.set('view engine', 'tpl');
app.set('views', nconf.get('views_dir'));
app.set('json spaces', process.env.NODE_ENV === 'development' ? 4 : 0);
app.set('views', viewsDir);
app.set('json spaces', global.env === 'development' ? 4 : 0);
app.use(flash());
app.enable('view cache');

View File

@@ -2,8 +2,8 @@
var async = require('async');
var winston = require('winston');
var templates = require('templates.js');
var _ = require('lodash');
var Benchpress = require('benchpressjs');
var plugins = require('../plugins');
var translator = require('../translator');
@@ -93,12 +93,12 @@ function renderWidget(widget, uid, options, callback) {
if (widget.data.container && widget.data.container.match('{body}')) {
translator.translate(widget.data.title, function (title) {
html = templates.parse(widget.data.container, {
Benchpress.compileParse(widget.data.container, {
title: title,
body: html,
}, function (err, html) {
next(err, { html: html });
});
next(null, { html: html });
});
} else {
next(null, { html: html });