Skip to content

Commit

Permalink
Merge pull request #1606 from Gotvitch/issue1203
Browse files Browse the repository at this point in the history
Bug fixes for partial views
  • Loading branch information
ErisDS committed Dec 12, 2013
2 parents 7c8abb0 + fef9b4b commit 968176c
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 253 deletions.
62 changes: 40 additions & 22 deletions core/server/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ var _ = require('underscore'),
coreHelpers = {},
registerHelpers;



/**
* [ description]
* @todo ghost core helpers + a way for themes to register them
Expand Down Expand Up @@ -536,10 +538,6 @@ coreHelpers.has_tag = function (name, options) {
return options.inverse(this);
};

// ## Template driven helpers
// Template driven helpers require that their template is loaded before they can be registered.
coreHelpers.paginationTemplate = null;

// ### Pagination Helper
// `{{pagination}}`
// Outputs previous and next buttons, along with info about the current page
Expand All @@ -564,7 +562,7 @@ coreHelpers.pagination = function (options) {
errors.logAndThrowError('Invalid value, check page, pages, limit and total are numbers');
return;
}
return new hbs.handlebars.SafeString(coreHelpers.paginationTemplate(this.pagination));
return template.execute('pagination', this.pagination);
};

coreHelpers.helperMissing = function (arg) {
Expand All @@ -574,13 +572,8 @@ coreHelpers.helperMissing = function (arg) {
errors.logError('Missing helper: "' + arg + '"');
};

// Register a handlebars helper for themes
function registerThemeHelper(name, fn) {
hbs.registerHelper(name, fn);
}

// Register an async handlebars helper for themes
function registerAsyncThemeHelper(name, fn) {
// Register an async handlebars helper for a given handlebars instance
function registerAsyncHelper(hbs, name, fn) {
hbs.registerAsyncHelper(name, function (options, cb) {
// Wrap the function passed in with a when.resolve so it can
// return either a promise or a value
Expand All @@ -592,12 +585,39 @@ function registerAsyncThemeHelper(name, fn) {
});
}

registerHelpers = function (config) {
var paginationHelper;

// Register a handlebars helper for themes
function registerThemeHelper(name, fn) {
hbs.registerHelper(name, fn);
}

// Register an async handlebars helper for themes
function registerAsyncThemeHelper(name, fn) {
registerAsyncHelper(hbs, name, fn);
}

// Register a handlebars helper for admin
function registerAdminHelper(name, fn) {
coreHelpers.adminHbs.registerHelper(name, fn);
}

// Register an async handlebars helper for admin
function registerAsyncAdminHelper(name, fn) {
registerAsyncHelper(coreHelpers.adminHbs, name, fn);
}



registerHelpers = function (config, adminHbs) {

// And expose config
coreHelpers.config = config;

// Expose hbs instance for admin
coreHelpers.adminHbs = adminHbs;


// Register theme helpers
registerThemeHelper('asset', coreHelpers.asset);

registerThemeHelper('author', coreHelpers.author);
Expand All @@ -622,6 +642,8 @@ registerHelpers = function (config) {

registerThemeHelper('pageUrl', coreHelpers.pageUrl);

registerThemeHelper('pagination', coreHelpers.pagination);

registerThemeHelper('tags', coreHelpers.tags);

registerAsyncThemeHelper('body_class', coreHelpers.body_class);
Expand All @@ -640,18 +662,14 @@ registerHelpers = function (config) {

registerAsyncThemeHelper('url', coreHelpers.url);

paginationHelper = template.loadTemplate('pagination').then(function (templateFn) {
coreHelpers.paginationTemplate = templateFn;

registerThemeHelper('pagination', coreHelpers.pagination);
});
// Register admin helpers
registerAdminHelper('asset', coreHelpers.asset);

// Return once the template-driven helpers have loaded
return when.join(
paginationHelper
);
registerAdminHelper('ghostScriptTags', coreHelpers.ghostScriptTags);
};


module.exports = coreHelpers;
module.exports.loadCoreHelpers = registerHelpers;
module.exports.registerThemeHelper = registerThemeHelper;
Expand Down
45 changes: 15 additions & 30 deletions core/server/helpers/template.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,27 @@
var templates = {},
nodefn = require('when/node/function'),
fs = require('fs'),
hbs = require('express-hbs'),
errors = require('../errorHandling'),
path = require('path'),
when = require('when'),
config = require('../config'),
api = require('../api');
errors = require('../errorHandling');

// ## Template utils

// Compile a template for a handlebars helper
templates.compileTemplate = function (templatePath) {
return nodefn.call(fs.readFile, templatePath).then(function (templateContents) {
return hbs.handlebars.compile(templateContents.toString());
}, errors.logAndThrowError);
};
// Execute a template helper
// All template helpers are register as partial view.
templates.execute = function (name, context) {

// Load a template for a handlebars helper
templates.loadTemplate = function (name) {
var templateFileName = name + '.hbs',
deferred = when.defer();
// Check for theme specific version first
return api.settings.read('activeTheme').then(function (activeTheme) {
var templatePath = path.join(config.paths().themePath, activeTheme.value, 'partials', templateFileName);
var partial = hbs.handlebars.partials[name];

// Can't use nodefn here because exists just returns one parameter, true or false
fs.exists(templatePath, function (exists) {
if (!exists) {
// Fall back to helpers templates location
templatePath = path.join(config.paths().helperTemplates, templateFileName);
}
if (partial === undefined) {
errors.logAndThrowError('Template ' + name + ' not found.');
return;
}

templates.compileTemplate(templatePath).then(deferred.resolve, deferred.reject);
});
// If the partial view is not compiled, it compiles and saves in handlebars
if (typeof partial === 'string') {
partial = hbs.handlebars.compile(partial);
hbs.handlebars.partials[name] = partial;
}

return deferred.promise;
});
return new hbs.handlebars.SafeString(partial(context));
};

module.exports = templates;
27 changes: 18 additions & 9 deletions core/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var config = require('./config'),
permissions = require('./permissions'),
uuid = require('node-uuid'),
api = require('./api'),
hbs = require('express-hbs'),

// Variables
setup,
Expand Down Expand Up @@ -105,25 +106,33 @@ function setup(server) {
permissions.init()
);
}).then(function () {
return when.join(
// Initialise mail after first run,
// passing in config module to prevent
// circular dependencies.
mailer.init(),
helpers.loadCoreHelpers(config)
);
// Initialise mail after first run,
// passing in config module to prevent
// circular dependencies.
return mailer.init();
}).then(function () {
var adminHbs;

// ##Configuration
// set the view engine
server.set('view engine', 'hbs');

// set the configured URL
server.set('ghost root', config.theme().path);

// return the correct mime type for woff filess
express['static'].mime.define({'application/font-woff': ['woff']});

// ## View engine
// set the view engine
server.set('view engine', 'hbs');

// Create a hbs instance for admin and init view engine
adminHbs = hbs.create();
server.set('admin view engine', adminHbs.express3({partialsDir: config.paths().adminViews + 'partials'}));

// Load helpers
helpers.loadCoreHelpers(config, adminHbs);


// ## Middleware
middleware(server, dbHash);

Expand Down
34 changes: 17 additions & 17 deletions core/server/middleware/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,13 @@ function ghostLocals(req, res, next) {
// Initialise Theme or Admin Views
function initViews(req, res, next) {
/*jslint unparam:true*/
var hbsOptions;

if (!res.isAdmin) {
// self.globals is a hack til we have a better way of getting combined settings & config
hbsOptions = {templateOptions: {data: {blog: config.theme()}}};
api.settings.read('activeTheme').then(function (activeTheme) {
if (config.paths().availableThemes[activeTheme.value].hasOwnProperty('partials')) {
// Check that the theme has a partials directory before trying to use it
hbsOptions.partialsDir = path.join(config.paths().themePath, activeTheme.value, 'partials');
}

expressServer.engine('hbs', hbs.express3(hbsOptions));
expressServer.set('views', path.join(config.paths().themePath, activeTheme.value));
});
hbs.updateTemplateOptions({ data: {blog: config.theme()} });
expressServer.engine('hbs', expressServer.get('theme view engine'));
expressServer.set('views', path.join(config.paths().themePath, expressServer.get('activeTheme')));
} else {
expressServer.engine('hbs', hbs.express3({partialsDir: config.paths().adminViews + 'partials'}));
expressServer.engine('hbs', expressServer.get('admin view engine'));
expressServer.set('views', config.paths().adminViews);
}

Expand All @@ -95,9 +86,10 @@ function initViews(req, res, next) {
// ### Activate Theme
// Helper for manageAdminAndTheme
function activateTheme(activeTheme) {
var stackLocation = _.indexOf(expressServer.stack, _.find(expressServer.stack, function (stackItem) {
return stackItem.route === '' && stackItem.handle.name === 'settingEnabled';
}));
var hbsOptions,
stackLocation = _.indexOf(expressServer.stack, _.find(expressServer.stack, function (stackItem) {
return stackItem.route === '' && stackItem.handle.name === 'settingEnabled';
}));

// clear the view cache
expressServer.cache = {};
Expand All @@ -108,6 +100,14 @@ function activateTheme(activeTheme) {
expressServer.stack[stackLocation].handle = middleware.whenEnabled(expressServer.get('activeTheme'), middleware.staticTheme());
}

// set view engine
hbsOptions = { partialsDir: [ config.paths().helperTemplates ] };
if (config.paths().availableThemes[activeTheme].hasOwnProperty('partials')) {
// Check that the theme has a partials directory before trying to use it
hbsOptions.partialsDir.push(path.join(config.paths().themePath, activeTheme, 'partials'));
}
expressServer.set('theme view engine', hbs.express3(hbsOptions));

// Update user error template
errors.updateActiveTheme(activeTheme);
}
Expand Down Expand Up @@ -242,4 +242,4 @@ module.exports = function (server, dbHash) {
// Export middleware functions directly
module.exports.middleware = middleware;
// Expose middleware functions in this file as well
module.exports.middleware.redirectToSignup = redirectToSignup;
module.exports.middleware.redirectToSignup = redirectToSignup;

0 comments on commit 968176c

Please sign in to comment.