Permalink
Browse files

Added new Jade example

- Example may need some fixing once we get the rendering complete

Moved EJS implementation to `/deps`
- I did this so we can easily manage it ouside the template folder
- Also because it works better there with the Templato module

Include a customized version of the Templato module
- Templato will manage our helper functions
- Also will manage the actual compiling of the templates
  • Loading branch information...
larzconwell committed Jun 16, 2012
1 parent b9c89f0 commit 7f414ae27e36b260d2b3852a3659e7ba6af9d788
Showing with 8,128 additions and 260 deletions.
  1. +10 −8 Jakefile
  2. +1 −1 README.md
  3. +1 −1 bin/cli.js
  4. +302 −0 deps/ejs.js
  5. +154 −0 deps/templato/color.js
  6. +64 −0 deps/templato/grunt.js
  7. +1 −0 deps/templato/index.js
  8. +23 −0 deps/templato/lib/engines/ejs.js
  9. +21 −0 deps/templato/lib/engines/geddy_ejs.js
  10. +23 −0 deps/templato/lib/engines/handlebars.js
  11. +23 −0 deps/templato/lib/engines/jade.js
  12. +29 −0 deps/templato/lib/engines/mustache.js
  13. +95 −0 deps/templato/lib/templato.js
  14. +18 −0 deps/templato/package.json
  15. +62 −0 deps/templato/test.js
  16. +25 −0 examples/todo_app_jade/app/controllers/application.js
  17. +30 −0 examples/todo_app_jade/app/controllers/main.js
  18. +83 −0 examples/todo_app_jade/app/controllers/todos.js
  19. +22 −0 examples/todo_app_jade/app/models/todo.js
  20. +45 −0 examples/todo_app_jade/app/views/layouts/application.html.jade
  21. +6 −0 examples/todo_app_jade/app/views/main/index.html.ejs
  22. +31 −0 examples/todo_app_jade/app/views/todos/_form.html.jade
  23. +2 −0 examples/todo_app_jade/app/views/todos/add.html.jade
  24. +2 −0 examples/todo_app_jade/app/views/todos/edit.html.jade
  25. +13 −0 examples/todo_app_jade/app/views/todos/index.html.jade
  26. +5 −0 examples/todo_app_jade/app/views/todos/show.html.jade
  27. +31 −0 examples/todo_app_jade/config/development.js
  28. +14 −0 examples/todo_app_jade/config/environment.js
  29. +6 −0 examples/todo_app_jade/config/init.js
  30. +32 −0 examples/todo_app_jade/config/production.js
  31. +37 −0 examples/todo_app_jade/config/router.js
  32. +3,363 −0 examples/todo_app_jade/public/css/bootstrap.css
  33. +610 −0 examples/todo_app_jade/public/css/bootstrap.min.css
  34. +567 −0 examples/todo_app_jade/public/css/bootstrap.responsive.css
  35. +3 −0 examples/todo_app_jade/public/css/bootstrap.responsive.min.css
  36. +50 −0 examples/todo_app_jade/public/css/style.css
  37. BIN examples/todo_app_jade/public/favicon.ico
  38. BIN examples/todo_app_jade/public/img/glyphicons-halflings-white.png
  39. BIN examples/todo_app_jade/public/img/glyphicons-halflings.png
  40. BIN examples/todo_app_jade/public/img/whitey.png
  41. +1,722 −0 examples/todo_app_jade/public/js/bootstrap.js
  42. +1 −0 examples/todo_app_jade/public/js/bootstrap.min.js
  43. +4 −0 examples/todo_app_jade/public/js/jquery.min.js
  44. +1 −1 lib/app.js
  45. +75 −210 lib/template/adapters/ejs.js
  46. +301 −0 lib/template/adapters/ejs_engine_copy.js
  47. +2 −3 lib/template/adapters/index.js
  48. +32 −26 lib/template/adapters/jade.js
  49. +168 −0 lib/template/adapters/mustache.js
  50. +9 −6 lib/template/index.js
  51. +3 −2 lib/template/template_node.js
  52. +1 −0 templates/locales/es-es.json
  53. +5 −2 test/ejs.js
View
@@ -7,20 +7,22 @@ var fs = require('fs')
, exec = child_process.exec
, inflection = require('./deps/inflection')
, utils = require('./lib/utils')
+ , Templato = require('./deps/templato')
, ejs = require('./lib/template/adapters/ejs')
, createPackageTask;
var JSPAT = /\.js$/;
namespace('gen', function () {
var _writeTemplate = function (name, filename, dirname, opts) {
- var names = _getInflections(name)
+ var templato = new Templato
+ , names = _getInflections(name)
, text = fs.readFileSync(path.join(__dirname,
'templates', filename +'.ejs'), 'utf8').toString()
, templ
, filePath;
// Render with the right model name
- templ = new ejs.Template({text: text});
+ templ = new ejs.Template({text: text, templato: templato});
templ.process({data: {names: names}});
filePath = path.join('app', dirname,
names.filename[opts.inflection] + '.js');
@@ -205,7 +207,7 @@ namespace('doc', function () {
}, {async: true});
task('clobber', function () {
- var cmd = 'rm -fr ./doc/*';
+ var cmd = 'rm -fr ./doc/**';
jake.exec([cmd], function () {
console.log('Clobbered old docs.');
complete();
@@ -242,11 +244,11 @@ var p = new jake.NpmPublishTask('geddy', [
, 'Jakefile'
, 'README.md'
, 'package.json'
-, 'bin/*'
-, 'deps/*'
-, 'lib/*'
-, 'templates/*'
-, 'test/*'
+, 'bin/**'
+, 'deps/**'
+, 'lib/**'
+, 'templates/**'
+, 'test/**'
]);
// Don't create the package-tasks when being called as a generator
View
@@ -109,7 +109,7 @@ Restart Geddy, and you'll see the new route working. Hit your
new route -- for example, http://localhost:4000/snow_dogs.json,
and you should see something like this:
-{"method":"index","params":{"extension":"json"}}
+ {"method":"index","params":{"extension":"json"}}
The geddy generator utility also handles fancy pluralization
between model and controller. Specify your resource-name as a
View
@@ -30,7 +30,7 @@ usage = ''
+ '{Usage}: geddy [options]\n'
+ '\n'
+ '{Options}:\n'
- + ' -e, --environment Evironment config to use\n'
+ + ' -e, --environment Environment config to use\n'
+ ' -p, --port NUM Port number, defaults to 4000\n'
+ ' -n, --workers NUM Number of worker processes to use, defaults to 2\n'
+ ' -V/v, --version Outputs the version of geddy that you have installed\n'
View
@@ -0,0 +1,302 @@
+/*
+ * Geddy JavaScript Web development framework
+ * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+// Note: If moved remember to change utils directory
+var utils = require('../lib/utils')
+ , ejs = {};
+
+ejs.Template = function(params) {
+ params = params || {};
+
+ this.mode = null;
+ this.truncate = false;
+ this.currentLine = 1;
+ this.afterLoaded = params.afterLoaded;
+ this.source = '';
+ this.markup = undefined;
+ // If you don't want to use Fleegix.js,
+ // override getTemplateTextFromNode to use
+ // textarea node value for template text
+ this.templateText = params.text || this.getTemplateTextFromNode(params.node);
+
+ // Try to get from URL
+ if(typeof this.templateText == 'undefined') {
+ // If you don't want to use Fleegix.js,
+ // override getTemplateTextFromUrl to use
+ // files for template text
+ this.getTemplateTextFromUrl(params);
+ }
+};
+
+ejs.Template.prototype = new function() {
+ var _REGEX = /(<%%)|(%%>)|(<%=)|(<%-)|(<%#)|(<%)|(%>)|(-%>)/;
+
+ this.modes = {
+ EVAL: 'eval'
+ , ESCAPED: 'escaped'
+ , RAW: 'raw'
+ , APPEND: 'append'
+ , COMMENT: 'comment'
+ , LITERAL: 'literal'
+ };
+
+ this.getTemplateTextFromNode = function(node) {
+ // Requires the fleegix.xhr module
+ if(typeof fleegix.string == 'undefined') throw('Requires fleegix.string module.');
+ var ret;
+
+ if(node) {
+ ret = node.value;
+ ret = fleegix.string.unescapeXML(ret);
+ ret = fleegix.string.trim(ret);
+ }
+ return ret;
+ };
+
+ this.getTemplateTextFromUrl = function(params) {
+ // Requires the fleegix.xhr module
+ if(typeof fleegix.xhr == 'undefined') throw('Requires fleegix.xhr module.');
+ var self = this
+ , url = params.url
+ , noCache = params.preventCache || false;
+
+ // Found text in cache, and caching is turned on
+ if(text && !noCache) {
+ this.templateText = text;
+ }
+ // Otherwise go grab the text
+ else {
+ var callback
+ , opts;
+
+ // Callback for setting templateText and caching --
+ // used for both sync and async loading
+ callback = function (s) {
+ self.templateText = s;
+ ejs.templateTextCache[url] = s;
+
+ // Use afterLoaded hook if set
+ if(typeof self.afterLoaded == 'function') {
+ self.afterLoaded();
+ }
+ };
+
+ if(params.async) {
+ opts = {
+ url: url
+ , method: 'GET'
+ , preventCache: noCache
+ , async: true
+ , handleSuccess: callback
+ }
+ // Get templ text asynchronously, wait for
+ // loading to exec the callback
+ fleegix.xhr.send(opts);
+ } else {
+ opts = {
+ url: url
+ , method: 'GET'
+ , preventCache: noCache
+ , async: false
+ }
+ // Get the templ text inline and pass directly to
+ // the callback
+ text = fleegix.xhr.send(opts);
+ callback(text);
+ }
+ }
+ };
+
+ this.handleErr = function(e, line) {
+ var src = this.templateText.split('\n')
+ , ctxt = ''
+ , err = new Error()
+ , start = Math.max(line - 3, 0)
+ , end = Math.min(src.length, line + 3)
+ , arr = src.slice(start, end)
+ , curr;
+
+ for(var i = 0, len = arr.length; i < len; i++) {
+ curr = i + start + 1;
+ ctxt += (curr == line ? ' >> ' : ' ')
+ + curr
+ + '| '
+ + arr[i] + '\n';
+ }
+
+ err.name = e.name;
+ err.message = 'ejs:' + line + '\n' + ctxt + e.message;
+ throw err;
+ };
+
+ this.process = function(params) {
+ var self = this
+ , params = params || {}
+ , domNode = params.node
+ , src
+ , fn
+ , rethrow;
+
+ this.data = params;
+ this.source = this.source || ''; // Cache the template source for speed
+
+ if(!this.source) this.generateSource();
+
+ src = 'var __output = "", __line = 1; with (locals) { try {' +
+ this.source + '} catch(e) { rethrow(e, __line); } } return __output;';
+ fn = new Function('locals', src);
+ rethrow = function(e, line) { self.handleErr(e, line); };
+
+ this.markup = fn.call(this, geddy.mixin({
+ utils: utils
+ , rethrow: rethrow
+ }, this.data));
+
+ if(domNode) domNode.innerHTML = this.markup;
+ return this.markup;
+ };
+
+ this.generateSource = function() {
+ var matches = this.parseTemplateText()
+ , line;
+
+ if(matches) {
+ for(var i in matches) {
+ line = matches[i];
+
+ if(line) this.scanLine(line);
+ }
+ }
+ };
+
+ this.parseTemplateText = function() {
+ var str = this.templateText
+ , pat = _REGEX
+ , result = pat.exec(str)
+ , arr = []
+ , firstPos
+ , lastPos;
+
+ while(result) {
+ firstPos = result.index;
+ lastPos = pat.lastIndex;
+
+ if(firstPos !== 0) {
+ arr.push(str.substring(0, firstPos));
+ str = str.slice(firstPos);
+ }
+
+ arr.push(result[0]);
+ str = str.slice(result[0].length);
+ result = pat.exec(str);
+ }
+
+ if(str !== '') {
+ arr.push(str);
+ }
+
+ return arr;
+ };
+
+ this.scanLine = function(line) {
+ var self = this
+ , newLineCount = 0
+ , _addOutput;
+
+ _addOutput = function() {
+ if(self.truncate) line = line.replace('\n', '');
+
+ // Preserve literal slashes
+ line = line.replace(/\\/g, '\\\\');
+
+ // Convert linebreaks
+ line = line.replace(/\n/g, '\\n');
+ line = line.replace(/\r/g, '\\r');
+
+ // Escape double-quotes
+ // - this will be the delimiter during execution
+ line = line.replace(/"/g, '\\"');
+ self.source += '__output += "' + line + '";';
+ };
+
+ newLineCount = (line.split('\n').length - 1);
+
+ switch (line) {
+ case '<%':
+ this.mode = this.modes.EVAL;
+ break;
+ case '<%=':
+ this.mode = this.modes.ESCAPED;
+ break;
+ case '<%-':
+ this.mode = this.modes.RAW;
+ break;
+ case '<%#':
+ this.mode = this.modes.COMMENT;
+ break;
+ case '<%%':
+ this.mode = this.modes.LITERAL;
+ this.source += '__output += "' + line.replace('<%%', '<%') + '";';
+ break;
+ case '%>':
+ case '-%>':
+ if(this.mode == this.modes.LITERAL) _addOutput();
+
+ this.mode = null;
+ this.truncate = line.indexOf('-') == 0;
+ break;
+ default:
+ // In script mode, depends on type of tag
+ if (this.mode) {
+ switch (this.mode) {
+ // Just executing code
+ case this.modes.EVAL:
+ this.source += line;
+ break;
+ // Exec, esc, and output
+ case this.modes.ESCAPED:
+ // Add the exec'd, escaped result to the output
+ this.source += '__output += utils.string.escapeXML(' +
+ line.replace(/;\S*/, '') + ');';
+ break;
+ // Exec and output
+ case this.modes.RAW:
+ // Add the exec'd result to the output
+ this.source += '__output += ' + line + ';';
+ break;
+ case this.modes.COMMENT:
+ // Do nothing
+ break;
+ // Literal <%% mode, append as raw output
+ case this.modes.LITERAL:
+ _addOutput();
+ break;
+ }
+ }
+ // In string mode, just add the output
+ else _addOutput();
+ }
+
+ if(newLineCount) {
+ this.currentLine += newLineCount;
+ this.source += '__line = ' + this.currentLine + ';';
+ }
+ };
+};
+
+exports.Template = ejs.Template;
Oops, something went wrong.

0 comments on commit 7f414ae

Please sign in to comment.