Skip to content

Commit

Permalink
Merge branch 'v0.8'
Browse files Browse the repository at this point in the history
  • Loading branch information
mde committed Apr 30, 2013
2 parents ead6495 + dbb652f commit 72100dd
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 354 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ router.match('/farewells/:farewelltype/kings/:kingid').to(

//Can also match specific HTTP methods only
router.match('/xandadu', 'get').to(
{controller: 'Xandadu', action: 'specialHandler'});
{controller: 'Xanadu', action: 'specialHandler'});
```
***Resource routes***
Expand Down
2 changes: 1 addition & 1 deletion examples/related_models/config/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ router.match('/').to({controller: 'Main', action: 'index'});
// {controller: 'Farewells', action: 'kings'});
// Can also match specific HTTP methods only
// router.match('/xandadu', 'get').to(
// {controller: 'Xandadu', action: 'specialHandler'});
// {controller: 'Xanadu', action: 'specialHandler'});
//
// Resource-based routes
// router.resource('hemispheres');
Expand Down
2 changes: 1 addition & 1 deletion examples/socket_io/config/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ router.match('/').to({controller: 'Main', action: 'index'});
// {controller: 'Farewells', action: 'kings'});
// Can also match specific HTTP methods only
// router.match('/xandadu', 'get').to(
// {controller: 'Xandadu', action: 'specialHandler'});
// {controller: 'Xanadu', action: 'specialHandler'});
//
// Resource-based routes
// router.resource('hemispheres');
Expand Down
2 changes: 1 addition & 1 deletion examples/todo_app/config/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ router.match('/').to({controller: 'Todos', action: 'index'});
// {controller: 'Farewells', action: 'kings'});
// Can also match specific HTTP methods only
// router.match('/xandadu', 'get').to(
// {controller: 'Xandadu', action: 'specialHandler'});
// {controller: 'Xanadu', action: 'specialHandler'});
//
// Resource-based routes
// router.resource('hemispheres');
Expand Down
2 changes: 1 addition & 1 deletion gen/jakelib/gen.jake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var cwd = process.cwd()
, fs = require('fs')
, path = require('path')
, utils = require('../../lib/utils')
, Adapter = require('../../lib/template/adapters')
, Adapter = require('../../lib/template/adapters').Adapter
, helpers = require('./helpers')
, mixinJSONData = helpers.mixinJSONData
, getRouterPath = helpers.getRouterPath
Expand Down
3 changes: 1 addition & 2 deletions lib/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ var App = function () {
if(!origFile) origFile = noExtFile;

templates[origFile] = {
registered: true
, file: file
file: file
, ext: fileExt
, baseName: fileBaseName
, baseNamePath: noExtFile
Expand Down
19 changes: 7 additions & 12 deletions lib/controller/base_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -641,8 +641,10 @@ controller.BaseController.prototype = new (function () {
};
this.render = this.respond; // Keep backwards compat

this.renderTemplate = function (data, callback) {
this.renderTemplate = function (d, callback) {

var self = this
, data = utils.mixin({}, d) // Prevent mixin-polution
, templater = new Templater()
, content = '';

Expand All @@ -664,17 +666,10 @@ controller.BaseController.prototype = new (function () {
this.layout = this.layout || 'app/views/layouts/' + dirName;
}

templater.addListener('data', function (data) {
// Buffer for now, but we could stream
content += data;
});
templater.addListener('end', function () {
callback(content);
});

// Mix in controller instance-vars -- don't overwrite data properties
// Mix in controller instance-vars (props only, no methods)
// Don't overwrite existing same-name properties
for (var p in this) {
if (!data[p]) {
if (!(data[p] || typeof this[p] == 'function')) {
data[p] = this[p];
}
};
Expand All @@ -684,7 +679,7 @@ controller.BaseController.prototype = new (function () {
, template: this.template
, controller: this.name
, action: this.params.action
});
}, callback);
};

})();
Expand Down
2 changes: 1 addition & 1 deletion lib/template/adapters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,4 @@ Adapter.prototype.render = function (data) {
return this.engine.render(data, this.compile());
};

module.exports = Adapter;
module.exports.Adapter = Adapter;
4 changes: 3 additions & 1 deletion lib/template/engines/ejs.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ Template.prototype = new function () {
// Return a callable function which will execute the function
// created by the source-code, with the passed data as locals
return function (data, context) {
var locals = utils.mixin(data, {
// Prevent mixin pollution
var d = utils.mixin({}, data);
var locals = utils.mixin(d, {
utils: utils
, rethrow: rethrow
});
Expand Down
203 changes: 13 additions & 190 deletions lib/template/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,199 +15,22 @@
* limitations under the License.
*
*/

var util = require('util') // Native node util for inherits
, path = require('path')
, EventEmitter = require('events').EventEmitter
, TemplateNode = require('./template_node').TemplateNode
, Adapter = require('./adapters')
, Helpers = require('./helpers')
var Adapter = require('./adapters').Adapter
, Templater
, getFileName
, getDirName
, getTemplateData;

/**
* Templating constructor
* @constructor
*/
Templater = function () {
this.currentPartialId = 0;
this.baseTemplateNode = undefined;
this.templateRoot = undefined;
this.isLayout = false;
};

// Create event emitter and event types
util.inherits(Templater, EventEmitter);
Templater.prototype.eventTypes = {
DATA: 'data'
, END: 'end'
};

// Main render function that renders pages from a layout and template(s)
Templater.prototype.render = function (data, config) {
var templateFileName;

// Register data to helpers, and register the helpers to the adapter
geddy.viewHelpers.registerData(data);
Adapter.registerHelpers(geddy.viewHelpers);

// Rendering a template in a layout
if (config.layout) {
this.isLayout = true;
this.templateRoot = getDirName(config.layout);
templateFileName = getFileName(config.layout);

var self = this
, templaterContent = new Templater()
, contentPartial = '';

// Add template content to buffer
templaterContent.addListener('data', function (content) {
contentPartial += content;
, Partial = require('./partial').Partial
, Layout = require('./layout').Layout;

// Define `yield` method
Adapter.registerHelper('yield', function () {
return contentPartial;
});
});
Templater = function () {};

// Once template has been rendered create a partial for the layout
templaterContent.addListener('end', function () {
self.partial(templateFileName, data);
});
Templater.prototype = new (function () {
this.render = function (data, config, cb) {
// Register data to helpers, and register the helpers to the adapter
geddy.viewHelpers.registerData(data);
Adapter.registerHelpers(geddy.viewHelpers);

// Render the template
templaterContent.render(data, {template: config.template});
}
// Rendering a template
else {
this.templateRoot = getDirName(config.template);
templateFileName = getFileName(config.template);

this.partial(templateFileName, data); // Create partial from template
}
};

// Main partial function that renders a template or layout file(or cache)
Templater.prototype.partial = function (partialURL, renderContextParam, parentNode) {
var self = this
, adapter = new Adapter
, partialId = this.currentPartialId
, isBaseNode = !this.baseTemplateNode
, renderParams = renderContextParam || {}
, node
, templateData;

// Get template data object from template registry
templateData = getTemplateData(this.templateRoot, partialURL, parentNode, this.isLayout);

// Create the current node, with reference to parent, if parent exists
node = new TemplateNode(partialId, templateData, renderParams, parentNode, adapter);

// Create helper function that will create partials from a template
renderParams.partial = function (partUrl, data) {
return self.partial.call(self, partUrl, data, node);
var layout = new Layout(config.layout, config.template, data);
layout.render(cb);
};

// If a parent node exists add current node as a child
if (parentNode) {
parentNode.childNodes[partialId] = node;
}

// If this is the base node(No baseTemplateNode yet) give this node
// a finishRoot method that'll render the final, complete version
// of the template
if (isBaseNode) {
// Emit the final content data
node.finishRoot = function () {
self.emit('data', self.baseTemplateNode.content);
self.emit('end');
};

this.baseTemplateNode = node;
node.loadTemplate(); // Start async loading process
}

// Increment current partial id for next partial
this.currentPartialId++;

// Return placeholder text to represent this specific template
// It gets replaced in the callback from the async load of the content
return '###partial###' + partialId;
};

// Return the file name for a path
getFileName = function (p) {
return p.split('/').pop();
};

// Return the first parent for a path
getDirName = function (p) {
p = p.split('/');
p.pop();
return p.join('/');
};

// Return the template object for a template from geddy's template registry
getTemplateData = function (templateRoot, partialURL, parentNode, isLayout) {
var dirs = []
, dir
, key
, templateData
, i;

// If it's a sub template, then look in the parent's directory
if (parentNode) {
dirs.push(parentNode.dirname);
}
// Add template root to directory list
dirs.push(path.normalize(templateRoot));
// Add the base views directory to the list
dirs.push(path.normalize('app/views'));

// Loop through dirs until a registered template path is found
// Note: Template paths are gathered at init so we don't have to touch the FS
// - when looking for templates
i = dirs.length;
while (--i >= 0) {
dir = dirs[i];
key = path.normalize(dir + '/' + partialURL); // Not full path(No extension(s))

if (geddy.templateRegistry[key] && geddy.templateRegistry[key].registered) {
templateData = geddy.templateRegistry[key];
break;
}
}

// No template has been found
if(!templateData) {
var err;

// If it's a layout attempt to find the default layout
if (isLayout) {
templateData = path.normalize('app/views/layouts/application');
// Should be true if the default layout exists
if (templateData in geddy.templateRegistry) {
templateData = geddy.templateRegistry[templateData];
}
// If default layout doesn't exist we have no other layout so throw error
else {
err = new geddy.errors.InternalServerError('Layout template "' +
partialURL + '" not found in ' + geddy.utils.array.humanize(dirs));
throw err;
}
}
// If it's a normal template then it doesn't exist
else {
err = new geddy.errors.InternalServerError('Partial template "' +
partialURL + '" not found in ' + geddy.utils.array.humanize(dirs));
throw err;
}
}

return templateData;
};

})();
exports.Templater = Templater;

22 changes: 22 additions & 0 deletions lib/template/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var Layout
, Partial = require('./partial').Partial;

// Subclass of Partial
Layout = function (layoutPath, templatePath, data) {
var self = this;
// Call the ctor on 'this' -- the the layoutPath will be our
// templatePath
Partial.call(this, layoutPath, data, null);

// `yield` is just a special case of `partial` using the template-path
// that the layout wraps -- just hard-code the path and pass along
// the same data
this.data.yield = function () {
return self.data.partial(templatePath, data);
};
};

Layout.prototype = Object.create(Partial.prototype);
Layout.prototype.constructor = Layout;

exports.Layout = Layout;
Loading

0 comments on commit 72100dd

Please sign in to comment.