Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[dist] Release v0.5.0

  • Loading branch information...
commit 4305ed95c34baadc5aeb0e0f76c77659958cfeb3 0 parents
@Marak Marak authored
Showing with 1,465 additions and 0 deletions.
  1. +11 −0 README.md
  2. +1 −0  TODO.md
  3. +19 −0 index.js
  4. +248 −0 lib/View.js
  5. +26 −0 lib/layout.js
  6. +54 −0 lib/middle.js
  7. +46 −0 lib/query.js
  8. +11 −0 lib/render.js
  9. +17 −0 package.json
  10. +330 −0 test/basic-view-test.js
  11. +121 −0 test/middleware-test.js
  12. +4 −0 test/view1/index.html
  13. +4 −0 test/view10/index.html
  14. +12 −0 test/view10/index.js
  15. +3 −0  test/view10/layout.html
  16. +7 −0 test/view10/layout.js
  17. +4 −0 test/view11/index.html
  18. +10 −0 test/view11/index.js
  19. +3 −0  test/view11/layout.html
  20. +9 −0 test/view11/layout.js
  21. +1 −0  test/view11/table.html
  22. +10 −0 test/view11/table.js
  23. +4 −0 test/view12/index.html
  24. +10 −0 test/view12/index.js
  25. +3 −0  test/view12/layout.html
  26. +9 −0 test/view12/layout.js
  27. +4 −0 test/view13/index.html
  28. +10 −0 test/view13/index.js
  29. +3 −0  test/view13/layout.html
  30. +9 −0 test/view13/layout.js
  31. +1 −0  test/view13/table.html
  32. +10 −0 test/view13/table.js
  33. +4 −0 test/view14/index.html
  34. +10 −0 test/view14/index.js
  35. +3 −0  test/view14/layout.html
  36. +9 −0 test/view14/layout.js
  37. +1 −0  test/view14/table.html
  38. +10 −0 test/view14/table.js
  39. +4 −0 test/view15/index.html
  40. +10 −0 test/view15/index.js
  41. +1 −0  test/view15/test/table.html
  42. +10 −0 test/view15/test/table.js
  43. +4 −0 test/view16/index.html
  44. +10 −0 test/view16/index.js
  45. +4 −0 test/view16/layout.html
  46. +9 −0 test/view16/layout.js
  47. +4 −0 test/view16/test/layout.html
  48. +9 −0 test/view16/test/layout.js
  49. +1 −0  test/view16/test/table.html
  50. +10 −0 test/view16/test/table.js
  51. +3 −0  test/view17/layout.html
  52. +9 −0 test/view17/layout.js
  53. +4 −0 test/view17/root.html
  54. +10 −0 test/view17/root.js
  55. +4 −0 test/view18/index.html
  56. +10 −0 test/view18/index.js
  57. +4 −0 test/view18/layout.html
  58. +9 −0 test/view18/layout.js
  59. +4 −0 test/view18/test/layout.html
  60. +9 −0 test/view18/test/layout.js
  61. +1 −0  test/view18/test/table.html
  62. +10 −0 test/view18/test/table.js
  63. +4 −0 test/view19/index2.html
  64. +10 −0 test/view19/index2.js
  65. +4 −0 test/view19/layout.html
  66. +9 −0 test/view19/layout.js
  67. +1 −0  test/view19/table2.html
  68. +10 −0 test/view19/table2.js
  69. +4 −0 test/view19/test2/index.html
  70. +10 −0 test/view19/test2/index.js
  71. +4 −0 test/view19/test2/layout.html
  72. +9 −0 test/view19/test2/layout.js
  73. +1 −0  test/view19/test2/table.html
  74. +10 −0 test/view19/test2/table.js
  75. +4 −0 test/view2/index.html
  76. +10 −0 test/view2/index.js
  77. +4 −0 test/view3/index.html
  78. +10 −0 test/view3/index.js
  79. +3 −0  test/view3/layout.html
  80. +4 −0 test/view4/index.html
  81. +10 −0 test/view4/index.js
  82. +7 −0 test/view4/layout.js
  83. +4 −0 test/view5/index.html
  84. +10 −0 test/view5/index.js
  85. +3 −0  test/view5/layout.html
  86. +9 −0 test/view5/layout.js
  87. +4 −0 test/view6/index.html
  88. +11 −0 test/view6/index.js
  89. +5 −0 test/view6/layout.html
  90. +11 −0 test/view6/layout.js
  91. +4 −0 test/view7/index.html
  92. +10 −0 test/view7/index.js
  93. +3 −0  test/view7/layout.html
  94. +10 −0 test/view7/layout.js
  95. +1 −0  test/view8/index.html
  96. +10 −0 test/view8/index.js
  97. +2 −0  test/view8/layout.html
  98. +9 −0 test/view8/layout.js
  99. +4 −0 test/view9/index.html
  100. +10 −0 test/view9/index.js
  101. +2 −0  test/view9/layout.html
  102. +11 −0 test/view9/layout.js
11 README.md
@@ -0,0 +1,11 @@
+# view
+
+A View engine for JavaScript.
+
+## Installation
+
+ npm install view
+
+## Tests
+
+ tap test/*.*
1  TODO.md
@@ -0,0 +1 @@
+- Add documentation
19 index.js
@@ -0,0 +1,19 @@
+var view = {};
+
+var View = view.View = require('./lib/View');
+view.middle = require('./lib/middle');
+
+view.create = function (options, callback) {
+ options = options || {};
+ var _view;
+ _view = new View(options);
+ if (options.path) {
+ return _view.load(function(err, r){
+ callback(null, r)
+ });
+ } else {
+ return callback(null, _view);
+ }
+}
+
+module['exports'] = view;
248 lib/View.js
@@ -0,0 +1,248 @@
+var path = require('path'),
+ fs = require('fs');
+
+var query = require('./query'),
+ layout = require('./layout'),
+ render = require('./render');
+
+var View = function (options) {
+
+ var self = this;
+
+ options = options || {};
+
+ self.viewPath = options.path || process.cwd();
+
+ if (options.path) {
+ self.viewPath = options.path;
+ self.templatePath = self.viewPath + '/';
+ self.presenterPath = self.viewPath + '/';
+ }
+
+ if (options.name) {
+ self.name = options.name;
+ } else {
+ self.name = "";
+ }
+
+ if (options.template) {
+ self.template = options.template;
+ //
+ // Remark: If we have been passed in a template as a string, the querySelectorAll context needs to be updated
+ //
+ self.$ = query(self.template);
+ }
+
+ if (options.presenter) {
+ self.presenter = options.presenter;
+ }
+
+ if (options.parent) {
+ self.parent = options.parent;
+ }
+
+ if (typeof options === "string") {
+ this.load(options);
+ }
+
+ return this;
+};
+
+//
+// Loads a template file or directory by path
+//
+View.prototype.load = function (viewPath, cb) {
+ var self = this;
+
+ if(typeof cb !== 'function' && typeof viewPath === 'function') {
+ cb = viewPath;
+ }
+
+ if(typeof viewPath === "string") {
+ self.viewPath = viewPath;
+ }
+
+ self.templatePath = self.viewPath + '/';
+ self.presenterPath = self.viewPath + '/';
+
+ if (typeof cb !== 'function') {
+ throw new Error("callback is required");
+ }
+
+ return self._loadAsync(cb);
+};
+
+View.prototype._loadAsync = function (cb) {
+
+ var self = this,
+ viewPath = self.viewPath,
+ callbacks = 0;
+
+ var root = self.viewPath;
+
+ fs.readdir(root, function(err, dir) {
+ if (err) {
+ return cb(err);
+ }
+ dir.forEach(function(p) {
+ fs.stat(root + '/' + p, function(err, stat) {
+ if (stat.isDirectory()){
+ delegate('dir', p);
+ } else {
+ delegate('file', p);
+ }
+ });
+ });
+ });
+
+ function delegate (type, _path) {
+ var ext = self.detect(_path),
+ subViewName;
+
+ subViewName = _path;
+
+ if (type === "file") {
+
+ subViewName = _path.replace(ext, '');
+
+ //
+ // increase the callback count
+ //
+ callbacks++;
+
+ // determine if file is template or presenter ( presenters end in .js and are node modules )
+ if (ext === ".js") {
+ callbacks--;
+ // don't do anything
+ } else {
+
+ //
+ // load the file as the current template
+ //
+ fs.readFile(root + '/' + _path, function (err, result) {
+
+ if (err) {
+ throw err;
+ }
+ result = result.toString();
+ var presenter, template;
+ //
+ // determine if file is template or presenter
+ //
+ template = result;
+
+ //
+ // get presenter, if it exists
+ //
+ var presenterPath = root + '/' + _path.replace(ext, '.js');
+
+ //
+ // Determine if presenter file exists first before attempting to require it
+ //
+ // TODO: replace with async stat
+ var exists = false;
+ try {
+ var stat = fs.statSync(presenterPath);
+ exists = true;
+ } catch (err) {
+ exists = false;
+ }
+
+ if (exists) {
+ presenterPath = presenterPath.replace('.js', '');
+ presenter = require(presenterPath);
+ }
+
+ self[subViewName] = new View({
+ name: subViewName,
+ template: template,
+ presenter: presenter,
+ parent: self
+ });
+
+ callbacks--;
+ if(callbacks === 0) {
+ cb(null, self);
+ }
+
+ });
+ }
+ }
+
+ if (type === "dir") {
+ //
+ // create a new subview
+ //
+ self[subViewName] = new View({
+ name: subViewName,
+ path: root + '/' + _path,
+ parent: self
+ });
+ //
+ // increase callback count
+ //
+ callbacks ++;
+ //
+ // load view
+ //
+ self[subViewName].load(function() {
+ //
+ // decrease callback count
+ //
+ callbacks--;
+ if(callbacks === 0){
+ cb(null, self);
+ }
+ });
+ }
+ }
+ return;
+
+};
+
+View.prototype.present = function(options, callback) {
+
+ var self = this;
+
+ // if this is not a layout, do perform layout
+ if (self.name !== "layout") {
+ // load query
+ self.$ = query(self.template);
+ layout.call(self, self, options, function(err, result) {
+ if (err)
+ throw err;
+
+ // update template and reload query
+ self.$ = query(result);
+
+ // if we have presenter, use it,
+ // otherwise fallback to default presenter
+ return (self.presenter || render).call(self, options, callback);
+ });
+ } else {
+ // load query
+ self.$ = query(self.template);
+
+ // if we have presenter, use it,
+ // otherwise fallback to default presenter
+ return (self.presenter || render).call(self, options, function(err, result) {
+ return callback(err, result);
+ });
+ }
+};
+
+//
+// TODO: Detects view type based on current path
+//
+View.prototype.detect = function (p) {
+ return path.extname(p);
+};
+
+View.prototype.breadcrumb = function () {
+ if (typeof this.parent === "undefined") {
+ return this.name;
+ }
+ return this.parent.breadcrumb() + '/' + this.name;
+};
+
+module['exports'] = View;
26 lib/layout.js
@@ -0,0 +1,26 @@
+var query = require('./query');
+
+module['exports'] = function (view, data, cb) {
+ var $;
+
+ if(typeof view.parent !== "undefined" && typeof view.parent.layout !== "undefined" && typeof view.parent.layout.present === 'function') {
+ if (cb) {
+ return view.parent.layout.present(data, function(err, content) {
+ $ = query(content);
+ $('#main').html(view.template);
+ return cb(null, $.html());
+ });
+ } else {
+ $ = query(view.parent.layout.present(data));
+ $('#main').html(view.template);
+ }
+ } else {
+ $ = query(view.template);
+ }
+
+ if (cb) {
+ return cb(null, $.html());
+ } else {
+ return $.html();
+ }
+};
54 lib/middle.js
@@ -0,0 +1,54 @@
+// view connect middleware
+
+module['exports'] = function (options) {
+
+ options.prefix = options.prefix || '';
+
+ return function (req, res, next) {
+ if (options.view) {
+ //
+ // If the view was mounted with a prefix and that prefix was not found in the incoming url,
+ // do not attempt to use that view
+ //
+ if (options.prefix.length > 0 && req.url.search(options.prefix) === -1) {
+ return next();
+ }
+ var _view = options.view;
+ var parts = require('url').parse(req.url).pathname.replace(options.prefix, '').split('/');
+ parts.shift();
+
+ // Remark: special case for root with no index, should be refactored
+ if (parts.length === 1 && parts[0] === "" && !_view['index']) {
+ return next();
+ }
+
+ parts.forEach(function(part) {
+ if(part.length > 0 && typeof _view !== 'undefined') {
+ _view = _view[part];
+ }
+ });
+ if (_view && _view['index']) {
+ _view = _view['index'];
+ }
+ if(typeof _view === "undefined") {
+ return next();
+ }
+ if (typeof _view.present !== 'function') {
+ return next();
+ }
+ _view.present({
+ request: req,
+ response: res,
+ data: req.resource.params
+ }, function (err, rendered) {
+ res.end(rendered);
+ });
+ } else {
+ //
+ // No view was found, do not use middleware
+ //
+ next();
+ }
+ };
+
+};
46 lib/query.js
@@ -0,0 +1,46 @@
+var query = function (content) {
+ //
+ // TODO: Add better feature detection here for $
+ //
+ var $,
+ cheerio;
+
+ try {
+ cheerio = require('cheerio');
+ } catch (err) {
+ // Do nothing
+ }
+
+ //
+ // Detected server-side node.js, use cheerio
+ //
+ if(typeof cheerio !== 'undefined') {
+ $ = cheerio;
+ }
+ else
+ {
+ $ = function(){};
+ }
+
+ if(typeof $.load === 'function') {
+ $ = $.load(content);
+ }
+ return $;
+
+ //
+ // Detected client-side jQuery, use jQuery
+ //
+ // TODO
+
+ //
+ // Detected client-side querySelectorAll, using querySelectorAll
+ //
+ // TODO
+
+ //
+ // Client-side, but no $ found. Using Zepto fallback
+ //
+ // TODO
+};
+
+module['exports'] = query;
11 lib/render.js
@@ -0,0 +1,11 @@
+var render = function (options, callback) {
+ var $ = this.$;
+
+ if (typeof callback === "function") {
+ callback(null, $.html());
+ } else {
+ return $.html();
+ }
+};
+
+module['exports'] = render;
17 package.json
@@ -0,0 +1,17 @@
+{
+ "name": "view",
+ "version": "0.5.0",
+ "description": "A View engine",
+ "keywords": [
+ "view",
+ "resource",
+ "resources"
+ ],
+ "scripts": {
+ "test": "tap test/*.*"
+ },
+ "main": "./index.js",
+ "dependencies": {
+ "cheerio": "0.9.x"
+ }
+}
330 test/basic-view-test.js
@@ -0,0 +1,330 @@
+var test = require("tap").test,
+ view = require('../');
+
+test("start a view", function (t) {
+ view.create({} , function (err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ // check default properties
+ t.equal(/.*\/view/.test(_view.viewPath), true, "default viewPath is './view'");
+ t.equal(_view.name, '', "default name is ''");
+ t.equal(_view.template, undefined, "no template is loaded when no path is given");
+ t.equal(_view.presenter, undefined, "no presenter is loaded when no path is given");
+ t.end();
+ });
+});
+
+test("start a view with a given template", function (t) {
+ var _template = '<div class="user">\n\t<div class="name">name</div>\n\t<div class="email">email</div>\n</div>\n';
+ view.create( { template: _template } , function (err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result, _template, 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("start a view with a given template and presenter", function (t) {
+ var _template = '<div class="user">\n\t<div class="name">name</div>\n\t<div class="email">email</div>\n</div>\n';
+ var _presenter = function (options, callback) {
+ callback(null, 'hi');
+ };
+ view.create( { template: _template, presenter: _presenter } , function (err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ t.equal(_view.presenter, _presenter, 'view loaded given presenter');
+ _view.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result, 'hi', 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("start a view with a given presenter but no template", function (t) {
+ var _presenter = function (options, callback) {
+ callback(null, 'hi');
+ };
+ view.create( { presenter: _presenter } , function (err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ t.equal(_view.presenter, _presenter, 'view loaded given presenter');
+ t.equal(_view.template, undefined, 'view loaded empty string as template');
+ _view.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result, "hi", 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("start view from single template at given path", function (t) {
+ var viewPath = __dirname + "/view1";
+ view.create( { path: viewPath } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ t.equal(_view.viewPath, viewPath,
+ 'viewPath was correctly set to path: ' + viewPath);
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<div class="user">\n\t<div class="name">name</div>\n\t<div class="email">email</div>\n</div>\n',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("start view from given path containing single template and presenter", function (t) {
+ view.create( { path: __dirname + "/view2" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("start view from given path containing single template and presenter with layout template", function (t) {
+ view.create( { path: __dirname + "/view3" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>nothing</h1>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+// TODO: is this test valid?
+test("start view from given path containing single template and presenter with layout presenter", function (t) {
+ view.create( { path: __dirname + "/view4" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,'<div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n');
+ t.end();
+ });
+ });
+});
+
+test("start from view given path containing single template and presenter with layout template and presenter", function (t) {
+ view.create( { path: __dirname + "/view5" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>big</h1>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("presenters should have access to view object", function (t) {
+ view.create( { path: __dirname + "/view6" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<div class="layout-name">layout</div>\n<div class="layout-template">%3Cdiv%20class%3D%22layout-name%22%3Ename%3C/div%3E%0A%3Cdiv%20class%3D%22layout-template%22%3Etemplate%3C/div%3E%0A%3Cdiv%20class%3D%22layout-presenter%22%3Epresenter%3C/div%3E%0A%3Cdiv%20class%3D%22layout-parent%22%3Eparent%3C/div%3E%0A%3Cdiv%20id%3D%22main%22%3E%3C/div%3E</div>\n<div class="layout-presenter">function%20%28options%2C%20callback%29%20%7B%0A%0A%20%20var%20%24%20%3D%20this.%24%3B%0A%0A%20%20%24%28%27.layout-name%27%29.html%28this.name%29%3B%0A%20%20%24%28%27.layout-template%27%29.html%28escape%28this.template%29%29%3B%0A%20%20%24%28%27.layout-presenter%27%29.html%28escape%28this.presenter%29%29%3B%0A%20%20%24%28%27.layout-parent%27%29.html%28this.parent.name%29%3B%0A%0A%20%20callback%28null%2C%20%24.html%28%29%29%3B%0A%7D</div>\n<div class="layout-parent"></div>\n<div id="main"><div class="name">index</div>\n<div class="template">%3Cdiv%20class%3D%22name%22%3Ename%3C/div%3E%0A%3Cdiv%20class%3D%22template%22%3Etemplate%3C/div%3E%0A%3Cdiv%20class%3D%22presenter%22%3Epresenter%3C/div%3E%0A%3Cdiv%20class%3D%22parent%22%3Eparent%3C/div%3E</div>\n<div class="presenter">function%20%28options%2C%20callback%29%20%7B%0A%0A%20%20var%20%24%20%3D%20this.%24%3B%0A%0A%20%20%24%28%27.name%27%29.html%28this.name%29%3B%0A%20%20%24%28%27.presenter%27%29.html%28escape%28this.presenter%29%29%3B%0A%20%20%24%28%27.parent%27%29.html%28this.parent.name%29%3B%0A%20%20%24%28%22.template%22%29.html%28escape%28this.template%29%29%3B%0A%0A%20%20callback%28null%2C%20%24.html%28%29%29%3B%0A%7D</div>\n<div class="parent"></div></div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("layout presenter should run before template presenter", function (t) {
+ view.create( { path: __dirname + "/view7" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>big</h1>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+
+test("layout presenter should modify a template before the template presenter is called", function (t) {
+ view.create( { path: __dirname + "/view8" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div></div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("layout presenter should be able to modify template presenter", function (t) {
+ view.create( { path: __dirname + "/view9" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result, 'hi', 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("template presenter should be able to modify layout html", function (t) {
+ view.create( { path: __dirname + "/view10" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>big</h1>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("multiple views with a layout and presenter", function (t) {
+ view.create( { path: __dirname + "/view11" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>big</h1>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>\n',
+ 'present() returns correct result');
+ });
+ _view.table.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>big</h1>\n<div id="main"><div class="table">steve</div>\n</div>\n',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("layout presenter and template presenter both see passed options", function (t) {
+ view.create( { path: __dirname + "/view12" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({
+ name: "Bob",
+ email: "bob@bob.com",
+ company: "big"
+ }, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>big</h1>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("multiple views with a layout and presenter, as well as options", function (t) {
+ view.create( { path: __dirname + "/view13" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({
+ name: "Bob",
+ email: "bob@bob.com",
+ company: "big"
+ }, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>big</h1>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'present() returns correct result');
+ });
+ _view.table.present({
+ table: "steve",
+ company: "company"
+ }, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>company</h1>\n<div id="main"><div class="table">steve</div>\n</div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("nested views, no layouts", function(t) {
+ view.create( { path: __dirname + "/view15" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n',
+ 'present() returns correct result');
+ });
+ _view.test.table.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<div class="table">steve</div>\n',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("nested views, nested layouts affect only appropriate directory level", function(t) {
+ view.create( { path: __dirname + "/view16" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ _view.index.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>big</h1>\n<h2>nothing</h2>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'present() returns correct result');
+ });
+ _view.test.table.present({}, function (err, result) {
+ t.error(err, 'no error');
+ t.ok(result, 'present returns result');
+ t.equal(result,
+ '<h1>nothing</h1>\n<h2>big</h2>\n<div id="main"><div class="table">steve</div>\n</div>',
+ 'present() returns correct result');
+ t.end();
+ });
+ });
+});
121 test/middleware-test.js
@@ -0,0 +1,121 @@
+var test = require("tap").test,
+ resource = require("resource"),
+ supertest = require('supertest'),
+ http,
+ view,
+ server;
+
+test("start a view server", function(t) {
+ view = require('../'),
+ http = require('resource-http');
+ http.listen(function(err, _server) {
+ t.error(err, 'no error');
+ t.ok(_server, 'server is returned');
+ server = _server;
+ t.end();
+ });
+});
+
+test("load a view/layout with http and view.middle", function(t) {
+ view.create({ path: __dirname + "/view17" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+
+ server.before('404').use(view.middle({view: _view})).as('view');
+
+ supertest(server)
+ .get('/root')
+ .end(function(err, res){
+ if (err) throw err;
+ t.error(err, 'no error');
+ t.equal(res.text, '<h1>big</h1>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'response returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("load nested view/layout with http and view.middle", function(t) {
+ view.create( { path: __dirname + "/view18" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ server.before('404').use(view.middle({view: _view})).as('view');
+ supertest(server) // first test index
+ .get('/index')
+ .end(function(err, res){
+ if (err) throw err;
+ t.error(err, 'no error');
+ t.equal(res.text,
+ '<h1>big</h1>\n<h2>nothing</h2>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'response returns correct result');
+ });
+
+ supertest(server) // then test test/table
+ .get('/test/table')
+ .end(function(err, res){
+ if (err) throw err;
+ t.error(err, 'no error');
+ t.equal(res.text,
+ '<h1>nothing</h1>\n<h2>big</h2>\n<div id="main"><div class="table">steve</div>\n</div>',
+ 'response returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("load nested views/layouts with http and view.middle", function(t) {
+ view.create( { path: __dirname + "/view19" } , function(err, _view) {
+ t.error(err, 'no error');
+ t.ok(_view, 'view is returned');
+ server.before('404').use(view.middle({view: _view})).as('view');
+
+ supertest(server) // first test index2
+ .get('/index2')
+ .end(function(err, res){
+ if (err) throw err;
+ t.error(err, 'no error');
+ t.equal(res.text,
+ '<h1>big</h1>\n<h2>nothing</h2>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'response returns correct result');
+ });
+
+ supertest(server) // then test table2
+ .get('/table2')
+ .end(function(err, res){
+ if (err) throw err;
+ t.error(err, 'no error');
+ t.equal(res.text,
+ '<h1>big</h1>\n<h2>nothing</h2>\n<div id="main"><div class="table">steve</div>\n</div>',
+ 'response returns correct result');
+ });
+
+ supertest(server) // then test test2/index
+ .get('/test2/index')
+ .end(function(err, res){
+ if (err) throw err;
+ t.error(err, 'no error');
+ t.equal(res.text,
+ '<h1>nothing</h1>\n<h2>big</h2>\n<div id="main"><div class="user">\n\t<div class="name">Bob</div>\n\t<div class="email">bob@bob.com</div>\n</div>\n</div>',
+ 'response returns correct result');
+ });
+
+ supertest(server) // then test test2/table
+ .get('/test2/table')
+ .end(function(err, res){
+ if (err) throw err;
+ t.error(err, 'no error');
+ t.equal(res.text,
+ '<h1>nothing</h1>\n<h2>big</h2>\n<div id="main"><div class="table">steve</div>\n</div>',
+ 'response returns correct result');
+ t.end();
+ });
+ });
+});
+
+test("stop a view server", function(t) {
+ server.server.close(function(err) {
+ t.ok(!err, 'no error');
+ t.end();
+ process.exit();
+ });
+});
4 test/view1/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
4 test/view10/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
12 test/view10/index.js
@@ -0,0 +1,12 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ $('h1').html('big');
+
+ callback(null, $.html());
+};
3  test/view10/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id="main">
+</div>
7 test/view10/layout.js
@@ -0,0 +1,7 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ callback(null, $.html());
+};
4 test/view11/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view11/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
3  test/view11/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id="main">
+</div>
9 test/view11/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html('big');
+
+ callback(null, $.html());
+};
1  test/view11/table.html
@@ -0,0 +1 @@
+<div class="table">nothing</div>
10 test/view11/table.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.table').html('steve');
+
+ callback(null, $.html());
+};
+
4 test/view12/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view12/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html(options.name);
+ $('.user > .email').html(options.email);
+
+ callback(null, $.html());
+};
3  test/view12/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id="main">
+</div>
9 test/view12/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html(options.company);
+
+ callback(null, $.html());
+};
4 test/view13/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view13/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html(options.name);
+ $('.user > .email').html(options.email);
+
+ callback(null, $.html());
+};
3  test/view13/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id="main">
+</div>
9 test/view13/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html(options.company);
+
+ callback(null, $.html());
+};
1  test/view13/table.html
@@ -0,0 +1 @@
+<div class="table">nothing</div>
10 test/view13/table.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.table').html('steve');
+
+ callback(null, $.html());
+};
+
4 test/view14/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view14/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html(options.name);
+ $('.user > .email').html(options.email);
+
+ callback(null, $.html());
+};
3  test/view14/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id="main">
+</div>
9 test/view14/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html(options.company);
+
+ callback(null, $.html());
+};
1  test/view14/table.html
@@ -0,0 +1 @@
+<div class="table">nothing</div>
10 test/view14/table.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.table').html(options.table);
+
+ callback(null, $.html());
+};
+
4 test/view15/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view15/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
1  test/view15/test/table.html
@@ -0,0 +1 @@
+<div class="table">nothing</div>
10 test/view15/test/table.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.table').html('steve');
+
+ callback(null, $.html());
+};
+
4 test/view16/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view16/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
4 test/view16/layout.html
@@ -0,0 +1,4 @@
+<h1>nothing</h1>
+<h2>nothing</h2>
+<div id="main">
+</div>
9 test/view16/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html('big');
+
+ callback(null, $.html());
+};
4 test/view16/test/layout.html
@@ -0,0 +1,4 @@
+<h1>nothing</h1>
+<h2>nothing</h2>
+<div id="main">
+</div>
9 test/view16/test/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h2').html('big');
+
+ callback(null, $.html());
+};
1  test/view16/test/table.html
@@ -0,0 +1 @@
+<div class="table">nothing</div>
10 test/view16/test/table.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.table').html('steve');
+
+ callback(null, $.html());
+};
+
3  test/view17/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id="main">
+</div>
9 test/view17/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html('big');
+
+ callback(null, $.html());
+};
4 test/view17/root.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view17/root.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
4 test/view18/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view18/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
4 test/view18/layout.html
@@ -0,0 +1,4 @@
+<h1>nothing</h1>
+<h2>nothing</h2>
+<div id="main">
+</div>
9 test/view18/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html('big');
+
+ callback(null, $.html());
+};
4 test/view18/test/layout.html
@@ -0,0 +1,4 @@
+<h1>nothing</h1>
+<h2>nothing</h2>
+<div id="main">
+</div>
9 test/view18/test/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h2').html('big');
+
+ callback(null, $.html());
+};
1  test/view18/test/table.html
@@ -0,0 +1 @@
+<div class="table">nothing</div>
10 test/view18/test/table.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.table').html('steve');
+
+ callback(null, $.html());
+};
+
4 test/view19/index2.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view19/index2.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
4 test/view19/layout.html
@@ -0,0 +1,4 @@
+<h1>nothing</h1>
+<h2>nothing</h2>
+<div id="main">
+</div>
9 test/view19/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html('big');
+
+ callback(null, $.html());
+};
1  test/view19/table2.html
@@ -0,0 +1 @@
+<div class="table">nothing</div>
10 test/view19/table2.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.table').html('steve');
+
+ callback(null, $.html());
+};
+
4 test/view19/test2/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view19/test2/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
4 test/view19/test2/layout.html
@@ -0,0 +1,4 @@
+<h1>nothing</h1>
+<h2>nothing</h2>
+<div id="main">
+</div>
9 test/view19/test2/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h2').html('big');
+
+ callback(null, $.html());
+};
1  test/view19/test2/table.html
@@ -0,0 +1 @@
+<div class="table">nothing</div>
10 test/view19/test2/table.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.table').html('steve');
+
+ callback(null, $.html());
+};
+
4 test/view2/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view2/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
4 test/view3/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view3/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
3  test/view3/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id="main">
+</div>
4 test/view4/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view4/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
7 test/view4/layout.js
@@ -0,0 +1,7 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ callback(null, "<div id='main'></div>");
+};
4 test/view5/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view5/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
3  test/view5/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id="main">
+</div>
9 test/view5/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html('big');
+
+ callback(null, $.html());
+};
4 test/view6/index.html
@@ -0,0 +1,4 @@
+<div class="name">name</div>
+<div class="template">template</div>
+<div class="presenter">presenter</div>
+<div class="parent">parent</div>
11 test/view6/index.js
@@ -0,0 +1,11 @@
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.name').html(this.name);
+ $('.presenter').html(escape(this.presenter));
+ $('.parent').html(this.parent.name);
+ $(".template").html(escape(this.template));
+
+ callback(null, $.html());
+};
5 test/view6/layout.html
@@ -0,0 +1,5 @@
+<div class="layout-name">name</div>
+<div class="layout-template">template</div>
+<div class="layout-presenter">presenter</div>
+<div class="layout-parent">parent</div>
+<div id="main"></div>
11 test/view6/layout.js
@@ -0,0 +1,11 @@
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.layout-name').html(this.name);
+ $('.layout-template').html(escape(this.template));
+ $('.layout-presenter').html(escape(this.presenter));
+ $('.layout-parent').html(this.parent.name);
+
+ callback(null, $.html());
+};
4 test/view7/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view7/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
3  test/view7/layout.html
@@ -0,0 +1,3 @@
+<h1>nothing</h1>
+<div id='main'>
+</div>
10 test/view7/layout.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('h1').html('big');
+ $('.main').html('big');
+
+ callback(null, $.html());
+};
1  test/view8/index.html
@@ -0,0 +1 @@
+<div class="user">nothing</div>
10 test/view8/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
2  test/view8/layout.html
@@ -0,0 +1,2 @@
+<div id='main'>
+</div>
9 test/view8/layout.js
@@ -0,0 +1,9 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ this.parent.index.template = '<div class="user">\n\t<div class="name">name</div>\n\t<div class="email">email</div>\n</div>';
+
+ callback(null, $.html());
+};
4 test/view9/index.html
@@ -0,0 +1,4 @@
+<div class="user">
+ <div class="name">name</div>
+ <div class="email">email</div>
+</div>
10 test/view9/index.js
@@ -0,0 +1,10 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ $('.user > .name').html('Bob');
+ $('.user > .email').html('bob@bob.com');
+
+ callback(null, $.html());
+};
2  test/view9/layout.html
@@ -0,0 +1,2 @@
+<div id='main'>
+</div>
11 test/view9/layout.js
@@ -0,0 +1,11 @@
+
+module['exports'] = function (options, callback) {
+
+ var $ = this.$;
+
+ this.parent.index.presenter = function (options, callback) {
+ callback(null, "hi");
+ };
+
+ callback(null, $.html());
+};
Please sign in to comment.
Something went wrong with that request. Please try again.