From 0a562e12402f6404b420ecf30dc10093db8d548b Mon Sep 17 00:00:00 2001 From: cliftonc Date: Fri, 13 Apr 2012 17:26:36 +0100 Subject: [PATCH] Refactored helpers to clean up core library --- app.js | 122 ++++++----- lib/calipso.js | 61 +++--- lib/core/Helpers.js | 375 +++++++++++++++++--------------- lib/core/Themes.js | 6 +- modules/core/content/content.js | 8 +- test/lib.calipso.js | 7 - 6 files changed, 298 insertions(+), 281 deletions(-) diff --git a/app.js b/app.js index f2059c4d5..d1a66e2d5 100644 --- a/app.js +++ b/app.js @@ -49,64 +49,76 @@ function bootApplication(next) { // Load configuration var Config = calipso.config; //require(path + "/lib/core/Config").Config; app.config = new Config(); - app.config.init(); - - app.use(express.bodyParser()); - app.use(express.methodOverride()); - app.use(express.cookieParser()); - app.use(express.responseTime()); - - // Create dummy session middleware - tag it so we can later replace - var temporarySession = express.session({ secret: "keyboard cat" }); - temporarySession.tag = "session"; - app.use(temporarySession); - - // Default Theme - calipso.defaultTheme = app.config.get('themes:default'); - - // Create holders for theme dependent middleware - // These are here because they need to be in the connect stack before the calipso router - // THese helpers are re-used when theme switching. - app.mwHelpers = {}; - - // Load placeholder, replaced later - if(app.config.get('libraries:stylus:enabled')) { - app.mwHelpers.stylusMiddleware = function (themePath) { - var mw = stylus.middleware({ - src: themePath + '/stylus', - dest: themePath + '/public', - debug: false, - compile: function (str, path) { // optional, but recommended - return stylus(str) - .set('filename', path) - .set('warn', app.config.get('libraries:stylus:warn')) - .set('compress', app.config.get('libraries:stylus:compress')); - } - }); - mw.tag = 'theme.stylus'; + app.config.init(function(err) { + + if(err) return console.error(err.message); + + // Default Theme + calipso.defaultTheme = app.config.get('themes:default'); + + app.use(express.bodyParser()); + app.use(express.methodOverride()); + app.use(express.cookieParser()); + app.use(express.responseTime()); + + // Create dummy session middleware - tag it so we can later replace + var temporarySession = app.config.get('installed') ? {} : express.session({ secret: "installing calipso is great fun" }); + temporarySession.tag = "session"; + app.use(temporarySession); + + // Create holders for theme dependent middleware + // These are here because they need to be in the connect stack before the calipso router + // THese helpers are re-used when theme switching. + app.mwHelpers = {}; + + // Load placeholder, replaced later + if(app.config.get('libraries:stylus:enabled')) { + app.mwHelpers.stylusMiddleware = function (themePath) { + var mw = stylus.middleware({ + src: themePath + '/stylus', + dest: themePath + '/public', + debug: false, + compile: function (str, path) { // optional, but recommended + return stylus(str) + .set('filename', path) + .set('warn', app.config.get('libraries:stylus:warn')) + .set('compress', app.config.get('libraries:stylus:compress')); + } + }); + mw.tag = 'theme.stylus'; + return mw; + }; + app.use(app.mwHelpers.stylusMiddleware('')); + } + // Static + app.mwHelpers.staticMiddleware = function (themePath) { + var mw = express["static"](themePath + '/public', {maxAge: 86400000}); + mw.tag = 'theme.static'; return mw; }; - app.use(app.mwHelpers.stylusMiddleware('')); - } - // Static - app.mwHelpers.staticMiddleware = function (themePath) { - var mw = express["static"](themePath + '/public', {maxAge: 86400000}); - mw.tag = 'theme.static'; - return mw; - }; - // Load placeholder, replaced later - app.use(app.mwHelpers.staticMiddleware('')); - - // Core static paths - app.use(express["static"](path + '/media', {maxAge: 86400000})); - app.use(express["static"](path + '/lib/client/js', {maxAge: 86400000})); - - // Translation - after static, set to add mode if appropriate - app.use(translate.translate(app.config.get('i18n:language'), app.config.get('i18n:languages'), app.config.get('i18n:additive'))); - - // Core calipso router - app.use(calipso.calipsoRouter(app, function() { next(app) })); + // Load placeholder, replaced later + app.use(app.mwHelpers.staticMiddleware('')); + + // Core static paths + app.use(express["static"](path + '/media', {maxAge: 86400000})); + app.use(express["static"](path + '/lib/client/js', {maxAge: 86400000})); + + // Translation - after static, set to add mode if appropriate + app.use(translate.translate(app.config.get('i18n:language'), app.config.get('i18n:languages'), app.config.get('i18n:additive'))); + + // Core calipso router + calipso.init(app, function() { + + // Add the calipso mw + app.use(calipso.routingFn()); + // return our app refrerence + next(app); + + }) + + }); + } /** diff --git a/lib/calipso.js b/lib/calipso.js index 4baa54d51..b5a7d7447 100644 --- a/lib/calipso.js +++ b/lib/calipso.js @@ -37,30 +37,22 @@ var rootpath = process.cwd() + '/', // Core object var calipso = module.exports = { - // View Helpers - getDynamicHelpers: function(req, res) { - req.helpers = {}; - for(var helper in this.helpers) { - req.helpers[helper] = this.helpers[helper](req, res, this); - } - }, - + // Router and initialisation + routingFn: routingFn, + init: init, + // Configuration exposed reloadConfig: reloadConfig, // Core objects - themes, data, modules theme: {}, data: {}, - modules: {}, - - // Express Router - calipsoRouter: router + modules: {} }; // Load libraries in the core folder loadCore(calipso); - function loadCore(calipso) { fs.readdirSync(rootpath + 'lib/core').forEach(function(library){ @@ -70,41 +62,49 @@ function loadCore(calipso) { }); } - module.exports.loaded = true; -/** - * Core router and initialisation function. - * - * Returns a connect middleware function that manages the roucting - * of requests to modules. +/** + * Calipso initialisation */ -function router(app, initCallback) { - +function init(app, initCallback) { + calipso.app = app; - // Load the calipso package.json into about + // Load the calipso package.json into app.about calipso.module.loadAbout(app, rootpath, 'package.json'); calipso.config = app.config; - // Configure the cache - calipso.cacheService = calipso.cache.Cache({ttl:calipso.config.get('performance:cache:ttl')}); - // Store the callback function for later calipso.initCallback = function() { initCallback(); }; + // Configure the cache + calipso.cacheService = calipso.cache.Cache({ttl:calipso.config.get('performance:cache:ttl')}); + // Create our calipso event emitter calipso.e = new calipso.event.CalipsoEventEmitter(); // Load configuration initialiseCalipso(); +} + +/** + * Core router function. + * + * Returns a connect middleware function that manages the roucting + * of requests to modules. + * + * Expects Calipso to be initialised. + */ +function routingFn() { + // Return the function that manages the routing // Ok being non-synchro - return function(req,res,next) { + return function(req, res, next) { // Default menus and blocks for each request // More of these can be added in modules, these are jsut the defaults @@ -120,12 +120,13 @@ function router(app, initCallback) { res.client = new Client(); // Initialise helpers - first pass - calipso.getDynamicHelpers(req, res); + calipso.helpers.getDynamicHelpers(req, res, calipso); // Route the modules calipso.module.eventRouteModules(req, res, next); }; + } /** @@ -206,11 +207,11 @@ function loadThemes(next) { var themeBasePath = calipso.config.get('server:themePath'); - calipso.lib.fs.readdirSync(calipso.lib.path.join(calipso.app.path,themeBasePath)).forEach(function(folder){ + calipso.lib.fs.readdirSync(calipso.lib.path.join(rootpath,themeBasePath)).forEach(function(folder){ if(folder != "README" && folder != '.DS_Store') { - var themes = calipso.lib.fs.readdirSync(calipso.lib.path.join(calipso.app.path,themeBasePath,folder)); + var themes = calipso.lib.fs.readdirSync(calipso.lib.path.join(rootpath,themeBasePath,folder)); // First scan for legacy themes var legacyTheme = false; @@ -226,7 +227,7 @@ function loadThemes(next) { themes.forEach(function(theme) { if(theme != "README" && theme != '.DS_Store') - var themePath = calipso.lib.path.join(calipso.app.path,themeBasePath,folder,theme); + var themePath = calipso.lib.path.join(rootpath,themeBasePath,folder,theme); // Create the theme object calipso.availableThemes[theme] = { name: theme, diff --git a/lib/core/Helpers.js b/lib/core/Helpers.js index 916f7226f..bb285c9f1 100644 --- a/lib/core/Helpers.js +++ b/lib/core/Helpers.js @@ -30,217 +30,234 @@ function stripUrlToConvert(url) { */ exports = module.exports = { - /** - * Request shortcut - */ - request: function(req, res, calipso){ - return req; - }, - - /** - * Config shortcut - */ - config: function(req, res, calipso){ - return calipso.config; - }, - - /** - * Translation shortcut - */ - t: function(req, res, calipso){ - return req.t; - }, - - /** - * User shortcut - */ - user: function(req, res, calipso){ - return req.session && req.session.user || { username: '', anonymous: true }; - }, - - /** - * Pretty date helper - */ - prettyDate: function(req,res,calipso) { - - var prettyFn = calipso.lib.prettyDate.prettyDate; - return prettyFn; - + // Attach view Helpers to the request + getDynamicHelpers: function(req, res, calipso) { + var self = this; + req.helpers = {}; + for(var helper in self.helpers) { + req.helpers[helper] = self.helpers[helper](req, res, calipso); + } }, - /** - * Hot date helper - */ - hotDate: function(req,res, calipso) { - - var hotFn = calipso.lib.prettyDate.hotDate; - return hotFn; - + // Add a new helper (e.g. so modules can add them) + addHelper: function(name, fn) { + var self = this + self.helpers[name] = fn; }, - /** - * Get block data not included preloaded in the theme configuration (in blockData) - */ - getBlock: function(req, res, calipso){ + helpers: { + /** + * Request shortcut + */ + request: function(req, res, calipso){ + return req; + }, + + /** + * Config shortcut + */ + config: function(req, res, calipso){ + return calipso.config; + }, + + /** + * Translation shortcut + */ + t: function(req, res, calipso){ + return req.t; + }, + + /** + * User shortcut + */ + user: function(req, res, calipso){ + return req.session && req.session.user || { username: '', anonymous: true }; + }, + + /** + * Pretty date helper + */ + prettyDate: function(req,res,calipso) { + + var prettyFn = calipso.lib.prettyDate.prettyDate; + return prettyFn; + + }, + + /** + * Hot date helper + */ + hotDate: function(req,res, calipso) { + + var hotFn = calipso.lib.prettyDate.hotDate; + return hotFn; + + }, + + /** + * Get block data not included preloaded in the theme configuration (in blockData) + */ + getBlock: function(req, res, calipso){ + + return function(block, next) { + + // TODO : Allow block to be passed as a regex (e.g. to include all scripts.* blocks) + var output = ""; + res.renderedBlocks.get(block,function(err,blocks) { + + blocks.forEach(function(content) { + output += content; + }); + + if(typeof next === 'function') + next(null, output); - return function(block, next) { - - // TODO : Allow block to be passed as a regex (e.g. to include all scripts.* blocks) - var output = ""; - res.renderedBlocks.get(block,function(err,blocks) { - - blocks.forEach(function(content) { - output += content; }); - if(typeof next === 'function') - next(null,output); + }; + }, - }); + /** + * Get a menu html, synchronous + */ + getMenu: function(req, res, calipso){ - }; - }, + return function(menu, depth) { + // Render menu + if(res.menu[menu]) { + var output = res.menu[menu].render(req, depth); + return output; + } else { + return 'Menu ' + menu + ' does not exist!'; + } - /** - * Get a menu html, synchronous - */ - getMenu: function(req, res, calipso){ - - return function(menu, depth) { - // Render menu - if(res.menu[menu]) { - var output = res.menu[menu].render(req, depth); - return output; - } else { - return 'Menu ' + menu + ' does not exist!'; - } + }; + }, - }; - }, + /** + * Directly call an exposed module function (e.g. over ride routing rules and inject it anywhere) + */ + getModuleFn: function(req, res, calipso){ - /** - * Directly call an exposed module function (e.g. over ride routing rules and inject it anywhere) - */ - getModuleFn: function(req, res, calipso){ + return function(req,moduleFunction,options,next) { - return function(req,moduleFunction,options,next) { + // Call an exposed module function + // e.g. user.loginForm(req, res, template, block, next) - // Call an exposed module function - // e.g. user.loginForm(req, res, template, block, next) + // First see if function exists + var moduleName = moduleFunction.split(".")[0]; + var functionName = moduleFunction.split(".")[1]; - // First see if function exists - var moduleName = moduleFunction.split(".")[0]; - var functionName = moduleFunction.split(".")[1]; + if(calipso.modules[moduleName] && calipso.modules[moduleName].enabled && calipso.modules[moduleName].fn[functionName]) { - if(calipso.modules[moduleName] && calipso.modules[moduleName].enabled && calipso.modules[moduleName].fn[functionName]) { + var fn = calipso.modules[moduleName].fn[functionName]; - var fn = calipso.modules[moduleName].fn[functionName]; + // Get the template + var template; + if(options.template && calipso.modules[moduleName].templates[options.template]) { + template = calipso.modules[moduleName].templates[options.template]; + } - // Get the template - var template; - if(options.template && calipso.modules[moduleName].templates[options.template]) { - template = calipso.modules[moduleName].templates[options.template]; - } + // Call the fn + try { + fn(req,res,template,null,next); + } catch(ex) { + next(ex); + } - // Call the fn - try { - fn(req,res,template,null,next); - } catch(ex) { - next(ex); + } else { + next(null,"
Function " + moduleFunction + " requested via getModuleFn does not exist or module is not enabled.
"); } - } else { - next(null,"
Function " + moduleFunction + " requested via getModuleFn does not exist or module is not enabled.
"); - } - - }; + }; - }, + }, - /** - * Retrieves the params parsed during module routing - */ - getParams: function(req, res, calipso) { - return function() { - return res.params; + /** + * Retrieves the params parsed during module routing + */ + getParams: function(req, res, calipso) { + return function() { + return res.params; + } + }, + + /** + * Constructs individual classes based on the url request + */ + getPageClasses: function(req, res, calipso) { + var url = stripUrlToConvert(req.url); + return url.split('/').join(' '); + }, + + /** + * Constructs a single id based on the url request + */ + getPageId: function(req, res, calipso) { + var url = stripUrlToConvert(req.url), + urlFrags = url.split('/'); + for (var i = 0, len = urlFrags.length; i < len; i++) { + var frag = urlFrags[i]; + if (frag === '') { + urlFrags.splice(i, 1); + } } - }, + return urlFrags.join('-'); + }, - /** - * Constructs individual classes based on the url request - */ - getPageClasses: function(req, res, calipso) { - var url = stripUrlToConvert(req.url); - return url.split('/').join(' '); - }, - /** - * Constructs a single id based on the url request - */ - getPageId: function(req, res, calipso) { - var url = stripUrlToConvert(req.url), - urlFrags = url.split('/'); - for (var i = 0, len = urlFrags.length; i < len; i++) { - var frag = urlFrags[i]; - if (frag === '') { - urlFrags.splice(i, 1); + addScript: function(req, res, calipso) { + return function(options) { + res.client.addScript(options); } - } - return urlFrags.join('-'); - }, - + }, - addScript: function(req, res, calipso) { - return function(options) { - res.client.addScript(options); - } - }, + getScripts: function(req, res, calipso) { + return function(next) { + res.client.listScripts(next); + } + }, - getScripts: function(req, res, calipso) { - return function(next) { - res.client.listScripts(next); - } - }, + addStyle: function(req, res, calipso) { + return function(options) { + res.client.addStyle(options); + } + }, - addStyle: function(req, res, calipso) { - return function(options) { - res.client.addStyle(options); - } - }, + getStyles: function(req, res, calipso) { + return function(next) { + res.client.listStyles(next); + } + }, - getStyles: function(req, res, calipso) { - return function(next) { - res.client.listStyles(next); + /** + * Flash message helpers + */ + flashMessages: function(req, res, calipso){ + return function() { + return req.flash(); + }; + }, + + /** + * HTML helpers - form (formApi), table, link (for now) + */ + formApi: function(req, res, calipso){ + return function(form) { + return calipso.form.render(form); + }; + }, + table: function(req, res, calipso){ + return function(table) { + return calipso.table.render(table); + }; + }, + link: function(req, res, calipso){ + return function(link) { + return calipso.link.render(link); + }; } - }, - - /** - * Flash message helpers - */ - flashMessages: function(req, res, calipso){ - return function() { - return req.flash(); - }; - }, - - /** - * HTML helpers - form (formApi), table, link (for now) - */ - formApi: function(req, res, calipso){ - return function(form) { - return calipso.form.render(form); - }; - }, - table: function(req, res, calipso){ - return function(table) { - return calipso.table.render(table); - }; - }, - link: function(req, res, calipso){ - return function(link) { - return calipso.link.render(link); - }; - }, + } }; diff --git a/lib/core/Themes.js b/lib/core/Themes.js index 3d6cbbd4e..fa72988d4 100644 --- a/lib/core/Themes.js +++ b/lib/core/Themes.js @@ -503,8 +503,6 @@ function loadModuleOverrideTemplate(templateCache, module, template, path) { // Load the function templateCache.modules[module].templates[template] = templateFnCompiled; - // TODO - Can't currently watch these for changes - } /** @@ -580,7 +578,7 @@ function loadTemplate(templateCache, template, themePath, next) { * If the required view engine does not exist, exit gracefully and let * them know that this is the case. */ -function compileTemplate(data,templatePath,templateExtension) { +function compileTemplate(template, templatePath, templateExtension) { var compiledTemplate = function() {}; var options = {filename:templatePath}; @@ -598,7 +596,7 @@ function compileTemplate(data,templatePath,templateExtension) { // Return our compiled template try { - compiledTemplate = templateEngine.compile(data,options); + compiledTemplate = templateEngine.compile(template, options); } catch(ex) { calipso.error("Error compiling template : " + templatePath + ", message: " + ex.message); } diff --git a/modules/core/content/content.js b/modules/core/content/content.js index 8842b22bf..ddd4baafa 100644 --- a/modules/core/content/content.js +++ b/modules/core/content/content.js @@ -85,14 +85,10 @@ function init(module,app,next) { function done() { // Add dynamic helpers - calipso.helpers.getContent = function() { - return getContent; - } + calipso.helpers.addHelper('getContent',function() { return getContent; }); // Get content list helper - calipso.helpers.getContentList = function() { - return getContentList; - } + calipso.helpers.addHelper('getContentList', function() { return getContentList; }); // Default Content Schema var Content = new calipso.lib.mongoose.Schema({ diff --git a/test/lib.calipso.js b/test/lib.calipso.js index 49bffff54..308ce0e89 100644 --- a/test/lib.calipso.js +++ b/test/lib.calipso.js @@ -21,13 +21,6 @@ describe('Calipso', function(){ done(); }); - it('Dynamic helpers can be loaded', function(done) { - var req = {url:'test/url.html', session: {user: { username:'cliftonc'}}}, res = {}; - calipso.getDynamicHelpers(req, res); - req.helpers.user.username.should.equal('cliftonc'); - done(); - }); - }); after(function() {