mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Plugin API Refactor: Filter and Theme Helpers
issue #769 - Refactor doFilter to allow returning a promise from a filter handler and to also return a promise itself - Move the logic out of the registerThemeHelper calls and into their own methods so we could test them in isolation. - Assign the server to the ghost instance so the initPlugins method can get access to it.
This commit is contained in:
parent
6634c4673d
commit
507174a00b
7 changed files with 718 additions and 546 deletions
|
@ -30,6 +30,8 @@ var config = require('../config'),
|
||||||
instance,
|
instance,
|
||||||
defaults;
|
defaults;
|
||||||
|
|
||||||
|
when.pipeline = require('when/pipeline');
|
||||||
|
|
||||||
// ## Default values
|
// ## Default values
|
||||||
/**
|
/**
|
||||||
* A hash of default values to use instead of 'magic' numbers/strings.
|
* A hash of default values to use instead of 'magic' numbers/strings.
|
||||||
|
@ -182,8 +184,6 @@ Ghost.prototype.init = function () {
|
||||||
return when.join(
|
return when.join(
|
||||||
// Check for or initialise a dbHash.
|
// Check for or initialise a dbHash.
|
||||||
initDbHashAndFirstRun(),
|
initDbHashAndFirstRun(),
|
||||||
// Initialize plugins
|
|
||||||
self.initPlugins(),
|
|
||||||
// Initialize the permissions actions and objects
|
// Initialize the permissions actions and objects
|
||||||
permissions.init()
|
permissions.init()
|
||||||
);
|
);
|
||||||
|
@ -282,6 +282,19 @@ Ghost.prototype.registerThemeHelper = function (name, fn) {
|
||||||
hbs.registerHelper(name, fn);
|
hbs.registerHelper(name, fn);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Register an async handlebars helper for themes
|
||||||
|
Ghost.prototype.registerAsyncThemeHelper = function (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
|
||||||
|
when.resolve(fn(options)).then(function (result) {
|
||||||
|
cb(result);
|
||||||
|
}).otherwise(function (err) {
|
||||||
|
errors.logAndThrowError(err, "registerAsyncThemeHelper: " + name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Register a new filter callback function
|
// Register a new filter callback function
|
||||||
Ghost.prototype.registerFilter = function (name, priority, fn) {
|
Ghost.prototype.registerFilter = function (name, priority, fn) {
|
||||||
// Curry the priority optional parameter to a default of 5
|
// Curry the priority optional parameter to a default of 5
|
||||||
|
@ -312,42 +325,61 @@ Ghost.prototype.unregisterFilter = function (name, priority, fn) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Execute filter functions in priority order
|
// Execute filter functions in priority order
|
||||||
Ghost.prototype.doFilter = function (name, args, callback) {
|
Ghost.prototype.doFilter = function (name, args) {
|
||||||
var callbacks = this.filterCallbacks[name];
|
var callbacks = this.filterCallbacks[name],
|
||||||
|
priorityCallbacks = [];
|
||||||
|
|
||||||
// Bug out early if no callbacks by that name
|
// Bug out early if no callbacks by that name
|
||||||
if (!callbacks) {
|
if (!callbacks) {
|
||||||
return callback(args);
|
return when.resolve(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For each priorityLevel
|
||||||
_.times(defaults.maxPriority + 1, function (priority) {
|
_.times(defaults.maxPriority + 1, function (priority) {
|
||||||
|
// Add a function that runs its priority level callbacks in a pipeline
|
||||||
|
priorityCallbacks.push(function (currentArgs) {
|
||||||
// Bug out if no handlers on this priority
|
// Bug out if no handlers on this priority
|
||||||
if (!_.isArray(callbacks[priority])) {
|
if (!_.isArray(callbacks[priority])) {
|
||||||
return;
|
return when.resolve(currentArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call each handler for this priority level
|
// Call each handler for this priority level, allowing for promises or values
|
||||||
_.each(callbacks[priority], function (filterHandler) {
|
return when.pipeline(callbacks[priority], currentArgs);
|
||||||
try {
|
|
||||||
args = filterHandler(args);
|
|
||||||
} catch (e) {
|
|
||||||
// If a filter causes an error, we log it so that it can be debugged, but do not throw the error
|
|
||||||
errors.logError(e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
callback(args);
|
return when.pipeline(priorityCallbacks, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialise plugins. Will load from config.activePlugins by default
|
// Initialise plugins. Will load from config.activePlugins by default
|
||||||
Ghost.prototype.initPlugins = function (pluginsToLoad) {
|
Ghost.prototype.initPlugins = function (pluginsToLoad) {
|
||||||
pluginsToLoad = pluginsToLoad || models.Settings.activePlugins;
|
pluginsToLoad = pluginsToLoad || JSON.parse(this.settings('activePlugins'));
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
return plugins.init(this, pluginsToLoad).then(function (loadedPlugins) {
|
// If no activePlugins defined in config settings, look in database settings.
|
||||||
|
if (!_.isArray(pluginsToLoad)) {
|
||||||
|
// The value will be resolved in the promise
|
||||||
|
pluginsToLoad = models.Settings.read("activePlugins").then(function (activePluginsSetting) {
|
||||||
|
var settingValue = activePluginsSetting.get('value') || '[]';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We have to parse the value because it's a string
|
||||||
|
settingValue = JSON.parse(settingValue) || [];
|
||||||
|
} catch (e) {
|
||||||
|
return when.reject(new Error("Failed to parse activePlugins setting value: " + e.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve with the array value
|
||||||
|
return when.resolve(settingValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return when(pluginsToLoad).then(function (pluginsToLoadValue) {
|
||||||
|
return plugins.init(self, pluginsToLoad).then(function (loadedPlugins) {
|
||||||
// Extend the loadedPlugins onto the available plugins
|
// Extend the loadedPlugins onto the available plugins
|
||||||
_.extend(self.availablePlugins, loadedPlugins);
|
_.extend(self.availablePlugins, loadedPlugins);
|
||||||
|
});
|
||||||
}, errors.logAndThrowError);
|
}, errors.logAndThrowError);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -445,6 +445,12 @@ when(ghost.init()).then(function () {
|
||||||
loading.resolve();
|
loading.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose the express server on the ghost instance.
|
||||||
|
ghost.server = server;
|
||||||
|
|
||||||
|
// Initialize plugins then start the server
|
||||||
|
ghost.initPlugins().then(function () {
|
||||||
|
|
||||||
// ## Start Ghost App
|
// ## Start Ghost App
|
||||||
if (getSocket()) {
|
if (getSocket()) {
|
||||||
// Make sure the socket is gone before trying to create another
|
// Make sure the socket is gone before trying to create another
|
||||||
|
@ -463,4 +469,6 @@ when(ghost.init()).then(function () {
|
||||||
startGhost
|
startGhost
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
});
|
||||||
}, errors.logAndThrowError);
|
}, errors.logAndThrowError);
|
||||||
|
|
|
@ -41,7 +41,6 @@ frontendControllers = {
|
||||||
}
|
}
|
||||||
|
|
||||||
api.posts.browse(options).then(function (page) {
|
api.posts.browse(options).then(function (page) {
|
||||||
|
|
||||||
var maxPage = page.pages;
|
var maxPage = page.pages;
|
||||||
|
|
||||||
// A bit of a hack for situations with no content.
|
// A bit of a hack for situations with no content.
|
||||||
|
@ -56,7 +55,7 @@ frontendControllers = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the page of posts
|
// Render the page of posts
|
||||||
ghost.doFilter('prePostsRender', page.posts, function (posts) {
|
ghost.doFilter('prePostsRender', page.posts).then(function (posts) {
|
||||||
res.render('index', {posts: posts, pagination: {page: page.page, prev: page.prev, next: page.next, limit: page.limit, total: page.total, pages: page.pages}});
|
res.render('index', {posts: posts, pagination: {page: page.page, prev: page.prev, next: page.next, limit: page.limit, total: page.total, pages: page.pages}});
|
||||||
});
|
});
|
||||||
}).otherwise(function (err) {
|
}).otherwise(function (err) {
|
||||||
|
@ -66,7 +65,7 @@ frontendControllers = {
|
||||||
'single': function (req, res, next) {
|
'single': function (req, res, next) {
|
||||||
api.posts.read({'slug': req.params.slug}).then(function (post) {
|
api.posts.read({'slug': req.params.slug}).then(function (post) {
|
||||||
if (post) {
|
if (post) {
|
||||||
ghost.doFilter('prePostsRender', post, function (post) {
|
ghost.doFilter('prePostsRender', post).then(function (post) {
|
||||||
res.render('post', {post: post});
|
res.render('post', {post: post});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -117,7 +116,7 @@ frontendControllers = {
|
||||||
return res.redirect('/rss/' + maxPage + '/');
|
return res.redirect('/rss/' + maxPage + '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
ghost.doFilter('prePostsRender', page.posts, function (posts) {
|
ghost.doFilter('prePostsRender', page.posts).then(function (posts) {
|
||||||
posts.forEach(function (post) {
|
posts.forEach(function (post) {
|
||||||
var item = {
|
var item = {
|
||||||
title: _.escape(post.title),
|
title: _.escape(post.title),
|
||||||
|
@ -148,7 +147,6 @@ frontendControllers = {
|
||||||
return next(new Error(err));
|
return next(new Error(err));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = frontendControllers;
|
module.exports = frontendControllers;
|
||||||
|
|
|
@ -3,26 +3,23 @@ var _ = require('underscore'),
|
||||||
downsize = require('downsize'),
|
downsize = require('downsize'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
hbs = require('express-hbs'),
|
hbs = require('express-hbs'),
|
||||||
packageInfo = require('../../../package.json'),
|
|
||||||
errors = require('../errorHandling'),
|
errors = require('../errorHandling'),
|
||||||
models = require('../models'),
|
models = require('../models'),
|
||||||
coreHelpers;
|
packageInfo = require('../../../package.json'),
|
||||||
|
version = packageInfo.version,
|
||||||
|
|
||||||
coreHelpers = function (ghost) {
|
|
||||||
var paginationHelper,
|
|
||||||
scriptTemplate = _.template("<script src='/built/scripts/<%= name %>?v=<%= version %>'></script>"),
|
scriptTemplate = _.template("<script src='/built/scripts/<%= name %>?v=<%= version %>'></script>"),
|
||||||
isProduction = process.env.NODE_ENV === 'production',
|
isProduction = process.env.NODE_ENV === 'production',
|
||||||
version = encodeURIComponent(packageInfo.version);
|
coreHelpers = {},
|
||||||
|
registerHelpers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [ description]
|
* [ description]
|
||||||
* @todo ghost core helpers + a way for themes to register them
|
* @todo ghost core helpers + a way for themes to register them
|
||||||
* @param {Object} context date object
|
* @param {Object} context date object
|
||||||
* @param {*} options
|
* @param {*} options
|
||||||
* @return {Object} A Moment time / date object
|
* @return {Object} A Moment time / date object
|
||||||
*/
|
*/
|
||||||
ghost.registerThemeHelper('date', function (context, options) {
|
coreHelpers.date = function (context, options) {
|
||||||
if (!options && context.hasOwnProperty('hash')) {
|
if (!options && context.hasOwnProperty('hash')) {
|
||||||
options = context;
|
options = context;
|
||||||
context = undefined;
|
context = undefined;
|
||||||
|
@ -45,47 +42,47 @@ coreHelpers = function (ghost) {
|
||||||
date = moment(context).format(f);
|
date = moment(context).format(f);
|
||||||
}
|
}
|
||||||
return date;
|
return date;
|
||||||
});
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### URI Encoding helper
|
// ### URI Encoding helper
|
||||||
//
|
//
|
||||||
// *Usage example:*
|
// *Usage example:*
|
||||||
// `{{encode uri}}`
|
// `{{encode uri}}`
|
||||||
//
|
//
|
||||||
// Returns URI encoded string
|
// Returns URI encoded string
|
||||||
//
|
//
|
||||||
ghost.registerThemeHelper('encode', function (context, str) {
|
coreHelpers.encode = function (context, str) {
|
||||||
var uri = context || str;
|
var uri = context || str;
|
||||||
return new hbs.handlebars.SafeString(encodeURIComponent(uri));
|
return new hbs.handlebars.SafeString(encodeURIComponent(uri));
|
||||||
});
|
};
|
||||||
|
|
||||||
// ### Page URL Helper
|
// ### Page URL Helper
|
||||||
//
|
//
|
||||||
// *Usage example:*
|
// *Usage example:*
|
||||||
// `{{pageUrl 2}}`
|
// `{{pageUrl 2}}`
|
||||||
//
|
//
|
||||||
// Returns the URL for the page specified in the current object
|
// Returns the URL for the page specified in the current object
|
||||||
// context.
|
// context.
|
||||||
//
|
//
|
||||||
ghost.registerThemeHelper('pageUrl', function (context, block) {
|
coreHelpers.pageUrl = function (context, block) {
|
||||||
return context === 1 ? '/' : ('/page/' + context + '/');
|
return context === 1 ? '/' : ('/page/' + context + '/');
|
||||||
});
|
};
|
||||||
|
|
||||||
// ### URL helper
|
// ### URL helper
|
||||||
//
|
//
|
||||||
// *Usage example:*
|
// *Usage example:*
|
||||||
// `{{url}}`
|
// `{{url}}`
|
||||||
// `{{url absolute}}`
|
// `{{url absolute}}`
|
||||||
//
|
//
|
||||||
// Returns the URL for the current object context
|
// Returns the URL for the current object context
|
||||||
// i.e. If inside a post context will return post permalink
|
// i.e. If inside a post context will return post permalink
|
||||||
// absolute flag outputs absolute URL, else URL is relative
|
// absolute flag outputs absolute URL, else URL is relative
|
||||||
ghost.registerThemeHelper('url', function (options) {
|
coreHelpers.url = function (options) {
|
||||||
var output = '';
|
var output = '';
|
||||||
|
|
||||||
if (options && options.hash.absolute) {
|
if (options && options.hash.absolute) {
|
||||||
output += ghost.config().url;
|
output += coreHelpers.ghost.config().url;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (models.isPost(this)) {
|
if (models.isPost(this)) {
|
||||||
|
@ -93,32 +90,32 @@ coreHelpers = function (ghost) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
});
|
};
|
||||||
|
|
||||||
// ### Author Helper
|
// ### Author Helper
|
||||||
//
|
//
|
||||||
// *Usage example:*
|
// *Usage example:*
|
||||||
// `{{author}}`
|
// `{{author}}`
|
||||||
//
|
//
|
||||||
// Returns the full name of the author of a given post, or a blank string
|
// Returns the full name of the author of a given post, or a blank string
|
||||||
// if the author could not be determined.
|
// if the author could not be determined.
|
||||||
//
|
//
|
||||||
ghost.registerThemeHelper('author', function (context, options) {
|
coreHelpers.author = function (context, options) {
|
||||||
return this.author ? this.author.name : '';
|
return this.author ? this.author.name : '';
|
||||||
});
|
};
|
||||||
|
|
||||||
// ### Tags Helper
|
// ### Tags Helper
|
||||||
//
|
//
|
||||||
// *Usage example:*
|
// *Usage example:*
|
||||||
// `{{tags}}`
|
// `{{tags}}`
|
||||||
// `{{tags separator=" - "}}`
|
// `{{tags separator=' - '}}`
|
||||||
//
|
//
|
||||||
// Returns a string of the tags on the post.
|
// Returns a string of the tags on the post.
|
||||||
// By default, tags are separated by commas.
|
// By default, tags are separated by commas.
|
||||||
//
|
//
|
||||||
// Note that the standard {{#each tags}} implementation is unaffected by this helper
|
// Note that the standard {{#each tags}} implementation is unaffected by this helper
|
||||||
// and can be used for more complex templates.
|
// and can be used for more complex templates.
|
||||||
ghost.registerThemeHelper('tags', function (options) {
|
coreHelpers.tags = function (options) {
|
||||||
var separator = _.isString(options.hash.separator) ? options.hash.separator : ', ',
|
var separator = _.isString(options.hash.separator) ? options.hash.separator : ', ',
|
||||||
prefix = _.isString(options.hash.prefix) ? options.hash.prefix : '',
|
prefix = _.isString(options.hash.prefix) ? options.hash.prefix : '',
|
||||||
suffix = _.isString(options.hash.suffix) ? options.hash.suffix : '',
|
suffix = _.isString(options.hash.suffix) ? options.hash.suffix : '',
|
||||||
|
@ -130,23 +127,23 @@ coreHelpers = function (ghost) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
});
|
};
|
||||||
|
|
||||||
// ### Content Helper
|
// ### Content Helper
|
||||||
//
|
//
|
||||||
// *Usage example:*
|
// *Usage example:*
|
||||||
// `{{content}}`
|
// `{{content}}`
|
||||||
// `{{content words=20}}`
|
// `{{content words=20}}`
|
||||||
// `{{content characters=256}}`
|
// `{{content characters=256}}`
|
||||||
//
|
//
|
||||||
// Turns content html into a safestring so that the user doesn't have to
|
// Turns content html into a safestring so that the user doesn't have to
|
||||||
// escape it or tell handlebars to leave it alone with a triple-brace.
|
// escape it or tell handlebars to leave it alone with a triple-brace.
|
||||||
//
|
//
|
||||||
// Enables tag-safe truncation of content by characters or words.
|
// Enables tag-safe truncation of content by characters or words.
|
||||||
//
|
//
|
||||||
// **returns** SafeString content html, complete or truncated.
|
// **returns** SafeString content html, complete or truncated.
|
||||||
//
|
//
|
||||||
ghost.registerThemeHelper('content', function (options) {
|
coreHelpers.content = function (options) {
|
||||||
var truncateOptions = (options || {}).hash || {};
|
var truncateOptions = (options || {}).hash || {};
|
||||||
truncateOptions = _.pick(truncateOptions, ['words', 'characters']);
|
truncateOptions = _.pick(truncateOptions, ['words', 'characters']);
|
||||||
|
|
||||||
|
@ -157,23 +154,22 @@ coreHelpers = function (ghost) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new hbs.handlebars.SafeString(this.html);
|
return new hbs.handlebars.SafeString(this.html);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// ### Excerpt Helper
|
||||||
// ### Excerpt Helper
|
//
|
||||||
//
|
// *Usage example:*
|
||||||
// *Usage example:*
|
// `{{excerpt}}`
|
||||||
// `{{excerpt}}`
|
// `{{excerpt words=50}}`
|
||||||
// `{{excerpt words=50}}`
|
// `{{excerpt characters=256}}`
|
||||||
// `{{excerpt characters=256}}`
|
//
|
||||||
//
|
// Attempts to remove all HTML from the string, and then shortens the result according to the provided option.
|
||||||
// Attempts to remove all HTML from the string, and then shortens the result according to the provided option.
|
//
|
||||||
//
|
// Defaults to words=50
|
||||||
// Defaults to words=50
|
//
|
||||||
//
|
// **returns** SafeString truncated, HTML-free content.
|
||||||
// **returns** SafeString truncated, HTML-free content.
|
//
|
||||||
//
|
coreHelpers.excerpt = function (options) {
|
||||||
ghost.registerThemeHelper('excerpt', function (options) {
|
|
||||||
var truncateOptions = (options || {}).hash || {},
|
var truncateOptions = (options || {}).hash || {},
|
||||||
excerpt;
|
excerpt;
|
||||||
|
|
||||||
|
@ -191,22 +187,51 @@ coreHelpers = function (ghost) {
|
||||||
return new hbs.handlebars.SafeString(
|
return new hbs.handlebars.SafeString(
|
||||||
downsize(excerpt, truncateOptions)
|
downsize(excerpt, truncateOptions)
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
// ### Filestorage helper
|
// ### Filestorage helper
|
||||||
//
|
//
|
||||||
// *Usage example:*
|
// *Usage example:*
|
||||||
// `{{fileStorage}}`
|
// `{{fileStorage}}`
|
||||||
//
|
//
|
||||||
// Returns the config value for fileStorage.
|
// Returns the config value for fileStorage.
|
||||||
ghost.registerThemeHelper('fileStorage', function (context, options) {
|
coreHelpers.fileStorage = function (context, options) {
|
||||||
if (ghost.config().hasOwnProperty('fileStorage')) {
|
if (coreHelpers.ghost.config().hasOwnProperty('fileStorage')) {
|
||||||
return ghost.config().fileStorage.toString();
|
return coreHelpers.ghost.config().fileStorage.toString();
|
||||||
}
|
}
|
||||||
return "true";
|
return "true";
|
||||||
|
};
|
||||||
|
|
||||||
|
coreHelpers.ghostScriptTags = function () {
|
||||||
|
var scriptFiles = [];
|
||||||
|
|
||||||
|
if (isProduction) {
|
||||||
|
scriptFiles.push("ghost.min.js");
|
||||||
|
} else {
|
||||||
|
scriptFiles = [
|
||||||
|
'vendor.js',
|
||||||
|
'helpers.js',
|
||||||
|
'templates.js',
|
||||||
|
'models.js',
|
||||||
|
'views.js'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptFiles = _.map(scriptFiles, function (fileName) {
|
||||||
|
return scriptTemplate({
|
||||||
|
name: fileName,
|
||||||
|
version: version
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ghost.registerThemeHelper('body_class', function (options) {
|
return scriptFiles.join('');
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Asynchronous Theme Helpers (Registered with ghost.registerAsyncThemeHelper)
|
||||||
|
*/
|
||||||
|
|
||||||
|
coreHelpers.body_class = function (options) {
|
||||||
var classes = [],
|
var classes = [],
|
||||||
tags = this.post && this.post.tags ? this.post.tags : this.tags || [],
|
tags = this.post && this.post.tags ? this.post.tags : this.tags || [],
|
||||||
page = this.post && this.post.page ? this.post.page : this.page || false;
|
page = this.post && this.post.page ? this.post.page : this.page || false;
|
||||||
|
@ -227,13 +252,13 @@ coreHelpers = function (ghost) {
|
||||||
classes.push('page');
|
classes.push('page');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ghost.doFilter('body_class', classes, function (classes) {
|
return coreHelpers.ghost.doFilter('body_class', classes).then(function (classes) {
|
||||||
var classString = _.reduce(classes, function (memo, item) { return memo + ' ' + item; }, '');
|
var classString = _.reduce(classes, function (memo, item) { return memo + ' ' + item; }, '');
|
||||||
return new hbs.handlebars.SafeString(classString.trim());
|
return new hbs.handlebars.SafeString(classString.trim());
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
ghost.registerThemeHelper('post_class', function (options) {
|
coreHelpers.post_class = function (options) {
|
||||||
var classes = ['post'],
|
var classes = ['post'],
|
||||||
tags = this.post && this.post.tags ? this.post.tags : this.tags || [],
|
tags = this.post && this.post.tags ? this.post.tags : this.tags || [],
|
||||||
featured = this.post && this.post.featured ? this.post.featured : this.featured || false,
|
featured = this.post && this.post.featured ? this.post.featured : this.featured || false,
|
||||||
|
@ -251,101 +276,107 @@ coreHelpers = function (ghost) {
|
||||||
classes.push('page');
|
classes.push('page');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ghost.doFilter('post_class', classes, function (classes) {
|
return coreHelpers.ghost.doFilter('post_class', classes).then(function (classes) {
|
||||||
var classString = _.reduce(classes, function (memo, item) { return memo + ' ' + item; }, '');
|
var classString = _.reduce(classes, function (memo, item) { return memo + ' ' + item; }, '');
|
||||||
return new hbs.handlebars.SafeString(classString.trim());
|
return new hbs.handlebars.SafeString(classString.trim());
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
ghost.registerThemeHelper('ghost_head', function (options) {
|
coreHelpers.ghost_head = function (options) {
|
||||||
var head = [],
|
var head = [],
|
||||||
majorMinor = /^(\d+\.)?(\d+)/,
|
majorMinor = /^(\d+\.)?(\d+)/,
|
||||||
trimmedVersion = this.version.match(majorMinor)[0];
|
trimmedVersion = this.version;
|
||||||
|
|
||||||
|
trimmedVersion = trimmedVersion ? trimmedVersion.match(majorMinor)[0] : '?';
|
||||||
|
|
||||||
head.push('<meta name="generator" content="Ghost ' + trimmedVersion + '" />');
|
head.push('<meta name="generator" content="Ghost ' + trimmedVersion + '" />');
|
||||||
head.push('<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
head.push('<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
||||||
|
|
||||||
return ghost.doFilter('ghost_head', head, function (head) {
|
return coreHelpers.ghost.doFilter('ghost_head', head).then(function (head) {
|
||||||
var headString = _.reduce(head, function (memo, item) { return memo + '\n' + item; }, '');
|
var headString = _.reduce(head, function (memo, item) { return memo + '\n' + item; }, '');
|
||||||
return new hbs.handlebars.SafeString(headString.trim());
|
return new hbs.handlebars.SafeString(headString.trim());
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
ghost.registerThemeHelper('meta_title', function (options) {
|
coreHelpers.ghost_foot = function (options) {
|
||||||
var title, blog;
|
var foot = [];
|
||||||
blog = ghost.blogGlobals();
|
foot.push('<script src="/shared/vendor/jquery/jquery.js"></script>');
|
||||||
|
|
||||||
|
return coreHelpers.ghost.doFilter('ghost_foot', foot).then(function (foot) {
|
||||||
|
var footString = _.reduce(foot, function (memo, item) { return memo + ' ' + item; }, '');
|
||||||
|
return new hbs.handlebars.SafeString(footString.trim());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
coreHelpers.meta_title = function (options) {
|
||||||
|
var title,
|
||||||
|
blog;
|
||||||
if (_.isString(this.path)) {
|
if (_.isString(this.path)) {
|
||||||
if (!this.path || this.path === '/' || this.path === '' || this.path.match(/\/page/)) {
|
if (!this.path || this.path === '/' || this.path === '' || this.path.match(/\/page/)) {
|
||||||
blog = ghost.blogGlobals();
|
blog = coreHelpers.ghost.blogGlobals();
|
||||||
title = blog.title;
|
title = blog.title;
|
||||||
} else {
|
} else {
|
||||||
title = this.post ? this.post.title : '';
|
title = this.post.title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ghost.doFilter('meta_title', title, function (title) {
|
return coreHelpers.ghost.doFilter('meta_title', title).then(function (title) {
|
||||||
|
title = title || "";
|
||||||
return new hbs.handlebars.SafeString(title.trim());
|
return new hbs.handlebars.SafeString(title.trim());
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
|
coreHelpers.meta_description = function (options) {
|
||||||
|
var description,
|
||||||
|
blog;
|
||||||
|
|
||||||
ghost.registerThemeHelper('meta_description', function (options) {
|
|
||||||
var description, blog;
|
|
||||||
blog = ghost.blogGlobals();
|
|
||||||
if (_.isString(this.path)) {
|
if (_.isString(this.path)) {
|
||||||
if (!this.path || this.path === '/' || this.path === '' || this.path.match(/\/page/)) {
|
if (!this.path || this.path === '/' || this.path === '' || this.path.match(/\/page/)) {
|
||||||
blog = ghost.blogGlobals();
|
blog = coreHelpers.ghost.blogGlobals();
|
||||||
description = blog.description;
|
description = blog.description;
|
||||||
} else {
|
} else {
|
||||||
description = '';
|
description = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ghost.doFilter('meta_description', description, function (description) {
|
return coreHelpers.ghost.doFilter('meta_description', description).then(function (description) {
|
||||||
|
description = description || "";
|
||||||
return new hbs.handlebars.SafeString(description.trim());
|
return new hbs.handlebars.SafeString(description.trim());
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
ghost.registerThemeHelper('ghost_foot', function (options) {
|
/**
|
||||||
var foot = [];
|
* Localised string helpers
|
||||||
foot.push('<script src="/shared/vendor/jquery/jquery.js"></script>');
|
|
||||||
|
|
||||||
return ghost.doFilter('ghost_foot', foot, function (foot) {
|
|
||||||
var footString = _.reduce(foot, function (memo, item) { return memo + ' ' + item; }, '');
|
|
||||||
return new hbs.handlebars.SafeString(footString.trim());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* [ description]
|
|
||||||
*
|
*
|
||||||
* @param String key
|
* @param String key
|
||||||
* @param String default translation
|
* @param String default translation
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @return String A correctly internationalised string
|
* @return String A correctly internationalised string
|
||||||
*/
|
*/
|
||||||
ghost.registerThemeHelper('e', function (key, defaultString, options) {
|
coreHelpers.e = function (key, defaultString, options) {
|
||||||
var output;
|
var output;
|
||||||
|
|
||||||
if (ghost.settings('defaultLang') === 'en' && _.isEmpty(options.hash) && !ghost.settings('forceI18n')) {
|
if (coreHelpers.ghost.settings('defaultLang') === 'en' && _.isEmpty(options.hash) && !coreHelpers.ghost.settings('forceI18n')) {
|
||||||
output = defaultString;
|
output = defaultString;
|
||||||
} else {
|
} else {
|
||||||
output = ghost.polyglot().t(key, options.hash);
|
output = coreHelpers.ghost.polyglot().t(key, options.hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
});
|
};
|
||||||
|
|
||||||
ghost.registerThemeHelper('json', function (object, options) {
|
coreHelpers.json = function (object, options) {
|
||||||
return JSON.stringify(object);
|
return JSON.stringify(object);
|
||||||
});
|
};
|
||||||
|
|
||||||
ghost.registerThemeHelper('foreach', function (context, options) {
|
coreHelpers.foreach = function (context, options) {
|
||||||
var fn = options.fn,
|
var fn = options.fn,
|
||||||
inverse = options.inverse,
|
inverse = options.inverse,
|
||||||
i = 0,
|
i = 0,
|
||||||
j = 0,
|
j = 0,
|
||||||
columns = options.hash.columns,
|
columns = options.hash.columns,
|
||||||
key,
|
key,
|
||||||
ret = '',
|
ret = "",
|
||||||
data;
|
data;
|
||||||
|
|
||||||
if (options.data) {
|
if (options.data) {
|
||||||
|
@ -406,42 +437,16 @@ coreHelpers = function (ghost) {
|
||||||
ret = inverse(this);
|
ret = inverse(this);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
});
|
};
|
||||||
|
|
||||||
// A helper for inserting the javascript tags with version hashes
|
// ## Template driven helpers
|
||||||
ghost.registerThemeHelper('ghostScriptTags', function () {
|
// Template driven helpers require that their template is loaded before they can be registered.
|
||||||
var scriptFiles = [];
|
coreHelpers.paginationTemplate = null;
|
||||||
|
|
||||||
if (isProduction) {
|
// ### Pagination Helper
|
||||||
scriptFiles.push("ghost.min.js");
|
// `{{pagination}}`
|
||||||
} else {
|
// Outputs previous and next buttons, along with info about the current page
|
||||||
scriptFiles = [
|
coreHelpers.pagination = function (options) {
|
||||||
'vendor.js',
|
|
||||||
'helpers.js',
|
|
||||||
'templates.js',
|
|
||||||
'models.js',
|
|
||||||
'views.js'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptFiles = _.map(scriptFiles, function (fileName) {
|
|
||||||
return scriptTemplate({
|
|
||||||
name: fileName,
|
|
||||||
version: version
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return scriptFiles.join('');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ## Template driven helpers
|
|
||||||
// Template driven helpers require that their template is loaded before they can be registered.
|
|
||||||
|
|
||||||
// ### Pagination Helper
|
|
||||||
// `{{pagination}}`
|
|
||||||
// Outputs previous and next buttons, along with info about the current page
|
|
||||||
paginationHelper = ghost.loadTemplate('pagination').then(function (templateFn) {
|
|
||||||
ghost.registerThemeHelper('pagination', function (options) {
|
|
||||||
if (!_.isObject(this.pagination) || _.isFunction(this.pagination)) {
|
if (!_.isObject(this.pagination) || _.isFunction(this.pagination)) {
|
||||||
errors.logAndThrowError('pagination data is not an object or is a function');
|
errors.logAndThrowError('pagination data is not an object or is a function');
|
||||||
return;
|
return;
|
||||||
|
@ -461,20 +466,73 @@ coreHelpers = function (ghost) {
|
||||||
errors.logAndThrowError('Invalid value, check page, pages, limit and total are numbers');
|
errors.logAndThrowError('Invalid value, check page, pages, limit and total are numbers');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return new hbs.handlebars.SafeString(templateFn(this.pagination));
|
return new hbs.handlebars.SafeString(coreHelpers.paginationTemplate(this.pagination));
|
||||||
});
|
};
|
||||||
});
|
|
||||||
|
|
||||||
ghost.registerThemeHelper('helperMissing', function (arg) {
|
coreHelpers.helperMissing = function (arg) {
|
||||||
if (arguments.length === 2) {
|
if (arguments.length === 2) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
errors.logError("Missing helper: '" + arg + "'");
|
errors.logError('Missing helper: "' + arg + '"');
|
||||||
|
};
|
||||||
|
|
||||||
|
registerHelpers = function (ghost) {
|
||||||
|
var paginationHelper;
|
||||||
|
|
||||||
|
// Expose this so our helpers can use it in their code.
|
||||||
|
coreHelpers.ghost = ghost;
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('date', coreHelpers.date);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('encode', coreHelpers.encode);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('pageUrl', coreHelpers.pageUrl);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('url', coreHelpers.url);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('author', coreHelpers.author);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('tags', coreHelpers.tags);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('content', coreHelpers.content);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('excerpt', coreHelpers.excerpt);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('fileStorage', coreHelpers.fileStorage);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('ghostScriptTags', coreHelpers.ghostScriptTags);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('e', coreHelpers.e);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('json', coreHelpers.json);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('foreach', coreHelpers.foreach);
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('helperMissing', coreHelpers.helperMissing);
|
||||||
|
|
||||||
|
ghost.registerAsyncThemeHelper('body_class', coreHelpers.body_class);
|
||||||
|
|
||||||
|
ghost.registerAsyncThemeHelper('post_class', coreHelpers.post_class);
|
||||||
|
|
||||||
|
ghost.registerAsyncThemeHelper('meta_title', coreHelpers.meta_title);
|
||||||
|
|
||||||
|
ghost.registerAsyncThemeHelper('meta_description', coreHelpers.meta_description);
|
||||||
|
|
||||||
|
ghost.registerAsyncThemeHelper('ghost_head', coreHelpers.ghost_head);
|
||||||
|
|
||||||
|
ghost.registerAsyncThemeHelper('ghost_foot', coreHelpers.ghost_foot);
|
||||||
|
|
||||||
|
paginationHelper = ghost.loadTemplate('pagination').then(function (templateFn) {
|
||||||
|
coreHelpers.paginationTemplate = templateFn;
|
||||||
|
|
||||||
|
ghost.registerThemeHelper('pagination', coreHelpers.pagination);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return once the template-driven helpers have loaded
|
// Return once the template-driven helpers have loaded
|
||||||
return when.join(
|
return when.join(
|
||||||
paginationHelper
|
paginationHelper
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.loadCoreHelpers = coreHelpers;
|
module.exports = coreHelpers;
|
||||||
|
module.exports.loadCoreHelpers = registerHelpers;
|
||||||
|
|
|
@ -94,7 +94,7 @@ describe("Ghost API", function () {
|
||||||
ghost.registerFilter(filterName, 2, testFilterHandler2);
|
ghost.registerFilter(filterName, 2, testFilterHandler2);
|
||||||
ghost.registerFilter(filterName, 9, testFilterHandler3);
|
ghost.registerFilter(filterName, 9, testFilterHandler3);
|
||||||
|
|
||||||
ghost.doFilter(filterName, null, function () {
|
ghost.doFilter(filterName, null).then(function () {
|
||||||
|
|
||||||
testFilterHandler1.calledBefore(testFilterHandler2).should.equal(true);
|
testFilterHandler1.calledBefore(testFilterHandler2).should.equal(true);
|
||||||
testFilterHandler2.calledBefore(testFilterHandler3).should.equal(true);
|
testFilterHandler2.calledBefore(testFilterHandler3).should.equal(true);
|
||||||
|
@ -105,6 +105,51 @@ describe("Ghost API", function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("executes filters that return a promise", function (done) {
|
||||||
|
var filterName = 'testprioritypromise',
|
||||||
|
testFilterHandler1 = sinon.spy(function (args) {
|
||||||
|
return when.promise(function (resolve) {
|
||||||
|
process.nextTick(function () {
|
||||||
|
args.filter1 = true;
|
||||||
|
|
||||||
|
resolve(args);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
testFilterHandler2 = sinon.spy(function (args) {
|
||||||
|
args.filter2 = true;
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}),
|
||||||
|
testFilterHandler3 = sinon.spy(function (args) {
|
||||||
|
return when.promise(function (resolve) {
|
||||||
|
process.nextTick(function () {
|
||||||
|
args.filter3 = true;
|
||||||
|
|
||||||
|
resolve(args);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ghost.registerFilter(filterName, 0, testFilterHandler1);
|
||||||
|
ghost.registerFilter(filterName, 2, testFilterHandler2);
|
||||||
|
ghost.registerFilter(filterName, 9, testFilterHandler3);
|
||||||
|
|
||||||
|
ghost.doFilter(filterName, { test: true }).then(function (newArgs) {
|
||||||
|
|
||||||
|
testFilterHandler1.calledBefore(testFilterHandler2).should.equal(true);
|
||||||
|
testFilterHandler2.calledBefore(testFilterHandler3).should.equal(true);
|
||||||
|
|
||||||
|
testFilterHandler3.called.should.equal(true);
|
||||||
|
|
||||||
|
newArgs.filter1.should.equal(true);
|
||||||
|
newArgs.filter2.should.equal(true);
|
||||||
|
newArgs.filter3.should.equal(true);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("can compile a template", function (done) {
|
it("can compile a template", function (done) {
|
||||||
var template = path.join(process.cwd(), testTemplatePath, 'test.hbs');
|
var template = path.join(process.cwd(), testTemplatePath, 'test.hbs');
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,13 @@ var testUtils = require('./testUtils'),
|
||||||
sinon = require('sinon'),
|
sinon = require('sinon'),
|
||||||
_ = require("underscore"),
|
_ = require("underscore"),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
|
knex = require('../../server/models/base').Knex,
|
||||||
errors = require('../../server/errorHandling'),
|
errors = require('../../server/errorHandling'),
|
||||||
|
|
||||||
// Stuff we are testing
|
// Stuff we are testing
|
||||||
plugins = require('../../server/plugins'),
|
plugins = require('../../server/plugins'),
|
||||||
GhostPlugin = plugins.GhostPlugin,
|
GhostPlugin = plugins.GhostPlugin,
|
||||||
loader = require('../../server/plugins/loader');
|
loader = require('../../server/plugins/loader');
|
||||||
|
|
||||||
describe('Plugins', function () {
|
describe('Plugins', function () {
|
||||||
|
|
||||||
var sandbox;
|
var sandbox;
|
||||||
|
|
|
@ -29,7 +29,7 @@ describe('Core Helpers', function () {
|
||||||
|
|
||||||
it('can render content', function () {
|
it('can render content', function () {
|
||||||
var html = "Hello World",
|
var html = "Hello World",
|
||||||
rendered = handlebars.helpers.content.call({html: html});
|
rendered = helpers.content.call({html: html});
|
||||||
|
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal(html);
|
rendered.string.should.equal(html);
|
||||||
|
@ -38,7 +38,7 @@ describe('Core Helpers', function () {
|
||||||
it('can truncate html by word', function () {
|
it('can truncate html by word', function () {
|
||||||
var html = "<p>Hello <strong>World! It's me!</strong></p>",
|
var html = "<p>Hello <strong>World! It's me!</strong></p>",
|
||||||
rendered = (
|
rendered = (
|
||||||
handlebars.helpers.content
|
helpers.content
|
||||||
.call(
|
.call(
|
||||||
{html: html},
|
{html: html},
|
||||||
{"hash":{"words": 2}}
|
{"hash":{"words": 2}}
|
||||||
|
@ -52,7 +52,7 @@ describe('Core Helpers', function () {
|
||||||
it('can truncate html by character', function () {
|
it('can truncate html by character', function () {
|
||||||
var html = "<p>Hello <strong>World! It's me!</strong></p>",
|
var html = "<p>Hello <strong>World! It's me!</strong></p>",
|
||||||
rendered = (
|
rendered = (
|
||||||
handlebars.helpers.content
|
helpers.content
|
||||||
.call(
|
.call(
|
||||||
{html: html},
|
{html: html},
|
||||||
{"hash":{"characters": 8}}
|
{"hash":{"characters": 8}}
|
||||||
|
@ -72,14 +72,14 @@ describe('Core Helpers', function () {
|
||||||
|
|
||||||
it("Returns the full name of the author from the context",function() {
|
it("Returns the full name of the author from the context",function() {
|
||||||
var data = {"author":{"name":"abc123"}},
|
var data = {"author":{"name":"abc123"}},
|
||||||
result = handlebars.helpers.author.call(data);
|
result = helpers.author.call(data);
|
||||||
|
|
||||||
String(result).should.equal("abc123");
|
String(result).should.equal("abc123");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Returns a blank string where author data is missing",function() {
|
it("Returns a blank string where author data is missing",function() {
|
||||||
var data = {"author": null},
|
var data = {"author": null},
|
||||||
result = handlebars.helpers.author.call(data);
|
result = helpers.author.call(data);
|
||||||
|
|
||||||
String(result).should.equal("");
|
String(result).should.equal("");
|
||||||
});
|
});
|
||||||
|
@ -110,7 +110,7 @@ describe('Core Helpers', function () {
|
||||||
|
|
||||||
it('can render excerpt', function () {
|
it('can render excerpt', function () {
|
||||||
var html = "Hello World",
|
var html = "Hello World",
|
||||||
rendered = handlebars.helpers.excerpt.call({html: html});
|
rendered = helpers.excerpt.call({html: html});
|
||||||
|
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal(html);
|
rendered.string.should.equal(html);
|
||||||
|
@ -123,7 +123,7 @@ describe('Core Helpers', function () {
|
||||||
+ "< test > those<<< test >>> who mistake it <for> binary.",
|
+ "< test > those<<< test >>> who mistake it <for> binary.",
|
||||||
expected = "There are 10 types of people in the world: those who understand trinary, those who don't "
|
expected = "There are 10 types of people in the world: those who understand trinary, those who don't "
|
||||||
+ "and those>> who mistake it <for> binary.",
|
+ "and those>> who mistake it <for> binary.",
|
||||||
rendered = handlebars.helpers.excerpt.call({html: html});
|
rendered = helpers.excerpt.call({html: html});
|
||||||
|
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal(expected);
|
rendered.string.should.equal(expected);
|
||||||
|
@ -134,7 +134,7 @@ describe('Core Helpers', function () {
|
||||||
var html = "<p>Hello <strong>World! It's me!</strong></p>",
|
var html = "<p>Hello <strong>World! It's me!</strong></p>",
|
||||||
expected = "Hello World",
|
expected = "Hello World",
|
||||||
rendered = (
|
rendered = (
|
||||||
handlebars.helpers.excerpt.call(
|
helpers.excerpt.call(
|
||||||
{html: html},
|
{html: html},
|
||||||
{"hash": {"words": 2}}
|
{"hash": {"words": 2}}
|
||||||
)
|
)
|
||||||
|
@ -148,7 +148,7 @@ describe('Core Helpers', function () {
|
||||||
var html = "<p>Hello <strong>World! It's me!</strong></p>",
|
var html = "<p>Hello <strong>World! It's me!</strong></p>",
|
||||||
expected = "Hello Wo",
|
expected = "Hello Wo",
|
||||||
rendered = (
|
rendered = (
|
||||||
handlebars.helpers.excerpt.call(
|
helpers.excerpt.call(
|
||||||
{html: html},
|
{html: html},
|
||||||
{"hash": {"characters": 8}}
|
{"hash": {"characters": 8}}
|
||||||
)
|
)
|
||||||
|
@ -164,35 +164,48 @@ describe('Core Helpers', function () {
|
||||||
should.exist(handlebars.helpers.body_class);
|
should.exist(handlebars.helpers.body_class);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can render class string', function () {
|
it('can render class string', function (done) {
|
||||||
var rendered = handlebars.helpers.body_class.call({});
|
helpers.body_class.call({}).then(function (rendered) {
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
|
|
||||||
rendered.string.should.equal('home-template');
|
rendered.string.should.equal('home-template');
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can render class string for context', function () {
|
it('can render class string for context', function (done) {
|
||||||
var rendered1 = handlebars.helpers.body_class.call({path: '/'}),
|
when.all([
|
||||||
rendered2 = handlebars.helpers.body_class.call({path: '/a-post-title'}),
|
helpers.body_class.call({path: '/'}),
|
||||||
rendered3 = handlebars.helpers.body_class.call({path: '/page/4'});
|
helpers.body_class.call({path: '/a-post-title'}),
|
||||||
|
helpers.body_class.call({path: '/page/4'})
|
||||||
|
]).then(function (rendered) {
|
||||||
|
rendered.length.should.equal(3);
|
||||||
|
|
||||||
should.exist(rendered1);
|
should.exist(rendered[0]);
|
||||||
should.exist(rendered2);
|
should.exist(rendered[1]);
|
||||||
should.exist(rendered3);
|
should.exist(rendered[2]);
|
||||||
|
|
||||||
rendered1.string.should.equal('home-template');
|
rendered[0].string.should.equal('home-template');
|
||||||
rendered2.string.should.equal('post-template');
|
rendered[1].string.should.equal('post-template');
|
||||||
rendered3.string.should.equal('archive-template');
|
rendered[2].string.should.equal('archive-template');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can render class for static page', function () {
|
it('can render class for static page', function (done) {
|
||||||
var rendered = handlebars.helpers.body_class.call(
|
helpers.body_class.call({
|
||||||
{post: {page: true}},
|
path: '/',
|
||||||
{path: '/'}
|
post: {
|
||||||
);
|
page: true
|
||||||
|
}
|
||||||
|
}).then(function (rendered) {
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal('home-template page');
|
rendered.string.should.equal('home-template page');
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -201,19 +214,23 @@ describe('Core Helpers', function () {
|
||||||
should.exist(handlebars.helpers.post_class);
|
should.exist(handlebars.helpers.post_class);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can render class string', function () {
|
it('can render class string', function (done) {
|
||||||
var rendered = handlebars.helpers.post_class.call({});
|
helpers.post_class.call({}).then(function (rendered) {
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
|
|
||||||
rendered.string.should.equal('post');
|
rendered.string.should.equal('post');
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can render featured class', function () {
|
it('can render featured class', function (done) {
|
||||||
var post = { featured: true },
|
var post = { featured: true };
|
||||||
rendered = handlebars.helpers.post_class.call(post);
|
|
||||||
|
|
||||||
|
helpers.post_class.call(post).then(function (rendered) {
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal('post featured');
|
rendered.string.should.equal('post featured');
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -222,28 +239,36 @@ describe('Core Helpers', function () {
|
||||||
should.exist(handlebars.helpers.ghost_head);
|
should.exist(handlebars.helpers.ghost_head);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns meta tag string', function () {
|
it('returns meta tag string', function (done) {
|
||||||
var rendered = handlebars.helpers.ghost_head.call({version: "0.3.0"});
|
helpers.ghost_head.call({version: "0.3.0"}).then(function (rendered) {
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns meta tag string even if version is invalid', function () {
|
it('returns meta tag string even if version is invalid', function () {
|
||||||
var rendered = handlebars.helpers.ghost_head.call({version: "0.9"});
|
var rendered = helpers.ghost_head.call({version: "0.9"}).then(function (rendered) {
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.9" />\n<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
rendered.string.should.equal('<meta name="generator" content="Ghost 0.9" />\n<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('ghost_foot Helper', function () {
|
describe('ghost_foot Helper', function () {
|
||||||
it('has loaded ghost_foot helper', function () {
|
it('has loaded ghost_foot helper', function () {
|
||||||
should.exist(handlebars.helpers.ghost_foot);
|
should.exist(handlebars.helpers.ghost_foot);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns meta tag string', function () {
|
it('returns meta tag string', function (done) {
|
||||||
var rendered = handlebars.helpers.ghost_foot.call();
|
helpers.ghost_foot.call().then(function (rendered) {
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal('<script src="/shared/vendor/jquery/jquery.js"></script>');
|
rendered.string.should.equal('<script src="/shared/vendor/jquery/jquery.js"></script>');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -253,7 +278,7 @@ describe('Core Helpers', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a the slug with a prefix slash if the context is a post', function () {
|
it('should return a the slug with a prefix slash if the context is a post', function () {
|
||||||
var rendered = handlebars.helpers.url.call({html: 'content', markdown: "ff", title: "title", slug: "slug"});
|
var rendered = helpers.url.call({html: 'content', markdown: "ff", title: "title", slug: "slug"});
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.should.equal('/slug/');
|
rendered.should.equal('/slug/');
|
||||||
});
|
});
|
||||||
|
@ -263,7 +288,7 @@ describe('Core Helpers', function () {
|
||||||
return { url: 'http://testurl.com' };
|
return { url: 'http://testurl.com' };
|
||||||
}),
|
}),
|
||||||
|
|
||||||
rendered = handlebars.helpers.url.call(
|
rendered = helpers.url.call(
|
||||||
{html: 'content', markdown: "ff", title: "title", slug: "slug"},
|
{html: 'content', markdown: "ff", title: "title", slug: "slug"},
|
||||||
{hash: { absolute: 'true'}}
|
{hash: { absolute: 'true'}}
|
||||||
);
|
);
|
||||||
|
@ -275,10 +300,10 @@ describe('Core Helpers', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return empty string if not a post', function () {
|
it('should return empty string if not a post', function () {
|
||||||
handlebars.helpers.url.call({markdown: "ff", title: "title", slug: "slug"}).should.equal('');
|
helpers.url.call({markdown: "ff", title: "title", slug: "slug"}).should.equal('');
|
||||||
handlebars.helpers.url.call({html: 'content', title: "title", slug: "slug"}).should.equal('');
|
helpers.url.call({html: 'content', title: "title", slug: "slug"}).should.equal('');
|
||||||
handlebars.helpers.url.call({html: 'content', markdown: "ff", slug: "slug"}).should.equal('');
|
helpers.url.call({html: 'content', markdown: "ff", slug: "slug"}).should.equal('');
|
||||||
handlebars.helpers.url.call({html: 'content', markdown: "ff", title: "title"}).should.equal('');
|
helpers.url.call({html: 'content', markdown: "ff", title: "title"}).should.equal('');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -288,9 +313,9 @@ describe('Core Helpers', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return a valid url', function () {
|
it('can return a valid url', function () {
|
||||||
handlebars.helpers.pageUrl(1).should.equal('/');
|
helpers.pageUrl(1).should.equal('/');
|
||||||
handlebars.helpers.pageUrl(2).should.equal('/page/2/');
|
helpers.pageUrl(2).should.equal('/page/2/');
|
||||||
handlebars.helpers.pageUrl(50).should.equal('/page/50/');
|
helpers.pageUrl(50).should.equal('/page/50/');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -307,7 +332,7 @@ describe('Core Helpers', function () {
|
||||||
it('can render single page with no pagination necessary', function (done) {
|
it('can render single page with no pagination necessary', function (done) {
|
||||||
var rendered;
|
var rendered;
|
||||||
helpers.loadCoreHelpers(ghost).then(function () {
|
helpers.loadCoreHelpers(ghost).then(function () {
|
||||||
rendered = handlebars.helpers.pagination.call({pagination: {page: 1, prev: undefined, next: undefined, limit: 15, total: 8, pages: 1}});
|
rendered = helpers.pagination.call({pagination: {page: 1, prev: undefined, next: undefined, limit: 15, total: 8, pages: 1}});
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
// strip out carriage returns and compare.
|
// strip out carriage returns and compare.
|
||||||
rendered.string.should.match(paginationRegex);
|
rendered.string.should.match(paginationRegex);
|
||||||
|
@ -322,7 +347,7 @@ describe('Core Helpers', function () {
|
||||||
it('can render first page of many with older posts link', function (done) {
|
it('can render first page of many with older posts link', function (done) {
|
||||||
var rendered;
|
var rendered;
|
||||||
helpers.loadCoreHelpers(ghost).then(function () {
|
helpers.loadCoreHelpers(ghost).then(function () {
|
||||||
rendered = handlebars.helpers.pagination.call({pagination: {page: 1, prev: undefined, next: 2, limit: 15, total: 8, pages: 3}});
|
rendered = helpers.pagination.call({pagination: {page: 1, prev: undefined, next: 2, limit: 15, total: 8, pages: 3}});
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
|
|
||||||
rendered.string.should.match(paginationRegex);
|
rendered.string.should.match(paginationRegex);
|
||||||
|
@ -337,7 +362,7 @@ describe('Core Helpers', function () {
|
||||||
it('can render middle pages of many with older and newer posts link', function (done) {
|
it('can render middle pages of many with older and newer posts link', function (done) {
|
||||||
var rendered;
|
var rendered;
|
||||||
helpers.loadCoreHelpers(ghost).then(function () {
|
helpers.loadCoreHelpers(ghost).then(function () {
|
||||||
rendered = handlebars.helpers.pagination.call({pagination: {page: 2, prev: 1, next: 3, limit: 15, total: 8, pages: 3}});
|
rendered = helpers.pagination.call({pagination: {page: 2, prev: 1, next: 3, limit: 15, total: 8, pages: 3}});
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
|
|
||||||
rendered.string.should.match(paginationRegex);
|
rendered.string.should.match(paginationRegex);
|
||||||
|
@ -353,7 +378,7 @@ describe('Core Helpers', function () {
|
||||||
it('can render last page of many with newer posts link', function (done) {
|
it('can render last page of many with newer posts link', function (done) {
|
||||||
var rendered;
|
var rendered;
|
||||||
helpers.loadCoreHelpers(ghost).then(function () {
|
helpers.loadCoreHelpers(ghost).then(function () {
|
||||||
rendered = handlebars.helpers.pagination.call({pagination: {page: 3, prev: 2, next: undefined, limit: 15, total: 8, pages: 3}});
|
rendered = helpers.pagination.call({pagination: {page: 3, prev: 2, next: undefined, limit: 15, total: 8, pages: 3}});
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
|
|
||||||
rendered.string.should.match(paginationRegex);
|
rendered.string.should.match(paginationRegex);
|
||||||
|
@ -370,7 +395,7 @@ describe('Core Helpers', function () {
|
||||||
helpers.loadCoreHelpers(ghost).then(function () {
|
helpers.loadCoreHelpers(ghost).then(function () {
|
||||||
var runErrorTest = function (data) {
|
var runErrorTest = function (data) {
|
||||||
return function () {
|
return function () {
|
||||||
handlebars.helpers.pagination.call(data);
|
helpers.pagination.call(data);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -485,43 +510,49 @@ describe('Core Helpers', function () {
|
||||||
should.exist(handlebars.helpers.meta_title);
|
should.exist(handlebars.helpers.meta_title);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return blog title', function () {
|
it('can return blog title', function (done) {
|
||||||
var rendered = handlebars.helpers.meta_title.call({path: '/'});
|
helpers.meta_title.call({path: '/'}).then(function (rendered) {
|
||||||
|
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
String(rendered).should.equal('Ghost');
|
rendered.string.should.equal('Ghost');
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return title of a post', function () {
|
it('can return title of a post', function (done) {
|
||||||
var rendered = handlebars.helpers.meta_title.call(
|
var post = {path: '/nice-post', post: {title: 'Post Title'}};
|
||||||
{path: '/nice-post', post: {title: 'Post Title'}}
|
helpers.meta_title.call(post).then(function (rendered) {
|
||||||
);
|
|
||||||
|
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
String(rendered).should.equal('Post Title');
|
rendered.string.should.equal('Post Title');
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("meta_description helper", function () {
|
describe("meta_description helper", function (done) {
|
||||||
|
|
||||||
it('has loaded meta_description helper', function () {
|
it('has loaded meta_description helper', function () {
|
||||||
should.exist(handlebars.helpers.meta_description);
|
should.exist(handlebars.helpers.meta_description);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return blog description', function () {
|
it('can return blog description', function () {
|
||||||
var rendered = handlebars.helpers.meta_description.call({path: '/'});
|
helpers.meta_description.call({path: '/'}).then(function (rendered) {
|
||||||
|
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
String(rendered).should.equal('Just a blogging platform.');
|
rendered.string.should.equal('Just a blogging platform.');
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return empty description on post', function () {
|
it('can return empty description on post', function (done) {
|
||||||
var rendered = handlebars.helpers.meta_description.call(
|
var post = {path: '/nice-post', post: {title: 'Post Title'}};
|
||||||
{path: '/nice-post', post: {title: 'Post Title'}}
|
helpers.meta_description.call(post).then(function (rendered) {
|
||||||
);
|
|
||||||
|
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
String(rendered).should.equal('');
|
rendered.string.should.equal('');
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue