diff --git a/Rakefile b/Rakefile index 37cb9b3..7240f8b 100644 --- a/Rakefile +++ b/Rakefile @@ -1,20 +1,18 @@ require 'rake' require 'rake/clean' -task :default => :spec +task :default => 'test:integration' -desc "Run all specs" -task :spec do - require 'rspec/core/rake_task' - RSpec::Core::RakeTask.new(:spec) do |t| - #t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""] - t.pattern = 'spec/*_spec.rb' +namespace :test do + desc "Run all integration tests" + task :integration do + require File.expand_path('../test/integration', __FILE__) end -end -desc "Run all unit tests" -task :test do - exec "vows test/*_test.js" + desc "Run all unit tests" + task :unit do + require File.expand_path('../test/unit', __FILE__) + end end # Creates a task that uses the various template wrappers to make a wrapped diff --git a/mustache.js b/mustache.js index 641cebd..7b34bbb 100644 --- a/mustache.js +++ b/mustache.js @@ -9,12 +9,18 @@ var Mustache = (typeof module !== "undefined" && module.exports) || {}; exports.name = "mustache.js"; exports.version = "0.5.0-dev"; exports.tags = ["{{", "}}"]; + exports.parse = parse; + exports.clearCache = clearCache; exports.compile = compile; + exports.compilePartial = compilePartial; exports.render = render; - exports.clearCache = clearCache; - // This is here for backwards compatibility with 0.4.x. + exports.Scanner = Scanner; + exports.Context = Context; + exports.Renderer = Renderer; + + // // This is here for backwards compatibility with 0.4.x. exports.to_html = function (template, view, partials, send) { var result = render(template, view, partials); @@ -25,63 +31,30 @@ var Mustache = (typeof module !== "undefined" && module.exports) || {}; } }; - var _toString = Object.prototype.toString; - var _isArray = Array.isArray; - var _forEach = Array.prototype.forEach; - var _trim = String.prototype.trim; - - var isArray; - if (_isArray) { - isArray = _isArray; - } else { - isArray = function (obj) { - return _toString.call(obj) === "[object Array]"; - }; - } - - var forEach; - if (_forEach) { - forEach = function (obj, callback, scope) { - return _forEach.call(obj, callback, scope); - }; - } else { - forEach = function (obj, callback, scope) { - for (var i = 0, len = obj.length; i < len; ++i) { - callback.call(scope, obj[i], i, obj); - } - }; - } - - var spaceRe = /^\s*$/; + var whiteRe = /\s*/; + var spaceRe = /\s+/; + var nonSpaceRe = /\S/; + var eqRe = /\s*=/; + var curlyRe = /\s*\}/; + var tagRe = /#|\^|\/|>|\{|&|=|!/; function isWhitespace(string) { - return spaceRe.test(string); + return !nonSpaceRe.test(string); } - var trim; - if (_trim) { - trim = function (string) { - return string == null ? "" : _trim.call(string); - }; - } else { - var trimLeft, trimRight; + var isArray = Array.isArray || function (obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; - if (isWhitespace("\xA0")) { - trimLeft = /^\s+/; - trimRight = /\s+$/; - } else { - // IE doesn't match non-breaking spaces with \s, thanks jQuery. - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; - } + var quote = (typeof JSON !== "undefined" && JSON.stringify) || function (string) { + return '"' + String(string).replace(/(^|[^\\])"/g, '\\"') + '"'; + }; - trim = function (string) { - return string == null ? "" : - String(string).replace(trimLeft, "").replace(trimRight, ""); - }; + function escapeRe(string) { + return string.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); } - var escapeMap = { + var entityMap = { "&": "&", "<": "<", ">": ">", @@ -89,448 +62,519 @@ var Mustache = (typeof module !== "undefined" && module.exports) || {}; "'": ''' }; - function escapeHTML(string) { + function escapeHtml(string) { return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) { - return escapeMap[s] || s; + return entityMap[s]; }); } + // Export these utility functions. + exports.isWhitespace = isWhitespace; + exports.isArray = isArray; + exports.quote = quote; + exports.escapeRe = escapeRe; + exports.escapeHtml = escapeHtml; + + function Scanner(string) { + this.string = string; + this.tail = string; + this.pos = 0; + } + /** - * Adds the `template`, `line`, and `file` properties to the given error - * object and alters the message to provide more useful debugging information. + * Returns `true` if the tail is empty (end of string). */ - function debug(e, template, line, file) { - file = file || "