mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-01 19:46:01 +01:00
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:
committed by
Barış Soner Uşaklı
parent
864321f727
commit
abffc29128
@@ -99,7 +99,7 @@ module.exports = function (grunt) {
|
||||
'public/src/**/*.js',
|
||||
'node_modules/nodebb-*/**/*.js',
|
||||
'!node_modules/nodebb-*/node_modules/**',
|
||||
'node_modules/templates.js/lib/templates.js',
|
||||
'node_modules/benchpressjs/build/benchpress.js',
|
||||
'!node_modules/nodebb-*/.git/**',
|
||||
],
|
||||
options: {
|
||||
|
||||
@@ -9,6 +9,8 @@ var less = require('less');
|
||||
var async = require('async');
|
||||
var uglify = require('uglify-js');
|
||||
var nconf = require('nconf');
|
||||
var Benchpress = require('benchpressjs');
|
||||
|
||||
var app = express();
|
||||
var server;
|
||||
|
||||
@@ -35,7 +37,7 @@ web.install = function (port) {
|
||||
winston.info('Launching web installer on port', port);
|
||||
|
||||
app.use(express.static('public', {}));
|
||||
app.engine('tpl', require('templates.js').__express);
|
||||
app.engine('tpl', Benchpress.__express);
|
||||
app.set('view engine', 'tpl');
|
||||
app.set('views', path.join(__dirname, '../src/views'));
|
||||
app.use(bodyParser.urlencoded({
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"async": "2.4.1",
|
||||
"autoprefixer": "7.1.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"benchpressjs": "^1.0.1",
|
||||
"body-parser": "^1.9.0",
|
||||
"bootstrap": "^3.3.7",
|
||||
"chart.js": "^2.4.0",
|
||||
@@ -93,7 +94,6 @@
|
||||
"socketio-wildcard": "2.0.0",
|
||||
"spdx-license-list": "^3.0.1",
|
||||
"string": "^3.0.0",
|
||||
"templates.js": "0.3.11",
|
||||
"toobusy-js": "^0.5.1",
|
||||
"uglify-js": "^3.0.11",
|
||||
"validator": "7.0.0",
|
||||
|
||||
@@ -328,20 +328,10 @@ $(document).ready(function () {
|
||||
};
|
||||
|
||||
ajaxify.loadTemplate = function (template, callback) {
|
||||
if (templates.cache[template]) {
|
||||
callback(templates.cache[template]);
|
||||
} else {
|
||||
$.ajax({
|
||||
url: config.relative_path + '/assets/templates/' + template + '.tpl?' + config['cache-buster'],
|
||||
type: 'GET',
|
||||
success: function (data) {
|
||||
callback(data.toString());
|
||||
},
|
||||
error: function (error) {
|
||||
throw new Error('Unable to load template: ' + template + ' (' + error.statusText + ')');
|
||||
},
|
||||
require([config.relative_path + '/assets/templates/' + template + '.jst'], callback, function (err) {
|
||||
console.error('Unable to load template: ' + template);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function ajaxifyAnchors() {
|
||||
@@ -424,7 +414,9 @@ $(document).ready(function () {
|
||||
});
|
||||
}
|
||||
|
||||
templates.registerLoader(ajaxify.loadTemplate);
|
||||
require(['benchpress'], function (Benchpress) {
|
||||
Benchpress.registerLoader(ajaxify.loadTemplate);
|
||||
});
|
||||
|
||||
if (window.history && window.history.pushState) {
|
||||
// Progressive Enhancement, ajaxify available only to modern browsers
|
||||
@@ -432,9 +424,4 @@ $(document).ready(function () {
|
||||
}
|
||||
|
||||
app.load();
|
||||
|
||||
$('[type="text/tpl"][data-template]').each(function () {
|
||||
templates.cache[$(this).attr('data-template')] = $('<div/>').html($(this).html()).text();
|
||||
$(this).parent().remove();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,21 @@ app.cacheBuster = null;
|
||||
(function () {
|
||||
var showWelcomeMessage = !!utils.params().loggedin;
|
||||
|
||||
templates.setGlobal('config', config);
|
||||
require(['benchpress'], function (Benchpress) {
|
||||
Benchpress.setGlobal('config', config);
|
||||
if (Object.defineProperty) {
|
||||
Object.defineProperty(window, 'templates', {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
console.warn('[deprecated] Accessing benchpress (formerly know as templates.js) globally is deprecated. Use `require(["benchpress"], function (Benchpress) { ... })` instead');
|
||||
return Benchpress;
|
||||
},
|
||||
});
|
||||
} else {
|
||||
window.templates = Benchpress;
|
||||
}
|
||||
});
|
||||
|
||||
app.cacheBuster = config['cache-buster'];
|
||||
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
(function (factory) {
|
||||
if (typeof module === 'object' && module.exports) {
|
||||
var relative_path = require('nconf').get('relative_path');
|
||||
module.exports = factory(require('../utils'), require('templates.js'), require('string'), relative_path);
|
||||
module.exports = factory(require('../utils'), require('benchpressjs'), require('string'), relative_path);
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define('helpers', ['string'], function (string) {
|
||||
return factory(utils, templates, string, config.relative_path);
|
||||
define('helpers', ['benchpress', 'string'], function (Benchpress, string) {
|
||||
return factory(utils, Benchpress, string, config.relative_path);
|
||||
});
|
||||
} else {
|
||||
window.helpers = factory(utils, templates, window.String, config.relative_path);
|
||||
}
|
||||
}(function (utils, templates, S, relative_path) {
|
||||
}(function (utils, Benchpress, S, relative_path) {
|
||||
var helpers = {
|
||||
displayMenuItem: displayMenuItem,
|
||||
buildMetaTag: buildMetaTag,
|
||||
@@ -30,8 +30,13 @@
|
||||
renderDigestAvatar: renderDigestAvatar,
|
||||
userAgentIcons: userAgentIcons,
|
||||
register: register,
|
||||
__escape: identity,
|
||||
};
|
||||
|
||||
function identity(str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
function displayMenuItem(data, index) {
|
||||
var item = data.navigation[index];
|
||||
if (!item) {
|
||||
@@ -270,7 +275,7 @@
|
||||
|
||||
function register() {
|
||||
Object.keys(helpers).forEach(function (helperName) {
|
||||
templates.registerHelper(helperName, helpers[helperName]);
|
||||
Benchpress.registerHelper(helperName, helpers[helperName]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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') },
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<script type="text/tpl" data-template="500">
|
||||
<div class="alert alert-danger">
|
||||
	<strong>[[global:500.title]]</strong>
|
||||
	<p>[[global:500.message]]</p>
|
||||
	<p>{path}</p>
|
||||
	<!-- IF error --><p>{error}</p><!-- ENDIF error -->
|
||||
</div>
|
||||
<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>
|
||||
@@ -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');
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -14,6 +14,15 @@ describe('admin search', function () {
|
||||
]);
|
||||
done();
|
||||
});
|
||||
it('should exclude .jst files', function (done) {
|
||||
assert.deepEqual(search.filterDirectories([
|
||||
'hfjksfd/fdsgagag/admin/gdhgfsdg/sggag.tpl',
|
||||
'dfahdfsgf/admin/hgkfds/fdhsdfh.jst',
|
||||
]), [
|
||||
'admin/gdhgfsdg/sggag',
|
||||
]);
|
||||
done();
|
||||
});
|
||||
it('should exclude partials', function (done) {
|
||||
assert.deepEqual(search.filterDirectories([
|
||||
'hfjksfd/fdsgagag/admin/gdhgfsdg/sggag.tpl',
|
||||
|
||||
Reference in New Issue
Block a user