Permalink
Browse files

[dist] Release v0.5.0

  • Loading branch information...
0 parents commit 4305ed95c34baadc5aeb0e0f76c77659958cfeb3 @Marak Marak committed Dec 5, 2013
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
@@ -0,0 +1,11 @@
+# view
+
+A View engine for JavaScript.
+
+## Installation
+
+ npm install view
+
+## Tests
+
+ tap test/*.*
@@ -0,0 +1 @@
+- Add documentation
@@ -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;
@@ -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;
@@ -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();
+ }
+};
@@ -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();
+ }
+ };
+
+};
Oops, something went wrong.

0 comments on commit 4305ed9

Please sign in to comment.