Skip to content

Commit

Permalink
Consolidate is dead, long live getRenderFn
Browse files Browse the repository at this point in the history
  • Loading branch information
sgress454 committed Oct 28, 2016
1 parent e6785a5 commit 6316452
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 210 deletions.
6 changes: 3 additions & 3 deletions lib/hooks/http/initialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ module.exports = function(sails) {
expressApp.set('views', sails.config.paths.views);

// Teach Express how to render templates w/ our configured view extension
expressApp.engine(sails.config.views.engine.ext, sails.config.views.engine.fn);
expressApp.engine(sails.config.views.extension, sails.hooks.views._renderFn);

// Set default view engine
sails.log.verbose('Setting default Express view engine to ' + sails.config.views.engine.ext + '...');
expressApp.set('view engine', sails.config.views.engine.ext);
sails.log.verbose('Setting default Express view engine to ' + sails.config.views.extension + '...');
expressApp.set('view engine', sails.config.views.extension);
});
}

Expand Down
152 changes: 33 additions & 119 deletions lib/hooks/views/configure.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
var path = require('path');
var util = require('util');
var _ = require('lodash');
var consolidate = require('consolidate');


/**
Expand All @@ -16,136 +15,51 @@ var consolidate = require('consolidate');
*/
module.exports = function configure ( sails ) {

if (sails.config.viewEngine) {
sails.log.warn('The `config.viewEngine` config has been deprecated in favor of `config.views.engine`.');
sails.log.warn('It has been automatically migrated, but you\'ll continue to see this warning until you change your configuration files.');
sails.config.views.engine = sails.config.viewEngine;
if (sails.config.views.engine) {
sails.log.warn('The `config.views.engine` config has been deprecated. ' +
'In Sails 1.x, use `config.views.extension` to choose your view extension (defaults to ".ejs"),\n' +
'and use `config.views.getRenderFn` to configure your template engine (or leave undefined to use\n' +
'the built-in EJS template support.');
sails.config.views.extension = sails.config.views.engine.ext || 'ejs';
delete sails.config.views.engine;
}

// Normalize view engine config and allow defining a custom extension
if (_.isString(sails.config.views.engine)) {
var viewExt = sails.config.views.extension || sails.config.views.engine;
sails.config.views.engine = {
name: sails.config.views.engine,
ext: viewExt
};
}

// Get the view engine name
var engineName = sails.config.views.engine.name || sails.config.views.engine.ext;

// Ensure valid config
if (! (sails.config.views.engine && sails.config.views.engine.ext) ) {
sails.log.error('Invalid view engine configuration. `config.views.engine` should');
sails.log.error('be set to either a `string` or an `object` with the following properties:');
sails.log.error(' {');
sails.log.error(' ext: <string>, // the file extension');
sails.log.error(' fn: <function> // the template engine render function');
sails.log.error(' }');
sails.log.error('For example: {ext:"html", fn: require("consolidate").swig}');
sails.log.error('For details: http://expressjs.com/api.html#app.engine');
throw new Error('Invalid view engine configuration.');
// Let user know that a leading . is not required in the viewEngine option and then fix it
if (sails.config.views.extension[0] === '.') {
sails.log.warn('A leading `.` is not required in the config.views.extension option. Removing it for you...');
sails.config.views.extension = sails.config.views.extension.substr(1);
}

// Try to load view module if a function wasn't specified directly
if ( !sails.config.views.engine.fn ) {

var appDependenciesPath;
var fn;

appDependenciesPath = path.join(sails.config.appPath, 'node_modules');

try {

// Try to load the view engine, optionally using a separate module
// (see https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js#L568)
fn = getEngine(appDependenciesPath,engineName,sails.config.views.engine.module, sails);
if (!_.isUndefined(sails.config.views.getRenderFn) && !_.isFunction(sails.config.views.getRenderFn)) {
sails.log.error('Ignoring invalid `config.views.getRenderFn` setting (expected a function, but got: ' + util.inspect(sails.config.views.getRenderFn));
delete sails.config.views.getRenderFn;
}

// If the engine doesn't export a function, it's not consolidate-compatible
if ( !_.isFunction(fn) ) {
sails.log.error(util.format('Invalid view engine (%s)-- are you sure it supports `consolidate`?', engineName));
throw new Error();
}
else if (sails.config.views.getRenderFn) {
var renderFn = sails.config.views.getRenderFn();
if (!_.isFunction(renderFn)) {
sails.log.error('Ignoring invalid value returned from calling `config.views.getRenderFn` (expected a function, but got: ' + util.inspect(renderFn));
return;
}
sails.hooks.views._renderFn = renderFn;

// If the engine can't be loaded, we can't continue
catch (e) {
sails.log.error('Your configured server-side view engine (' + engineName + ') could not be found.');
sails.log.error('Usually, this just means you need to install a dependency.');
sails.log.error('To install ' + engineName + ', try running: `npm install ' + engineName + ' --save`');
sails.log.error('Otherwise, please change your `engine` configuration in config/views.js.');
throw e;
if (sails.config.views.layout) {
sails.log.warn('Ignoring `sails.config.views.layout`...');
sails.log.warn('Sails\' built-in layout support only works with the default EJS view engine.');
sails.log.warn('You\'re using a custom view engine, so you\'ll need to implement layouts on your own!');
}

// Save reference to view rendering function
// munge callback to protect against https://github.com/tj/consolidate.js/issues/143
sails.config.views.engine.fn = function (str, options, cb) {
fn(str, options, function (e, result) { setImmediate(function () { cb(e, result); }); });
};
sails.log.silly('Configured view engine, `' + engineName + '`');
}

// Let user know that a leading . is not required in the viewEngine option and then fix it
if (sails.config.views.engine.ext[0] === '.') {
sails.log.warn('A leading `.` is not required in the views.engine option. Removing it for you...');
sails.config.views.engine.ext = sails.config.views.engine.ext.substr(1);
}

// Custom layout location
// (if string specified, it's used as the relative path from the views folder)
// (if not string, but truthy, relative path from views folder defaults to ./layout.*)
// (if falsy, don't use layout)
if ( !_.isString(sails.config.views.layout) && sails.config.views.layout ) {
sails.config.views.layout = 'layout.' + sails.config.views.engine.ext;
}

if ( sails.config.views.layout && engineName !== 'ejs' ) {
sails.log.warn('Sails\' built-in layout support only works with the EJS view engine.');
sails.log.warn('You\'re using `'+ engineName +'`.');
sails.log.warn('Ignoring `sails.config.views.layout`...');
}
};




/**
* getEngine()
*
* Load a view engine either from the Consolidate cache,
* or from a separate module installed locally in the Sails app.
* (see https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js#L568)
*
* @param {String} appDependenciesPath
* @param {String} engineName
* @param {String} moduleName
* @param {SailsApp} sails
* @returns {Function}
*/
function getEngine(appDependenciesPath, engineName, moduleName, sails) {

// Most of the time the module name and engine name are the same
moduleName = moduleName || engineName;

// Get the base template loading function from consolidate
var fn = consolidate[engineName];

// If we haven't cached the engine module in consolidate's requires cache, do it now.
if(!consolidate.requires[moduleName]) {
try {
//ensure the engine is required relative to the path of our app
consolidate.requires[moduleName] = require(appDependenciesPath+'/' + moduleName);
// If the engine name and module names are different, cache the engine under both
// keys, since Consolidate likes it both ways:
// https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js#L195
// https://github.com/tj/consolidate.js/blob/master/lib/consolidate.js#L568
if (engineName !== moduleName) {
consolidate.requires[engineName] = consolidate.requires[moduleName];
}
} catch(e) {
sails.log.info('Could not find module:', moduleName , 'in path:', appDependenciesPath);
else {
// Custom layout location
// (if string specified, it's used as the relative path from the views folder)
// (if not string, but truthy, relative path from views folder defaults to ./layout.*)
// (if falsy, don't use layout)
if ( !_.isString(sails.config.views.layout) && sails.config.views.layout ) {
sails.config.views.layout = 'layout.' + sails.config.views.extension;
}
}

return fn;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,23 @@

var path = require('path');
var _ = require('lodash');
var ejs = require('ejs');
var fs = require('fs');

var exists = fs.existsSync || path.existsSync;
var resolve = path.resolve;
var extname = path.extname;
var dirname = path.dirname;
var join = path.join;
var basename = path.basename;

/**
* Implement EJS layouts and partials (a la Express 2).
*
* For further explanation, see:
* => http://sailsjs.org/documentation/concepts/views/layouts#?why-do-layouts-only-work-for-ejs
* ------------------------------------------------------------------------------------------
* *
* @param {Sails} sails
*/
module.exports = function addShimForLayoutAndPartials (sails) {

// If layout config is truthy, attempt to use view partials/layout.
if (sails.config.views.layout) {

// Get the view engine name
var engineName = sails.config.views.engine.name || sails.config.views.engine.ext;

// Get the extension
var extension = sails.config.views.engine.ext || sails.config.views.extension;

// Use ejs-locals for all ejs templates
if (engineName === 'ejs') {
var ejsLayoutEngine = renderFile;
sails.log.verbose('Overriding ejs engine config with ejslocals to implement layout support...');
sails.config.views.engine.fn = ejsLayoutEngine;
}//</ejs>

}//</sails.config.views.layout is truthy>
};

/**
* Layout & Partial support for EJS.
*
* This is a slightly modified (for EJS 2.3.4) version of the defunct ejs-locals package
* https://github.com/randometc/ejs-locals
* (The MIT License)
Expand All @@ -48,17 +31,9 @@ module.exports = function addShimForLayoutAndPartials (sails) {
*
*/

var ejs = require('ejs');
var fs = require('fs');
var path = require('path');
var exists = fs.existsSync || path.existsSync;
var resolve = path.resolve;
var extname = path.extname;
var dirname = path.dirname;
var join = path.join;
var basename = path.basename;

function renderFile(file, options, fn){

module.exports = function renderFile(file, options, fn){

// Express used to set options.locals for us, but now we do it ourselves
// (EJS does some __proto__ magic to expose these funcs/values in the template)
if (!options.locals) {
Expand Down
4 changes: 2 additions & 2 deletions lib/hooks/views/get-implicit-defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ module.exports = function getImplicitDefaults (existingConfig) {
return {
views: {

// Engine for views (can be ejs, haml, etc.)
engine: 'ejs',
// Extension for view files
extension: 'ejs',

// Layout is on by default, in the top level of the view directory
// true === use default
Expand Down
9 changes: 4 additions & 5 deletions lib/hooks/views/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
var configure = require('./configure');
var getImplicitDefaults = require('./get-implicit-defaults');
var onRoute = require('./onRoute');
var addShimForLayoutAndPartials = require('./add-shim-for-layout-and-partials');
var defaultViewRenderingFn = require('./default-view-rendering-fn');
var addResViewMethod = require('./res.view');
var render = require('./render');
var statViews = require('./stat-views');
Expand All @@ -24,6 +24,9 @@ module.exports = function (sails) {

defaults: getImplicitDefaults,

// The view rendering function -- may be overriden if `sails.config.views.getRenderFn` is provided.
_renderFn: defaultViewRenderingFn,

configure: function (){
configure(sails);
},
Expand Down Expand Up @@ -69,10 +72,6 @@ module.exports = function (sails) {
return onRoute(sails, route);
});

// Declare hook loaded when ejs layouts have been applied,
// views have been inventoried, and view-serving middleware has been prepared
addShimForLayoutAndPartials(sails);

// Expose `sails.renderView()` function to userland.
// (experimental!)
sails.renderView = this.render;
Expand Down
14 changes: 7 additions & 7 deletions lib/hooks/views/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ module.exports = function (sails) {
}

// Disable sails built-in layouts for all view engine's except for ejs
if (sails.config.views.engine.ext !== 'ejs') {
if (sails.config.views.getRenderFn) {
layout = false;
}

var pathToViews = sails.config.paths.views;
var absPathToView = path.join(pathToViews, relPathToView) + '.' + sails.config.views.engine.ext;
var absPathToView = path.join(pathToViews, relPathToView) + '.' + sails.config.views.extension;

// Set layout file if enabled (using ejs-locals)
if (layout) {
Expand All @@ -68,22 +68,22 @@ module.exports = function (sails) {
path: relPathToView,
pathFromViews: relPathToView,
pathFromApp: path.join(path.relative(sails.config.appPath, sails.config.paths.views), relPathToView),
ext: sails.config.views.engine.ext
ext: sails.config.views.extension
};

// In development, provide access to complete path to view
// via `__dirname`
if (sails.config.environment !== 'production') {
options.__dirname = options.__dirname ||
absPathToView + '.' + sails.config.views.engine.ext;
absPathToView + '.' + sails.config.views.extension;
}

// Set the options for the view rendering engine. Copy all the current options into 'locals'
// in case the template engine expects them there.
_.extend(options, {
locals: _.cloneDeep(options),
settings: {
'view engine': sails.config.views.engine.ext,
'view engine': sails.config.views.extension,
'views': sails.config.paths.views
}
});
Expand All @@ -103,10 +103,10 @@ module.exports = function (sails) {
}

// Render the view
sails.config.views.engine.fn(absPathToView, options, cb_view);
sails.hooks.views._renderFn(absPathToView, options, cb_view);
});
} else {
sails.config.views.engine.fn(absPathToView, options, cb_view);
sails.hooks.views._renderFn(absPathToView, options, cb_view);
}

};
Expand Down
Loading

0 comments on commit 6316452

Please sign in to comment.