mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 19:15:58 +01:00 
			
		
		
		
	* widgets refactor render widgets server side widgets can use all the data the template can use * fix tests
		
			
				
	
	
		
			144 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| var async = require('async');
 | |
| var nconf = require('nconf');
 | |
| var validator = require('validator');
 | |
| var winston = require('winston');
 | |
| 
 | |
| var plugins = require('../plugins');
 | |
| var translator = require('../translator');
 | |
| var widgets = require('../widgets');
 | |
| 
 | |
| module.exports = function (middleware) {
 | |
| 	middleware.processRender = function (req, res, next) {
 | |
| 		// res.render post-processing, modified from here: https://gist.github.com/mrlannigan/5051687
 | |
| 		var render = res.render;
 | |
| 		res.render = function (template, options, fn) {
 | |
| 			var self = this;
 | |
| 			var req = this.req;
 | |
| 			var defaultFn = function (err, str) {
 | |
| 				if (err) {
 | |
| 					return next(err);
 | |
| 				}
 | |
| 				self.send(str);
 | |
| 			};
 | |
| 
 | |
| 			options = options || {};
 | |
| 			if (typeof options === 'function') {
 | |
| 				fn = options;
 | |
| 				options = {};
 | |
| 			}
 | |
| 			if (typeof fn !== 'function') {
 | |
| 				fn = defaultFn;
 | |
| 			}
 | |
| 
 | |
| 			var ajaxifyData;
 | |
| 			async.waterfall([
 | |
| 				function (next) {
 | |
| 					options.loggedIn = !!req.uid;
 | |
| 					options.relative_path = nconf.get('relative_path');
 | |
| 					options.template = { name: template };
 | |
| 					options.template[template] = true;
 | |
| 					options.url = (req.baseUrl + req.path).replace(/^\/api/, '');
 | |
| 					options.bodyClass = buildBodyClass(req);
 | |
| 
 | |
| 					plugins.fireHook('filter:' + template + '.build', { req: req, res: res, templateData: options }, next);
 | |
| 				},
 | |
| 				function (data, next) {
 | |
| 					plugins.fireHook('filter:middleware.render', { req: req, res: res, templateData: data.templateData }, next);
 | |
| 				},
 | |
| 				function (data, next) {
 | |
| 					options = data.templateData;
 | |
| 
 | |
| 					widgets.render(req.uid, {
 | |
| 						template: template + '.tpl',
 | |
| 						url: options.url,
 | |
| 						templateData: options,
 | |
| 						req: req,
 | |
| 						res: res,
 | |
| 					}, next);
 | |
| 				},
 | |
| 				function (data, next) {
 | |
| 					options.widgets = data;
 | |
| 
 | |
| 					res.locals.template = template;
 | |
| 					options._locals = undefined;
 | |
| 
 | |
| 					if (res.locals.isAPI) {
 | |
| 						if (req.route && req.route.path === '/api/') {
 | |
| 							options.title = '[[pages:home]]';
 | |
| 						}
 | |
| 
 | |
| 						return res.json(options);
 | |
| 					}
 | |
| 
 | |
| 					ajaxifyData = JSON.stringify(options).replace(/<\//g, '<\\/');
 | |
| 
 | |
| 					async.parallel({
 | |
| 						header: function (next) {
 | |
| 							renderHeaderFooter('renderHeader', req, res, options, next);
 | |
| 						},
 | |
| 						content: function (next) {
 | |
| 							render.call(self, template, options, next);
 | |
| 						},
 | |
| 						footer: function (next) {
 | |
| 							renderHeaderFooter('renderFooter', req, res, options, next);
 | |
| 						},
 | |
| 					}, next);
 | |
| 				},
 | |
| 				function (results, next) {
 | |
| 					var str = results.header +
 | |
| 						(res.locals.postHeader || '') +
 | |
| 						results.content + '<script id="ajaxify-data"></script>' +
 | |
| 						(res.locals.preFooter || '') +
 | |
| 						results.footer;
 | |
| 
 | |
| 					translate(str, req, res, next);
 | |
| 				},
 | |
| 				function (translated, next) {
 | |
| 					translated = translated.replace('<script id="ajaxify-data"></script>', function () {
 | |
| 						return '<script id="ajaxify-data" type="application/json">' + ajaxifyData + '</script>';
 | |
| 					});
 | |
| 					next(null, translated);
 | |
| 				},
 | |
| 			], fn);
 | |
| 		};
 | |
| 
 | |
| 		next();
 | |
| 	};
 | |
| 
 | |
| 	function renderHeaderFooter(method, req, res, options, next) {
 | |
| 		if (res.locals.renderHeader) {
 | |
| 			middleware[method](req, res, options, next);
 | |
| 		} else if (res.locals.renderAdminHeader) {
 | |
| 			middleware.admin[method](req, res, options, next);
 | |
| 		} else {
 | |
| 			next(null, '');
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function translate(str, req, res, next) {
 | |
| 		var language = (res.locals.config && res.locals.config.userLang) || 'en-GB';
 | |
| 		language = req.query.lang ? validator.escape(String(req.query.lang)) : language;
 | |
| 		translator.translate(str, language, function (translated) {
 | |
| 			next(null, translator.unescape(translated));
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	function buildBodyClass(req) {
 | |
| 		var clean = req.path.replace(/^\/api/, '').replace(/^\/|\/$/g, '');
 | |
| 		var parts = clean.split('/').slice(0, 3);
 | |
| 		parts.forEach(function (p, index) {
 | |
| 			try {
 | |
| 				p = decodeURIComponent(p);
 | |
| 			} catch (err) {
 | |
| 				winston.error(err.message);
 | |
| 				p = '';
 | |
| 			}
 | |
| 			p = validator.escape(String(p));
 | |
| 			parts[index] = index ? parts[0] + '-' + p : 'page-' + (p || 'home');
 | |
| 		});
 | |
| 		return parts.join(' ');
 | |
| 	}
 | |
| };
 |