Skip to content

Commit

Permalink
Major updates to the way plugins work
Browse files Browse the repository at this point in the history
  • Loading branch information
sax1johno committed Apr 23, 2013
1 parent 2cc1bb3 commit bdce450
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 165 deletions.
1 change: 1 addition & 0 deletions .c9revisions/lib/plugin.js.c9save
Expand Up @@ -16,3 +16,4 @@
{"ts":1361578660540,"patch":[[{"diffs":[[0,"ts ="],[-1," new"],[0," Plugin"],[-1,"()"],[0,";"]],"start1":235,"start2":235,"length1":18,"length2":12}]],"length":247,"saved":false}
{"contributors":[],"silentsave":false,"ts":1361737952552,"patch":[[{"diffs":[[0,";\n }\n"],[-1,"\n"],[0,"}\n\nmodul"]],"start1":211,"start2":211,"length1":17,"length2":16}]],"length":246,"saved":false}
{"ts":1361740895999,"patch":[[{"diffs":[[0,"s = "],[-1,"[]"],[1,"{}"],[0,";\n "]],"start1":153,"start2":153,"length1":10,"length2":10}]],"length":246,"saved":false}
{"contributors":[],"silentsave":false,"ts":1366739973698,"patch":[[{"diffs":[[0,"re')"],[-1,";\n\nfunction Plugin (obj, options) {\n if (!(this instanceof Plugin))\n return new Plugin(obj, options);\n \n this.views = {};\n \n if (obj) {\n this.views = obj.views;\n }"],[1,",\n Template = require('./template');\n\n/** \n * A Plugin represents a separate piece of functionality in a Ghiraldi app. Ghiraldi\n * apps are generally composed of a number of functional plugins.\n * \n * Plugins handle, among other things, the rendering of views.\n **/\nfunction Plugin (obj, options) {\n if (!(this instanceof Plugin))\n return new Plugin(obj, options);\n \n this.views = {};\n this.baseDir = null;\n this.fileName = null;\n this.name = null;\n \n // Contains a cache of the rendered views. This eliminates the need for re-building the views\n // on every call.\n this.viewCache = {};\n \n if (obj) {\n this.views = obj.views;\n }\n \n this.getView = function(viewName) {\n if (!_.isUndefined(this.views[viewName]) && !_.isNull(this.views[viewName])) {\n if (!_.isUndefined(this.viewCache[viewName]) && !_.isNull(this.viewCache[viewName])) {\n return this.viewCache[viewName];\n } else {\n this.viewCache[viewName] = new Template(this.views[viewName].uri);\n }\n } else {\n throw \"No view found with name \" + viewName + \" in this plugin\";\n }\n };\n \n this.get = function() {\n if (!_.isNull(this.basedir) \n && !_.isNull(this.requireFile))\n return require(this.baseDir + '/' + this.fileName);\n return null;\n };\n \n /**\n * Get a module from within this plugin's base directory.\n * @param modulePath the path to the module. (including the beginning /)\n * @return the complete module path which can be passed to \"require\"\n **/\n this.getModule = function(path) {\n return this.baseDir + path;\n }\n "],[0,"\n}\n\n"]],"start1":25,"start2":25,"length1":197,"length2":1722}]],"length":1771,"saved":false}
1 change: 1 addition & 0 deletions .c9revisions/lib/plugin_registry.js.c9save
Expand Up @@ -50,3 +50,4 @@
{"ts":1361250843922,"patch":[[{"diffs":[[0,"var "],[-1,"mongoose = require('mongoose'),\n "],[0,"_ = "]],"start1":0,"start2":0,"length1":44,"length2":8}]],"length":2284,"saved":false}
{"ts":1361251259384,"patch":[[{"diffs":[[0,"xports ="],[1," {\n registry:"],[0," new Plu"]],"start1":2254,"start2":2254,"length1":16,"length2":32},{"diffs":[[0,"gistry()"],[1,",\n plugin: plugin\n}"],[0,";"]],"start1":2291,"start2":2291,"length1":9,"length2":31}]],"length":2322,"saved":false}
{"ts":1361251344074,"patch":[[{"diffs":[[0,"stry(),\n "],[-1,"p"],[1,"P"],[0,"lugin: plugi"]],"start1":2293,"start2":2293,"length1":25,"length2":25}]],"length":2322,"saved":false}
{"contributors":[],"silentsave":false,"ts":1366739961535,"patch":[[{"diffs":[[0,"plugin')"],[-1,""],[0,""],[1,",\n template = require('./template')"],[0,";\n \nf"]],"start1":106,"start2":106,"length1":16,"length2":54},{"diffs":[[0,"new "],[-1,"schema"],[1,"plugin"],[0," to the "],[-1,"schema"],[1,"plugin"],[0," reg"]],"start1":460,"start2":460,"length1":28,"length2":28},{"diffs":[[0,"revious "],[-1,"schema"],[1,"plugin"],[0,"\n * "]],"start1":522,"start2":522,"length1":22,"length2":22},{"diffs":[[0,"ram "],[-1,"schema the schema"],[1,"plugin the plugin"],[0," to "]],"start1":570,"start2":570,"length1":25,"length2":25},{"diffs":[[0,"or this "],[-1,"schema"],[1,"plugin"],[0," (used t"]],"start1":627,"start2":627,"length1":22,"length2":22},{"diffs":[[0,"the "],[-1,"schema)"],[1,"plugin)\n * @param fn a function that is called when the add is complete."],[0,"\n "]],"start1":660,"start2":660,"length1":15,"length2":84},{"diffs":[[0,"e added "],[-1,"schema"],[1,"plugin"],[0,".\n *"]],"start1":758,"start2":758,"length1":22,"length2":22},{"diffs":[[0," "],[-1,"if (!_.isUndefined(fn) && !_.isNull(fn) && _.isFunction(fn)) {\n fn("],[0,"plug"]],"start1":830,"start2":830,"length1":86,"length2":8},{"diffs":[[0,"= plugin"],[-1,")"],[0,";\n "]],"start1":847,"start2":847,"length1":17,"length2":16},{"diffs":[[0," "],[-1,"} else {\n plugins[tag] ="],[1,"this.emit('add', tag,"],[0," plugin"],[1,")"],[0,";\n "]],"start1":861,"start2":861,"length1":50,"length2":37},{"diffs":[[0," "],[-1,"}\n this.emit('add', tag, "],[1,"if (!_.isUndefined(fn) && !_.isNull(fn)) {\n fn("],[0,"plug"]],"start1":900,"start2":900,"length1":40,"length2":66},{"diffs":[[0,"gin); "],[1,"\n"],[0," "],[1," }"],[0,"\n };\n"]],"start1":965,"start2":965,"length1":21,"length2":26},{"diffs":[[0,"emove a "],[-1,"schema"],[1,"plugin"],[0," from th"]],"start1":1012,"start2":1012,"length1":22,"length2":22},{"diffs":[[0,"rom the "],[-1,"schema"],[1,"plugin"],[0," registr"]],"start1":1028,"start2":1028,"length1":22,"length2":22},{"diffs":[[0,"the "],[-1,"schema to be removed"],[1,"plugin to be removed\n * @param fn a function that is called when the remove is complete."],[0,"\n "]],"start1":1083,"start2":1083,"length1":28,"length2":100},{"diffs":[[0,"= plugins[tag];\n"],[1," this.emit('remove', deleted);\n"],[0," if (!_.i"]],"start1":1314,"start2":1314,"length1":32,"length2":70},{"diffs":[[0,"(fn)"],[-1," && _.isFunction(fn)"],[0,") {\n"]],"start1":1411,"start2":1411,"length1":28,"length2":8},{"diffs":[[0,"lete"],[-1," plugins[tag]); \n } else {\n "],[1,"d);\n }\n"],[0," "]],"start1":1436,"start2":1436,"length1":57,"length2":22},{"diffs":[[0," "],[1,"};\n"],[0," "],[-1,"}"],[0,"\n "],[-1," this.emit('remove', deleted);\n };\n \n this.get = function(tag, fn) {\n if (_.isUndefined(plugins[tag])) {\n "],[1,"/**\n * Get a plugin from the plugin registry.\n * @param tag the tag for the plugin.\n * @param fn a function that is called with the plugin requested.\n * @return the requested plugin, or undefined if a plugin with the specified\n"],[0," "],[1,"*"],[0," "],[-1,"plugins[tag] = new plugin({});\n }"],[1,"tag is not found.\n **/\n this.get = function(tag, fn) {"],[0,"\n "]],"start1":1490,"start2":1490,"length1":194,"length2":336},{"diffs":[[0,"tag]);\n }"],[-1,""],[0,""],[1," "],[0,"\n return "]],"start1":1897,"start2":1897,"length1":32,"length2":40},{"diffs":[[0,".log = function("],[-1,"fn"],[0,") {\n if ("]],"start1":2033,"start2":2033,"length1":34,"length2":32},{"diffs":[[0," "],[-1,"if (!_.isUndefined(fn) && !_.isNull(fn)) {"],[1,"return plugins;\n };\n "],[0,"\n "],[1,"/**\n"],[0," "],[-1," fn(plugins);\n }"],[1,"* Get all of the plugins available in the plugin registry."],[0,"\n "],[-1," "],[1,"* @"],[0,"return "],[1,"the "],[0,"plugin"],[-1,"s;\n };\n "],[1," tags.\n **/"],[0,"\n "]],"start1":2057,"start2":2057,"length1":121,"length2":148},{"diffs":[[0,"unction("],[-1,"fn"],[0,") {\n "]],"start1":2222,"start2":2222,"length1":18,"length2":16},{"diffs":[[0," }\n"],[-1," if (!_.isUndefined(fn) && !_.isNull(fn)) {\n fn(keys); \n }\n"],[0," "]],"start1":2335,"start2":2335,"length1":97,"length2":8},{"diffs":[[0,": plugin"],[-1,""],[0,""],[1,",\n Template: template"],[0,"\n};"]],"start1":2496,"start2":2496,"length1":11,"length2":35}]],"length":2531,"saved":false}
2 changes: 2 additions & 0 deletions .c9revisions/lib/template.js.c9save
@@ -0,0 +1,2 @@
{"ts":1366739996860,"silentsave":true,"restoring":false,"patch":[[]],"length":0}
{"contributors":[],"silentsave":false,"ts":1366740000112,"patch":[[{"diffs":[[1,"var _ = require('underscore'),\n jade = require('jade'),\n fs = require('fs');\n\nfunction Template(uri) {\n if (!(this instanceof Template))\n return new Template(uri);\n\n this.cachedTemplateString = \"\";\n \n this.uri = uri;\n \n this.extend = {};\n \n this.includes = [];\n \n this.load(uri);\n \n}\n\n/**\n * Loads the file at the URI into the template string and performs the injections\n * of the extends and includes.\n * @param uri an optional uri that can be used to re-load the template with a new file.\n **/\nTemplate.prototype.load = function(uri, returnFn) {\n if (!_.isUndefined(uri) && !_.isNull(uri)) {\n this.uri = uri;\n }\n \n // Load up the URI into the cached template string.\n this.cachedTemplateString = fs.readFileSync(this.uri, 'utf8');\n \n var includes = [];\n var extend = {};\n \n // Inject the includes and extends into the cachedTemplateString.\n if (!_.isUndefined(this.includes) && !_.isNull(this.includes)) {\n includes = this.includes;\n };\n \n if (!_.isUndefined(this.extend) && !_.isNull(this.extend)) {\n extend = this.extend;\n }\n \n function processExtends() {\n if (!_.isNull(this.extend) && !_.isUndefined(this.extend)) {\n if (!_.isEmpty(this.extend)) {\n var re = new RegExp(\"extends \" + this.extend.name,\"g\");\n this.cachedTemplateString = this.cachedTemplateString.replace(re, \"extends \" + this.extend.uri); \n }\n }\n return processIncludes(0);\n }\n \n function processIncludes(index) {\n if (index < _.size(this.includes) - 1) {\n if(!_.isUndefined(this.includes) && !_.isUndefined(this.includes) && !_.isEmpty(this.includes)) {\n var re = new RegExp(\"include \" + this.includes[index].name,\"g\");\n this.cachedTemplateString = this.cachedTemplateString.replace(re, \"include \" + this.includes[index].uri); \n }\n // Now, call the next one.\n processIncludes(++index);\n } else {\n // Now, return the cachedTemplateString\n if (!_.isNull(returnFn) && !_.isUndefined(returnFn)) {\n returnFn(this.cachedTemplateString); \n }\n \n return this.cachedTemplateString; \n }\n }\n \n return processExtends();\n};\n\n/**\n * Use this method to dynamically inject layout items into a template.\n * @param obj an object with the layout extensions and inclusions.\n * @param fn a function to be called when injection is complete.\n **/\nTemplate.prototype.inject = function(object) {\n if (!_.isUndefined(object) && !_.isNull(object)) {\n if (!_.isUndefined(object.includes) && !_.isNull(object.includes)) {\n this.includes = object.includes;\n }\n if (!_.isUndefined(object.extend) && !_.isNull(object.extend)) {\n this.extend = object.extend;\n }\n }\n};\n\n/**\n * Renders the template with the given locals and calls the return function with\n * the HTML to be rendered. Can also optionally be given a \"response\" object from express\n * to render the response.\n * @param res a response object that can render html.\n * @param locals an object with local variables to pass into the template.\n * @param a function that is called when the render is complete. The function\n * takes an err and html parameter.\n **/\nTemplate.prototype.render = function(res, locals, fn) {\n // first, lets check to see if this is the 2 argument version or the 3 argument version.\n if (_.isFunction(locals)) {\n locals = res;\n fn = locals;\n res = null;\n }\n \n var compileConfig = {};\n compileConfig.filename = '/';\n if (!_.isUndefined(locals) && !_.isNull(locals)) {\n compileConfig.locals = locals; \n }\n \n if (this.cachedTemplateString === '') {\n this.load(this.uri);\n compileTemplate();\n } else {\n compileTemplate();\n }\n \n function compileTemplate() {\n var compiledTemplate = jade.compile(this.cachedTemplateString, compileConfig);\n console.log(\"Compiled template: \" + compiledTemplate);\n \n // Last part is to render and / or return the template.\n if (!_.isUndefined(res) && !_.isNull(res)) {\n res.send(compiledTemplate); \n }\n \n if (!_.isUndefiend(fn) && !_.isNull(fn) && _.isFunction(fn)) {\n fn(compiledTemplate);\n }\n }\n};\n\nmodule.exports = Template;"]],"start1":0,"start2":0,"length1":0,"length2":4522}]],"length":4522,"saved":false}
1 change: 1 addition & 0 deletions .c9revisions/package.json.c9save
Expand Up @@ -35,3 +35,4 @@
{"contributors":[],"silentsave":false,"ts":1361255820545,"patch":[[{"diffs":[[0,"name\": \""],[-1,"mongoose-schema"],[1,"ghiraldi-plugin"],[0,"-registr"]],"start1":5,"start2":5,"length1":31,"length2":31},{"diffs":[[0,"\": \""],[-1,"Creates a schema registry that can be used to store and retrieve mongoose schemas.\",\n \"tags\": [\n \"mongoose\",\n \"schema"],[1,"The plugin registry allows for the registration of plugins into a central store and provides access to plugin properties for other controllers. This is particularly useful for things like the admin core plugin, which uses the registry to build the admin views for controllers."],[0,"\",\n"],[-1," "],[0," \""],[-1,"registry\","],[1,"tags\": ["],[0,"\n "]],"start1":54,"start2":54,"length1":150,"length2":298},{"diffs":[[0,"hiraldi\""],[1,",\n \"registry\""],[0,"\n ],\n "]],"start1":355,"start2":355,"length1":16,"length2":32},{"diffs":[[0," \"./lib/"],[-1,"mongoose"],[1,"plugin"],[0,"_registr"]],"start1":540,"start2":540,"length1":24,"length2":22}]],"length":860,"saved":false}
{"ts":1361255849410,"patch":[[{"diffs":[[0,"hno/"],[-1,"mongoose-schema"],[1,"ghiraldi-plugin"],[0,"-reg"]],"start1":746,"start2":746,"length1":23,"length2":23},{"diffs":[[0,",\n \"_id\": \""],[-1,"mongoose"],[1,"ghiraldi_plugin"],[0,"_registry@0."]],"start1":783,"start2":783,"length1":32,"length2":39},{"diffs":[[0,"from\": \""],[-1,"mongoose"],[1,"ghiraldi_plugin"],[0,"_registr"]],"start1":832,"start2":832,"length1":24,"length2":31}]],"length":874,"saved":false}
{"contributors":[],"silentsave":false,"ts":1361741690754,"patch":[[{"diffs":[[0,"sion\": \"0.0."],[-1,"6"],[1,"7"],[0,"\",\n \"author"]],"start1":391,"start2":391,"length1":25,"length2":25},{"diffs":[[0,"try@0.0."],[-1,"6"],[1,"7"],[0,"\",\n \"_f"]],"start1":816,"start2":816,"length1":17,"length2":17},{"diffs":[[0,"0.0."],[-1,"6"],[1,"7"],[0,"\"\n}\n"]],"start1":865,"start2":865,"length1":9,"length2":9}]],"length":874,"saved":false}
{"contributors":[],"silentsave":false,"ts":1366740026815,"patch":[[{"diffs":[[0,"sion\": \"0.0."],[-1,"7"],[1,"8"],[0,"\",\n \"author"]],"start1":391,"start2":391,"length1":25,"length2":25},{"diffs":[[0,"try@0.0."],[-1,"7"],[1,"8"],[0,"\",\n \"_f"]],"start1":816,"start2":816,"length1":17,"length2":17},{"diffs":[[0,"0.0."],[-1,"7"],[1,"8"],[0,"\"\n}\n"]],"start1":865,"start2":865,"length1":9,"length2":9}]],"length":874,"saved":false}
45 changes: 44 additions & 1 deletion lib/plugin.js
@@ -1,14 +1,57 @@
var _ = require('underscore');
var _ = require('underscore'),
Template = require('./template');

/**
* A Plugin represents a separate piece of functionality in a Ghiraldi app. Ghiraldi
* apps are generally composed of a number of functional plugins.
*
* Plugins handle, among other things, the rendering of views.
**/
function Plugin (obj, options) {
if (!(this instanceof Plugin))
return new Plugin(obj, options);

this.views = {};
this.baseDir = null;
this.fileName = null;
this.name = null;

// Contains a cache of the rendered views. This eliminates the need for re-building the views
// on every call.
this.viewCache = {};

if (obj) {
this.views = obj.views;
}

this.getView = function(viewName) {
if (!_.isUndefined(this.views[viewName]) && !_.isNull(this.views[viewName])) {
if (!_.isUndefined(this.viewCache[viewName]) && !_.isNull(this.viewCache[viewName])) {
return this.viewCache[viewName];
} else {
this.viewCache[viewName] = new Template(this.views[viewName].uri);
}
} else {
throw "No view found with name " + viewName + " in this plugin";
}
};

this.get = function() {
if (!_.isNull(this.basedir)
&& !_.isNull(this.requireFile))
return require(this.baseDir + '/' + this.fileName);
return null;
};

/**
* Get a module from within this plugin's base directory.
* @param modulePath the path to the module. (including the beginning /)
* @return the complete module path which can be passed to "require"
**/
this.getModule = function(path) {
return this.baseDir + path;
}

}

module.exports = Plugin;

0 comments on commit bdce450

Please sign in to comment.