Created
November 12, 2014 00:18
-
-
Save shinypb/b17a7fb7762a764102ce to your computer and use it in GitHub Desktop.
hogan-3.0.1.js → ES6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/thirdparties/hogan-3.0.1.js b/thirdparties/hogan-3.0.1.js | |
index ebdcf43..a184136 100644 | |
--- a/thirdparties/hogan-3.0.1.js | |
+++ b/thirdparties/hogan-3.0.1.js | |
@@ -15,737 +15,729 @@ | |
-var Hogan = {}; | |
- | |
-(function (Hogan) { | |
- Hogan.Template = function (codeObj, text, compiler, options) { | |
- codeObj = codeObj || {}; | |
- this.r = codeObj.code || this.r; | |
- this.c = compiler; | |
- this.options = options || {}; | |
- this.text = text || ''; | |
- this.partials = codeObj.partials || {}; | |
- this.subs = codeObj.subs || {}; | |
- this.buf = ''; | |
- } | |
- | |
- Hogan.Template.prototype = { | |
- // render: replaced by generated code. | |
- r: function (context, partials, indent) { return ''; }, | |
- | |
- // variable escaping | |
- v: hoganEscape, | |
- | |
- // triple stache | |
- t: coerceToString, | |
- | |
- render: function render(context, partials, indent) { | |
- return this.ri([context], partials || {}, indent); | |
- }, | |
- | |
- // render internal -- a hook for overrides that catches partials too | |
- ri: function (context, partials, indent) { | |
- return this.r(context, partials, indent); | |
- }, | |
- | |
- // ensurePartial | |
- ep: function(symbol, partials) { | |
- var partial = this.partials[symbol]; | |
+export var Hogan = {}; | |
+ | |
+Hogan.Template = function (codeObj, text, compiler, options) { | |
+ codeObj = codeObj || {}; | |
+ this.r = codeObj.code || this.r; | |
+ this.c = compiler; | |
+ this.options = options || {}; | |
+ this.text = text || ''; | |
+ this.partials = codeObj.partials || {}; | |
+ this.subs = codeObj.subs || {}; | |
+ this.buf = ''; | |
+} | |
+ | |
+Hogan.Template.prototype = { | |
+ // render: replaced by generated code. | |
+ r: function (context, partials, indent) { return ''; }, | |
+ | |
+ // variable escaping | |
+ v: hoganEscape, | |
+ | |
+ // triple stache | |
+ t: coerceToString, | |
+ | |
+ render: function render(context, partials, indent) { | |
+ return this.ri([context], partials || {}, indent); | |
+ }, | |
+ | |
+ // render internal -- a hook for overrides that catches partials too | |
+ ri: function (context, partials, indent) { | |
+ return this.r(context, partials, indent); | |
+ }, | |
+ | |
+ // ensurePartial | |
+ ep: function(symbol, partials) { | |
+ var partial = this.partials[symbol]; | |
+ | |
+ // check to see that if we've instantiated this partial before | |
+ var template = partials[partial.name]; | |
+ if (partial.instance && partial.base == template) { | |
+ return partial.instance; | |
+ } | |
- // check to see that if we've instantiated this partial before | |
- var template = partials[partial.name]; | |
- if (partial.instance && partial.base == template) { | |
- return partial.instance; | |
- } | |
- | |
- if (typeof template == 'string') { | |
- if (!this.c) { | |
- throw new Error("No compiler available."); | |
- } | |
- template = this.c.compile(template, this.options); | |
+ if (typeof template == 'string') { | |
+ if (!this.c) { | |
+ throw new Error("No compiler available."); | |
} | |
+ template = this.c.compile(template, this.options); | |
+ } | |
- if (!template) { | |
- return null; | |
- } | |
+ if (!template) { | |
+ return null; | |
+ } | |
- // We use this to check whether the partials dictionary has changed | |
- this.partials[symbol].base = template; | |
+ // We use this to check whether the partials dictionary has changed | |
+ this.partials[symbol].base = template; | |
- if (partial.subs) { | |
- // Make sure we consider parent template now | |
- if (!partials.stackText) partials.stackText = {}; | |
- for (key in partial.subs) { | |
- if (!partials.stackText[key]) { | |
- partials.stackText[key] = (this.activeSub !== undefined && partials.stackText[this.activeSub]) ? partials.stackText[this.activeSub] : this.text; | |
- } | |
+ if (partial.subs) { | |
+ // Make sure we consider parent template now | |
+ if (!partials.stackText) partials.stackText = {}; | |
+ for (key in partial.subs) { | |
+ if (!partials.stackText[key]) { | |
+ partials.stackText[key] = (this.activeSub !== undefined && partials.stackText[this.activeSub]) ? partials.stackText[this.activeSub] : this.text; | |
} | |
- template = createSpecializedPartial(template, partial.subs, partial.partials, | |
- this.stackSubs, this.stackPartials, partials.stackText); | |
- } | |
- this.partials[symbol].instance = template; | |
- | |
- return template; | |
- }, | |
- | |
- // tries to find a partial in the current scope and render it | |
- rp: function(symbol, context, partials, indent) { | |
- var partial = this.ep(symbol, partials); | |
- if (!partial) { | |
- return ''; | |
} | |
+ template = createSpecializedPartial(template, partial.subs, partial.partials, | |
+ this.stackSubs, this.stackPartials, partials.stackText); | |
+ } | |
+ this.partials[symbol].instance = template; | |
- return partial.ri(context, partials, indent); | |
- }, | |
+ return template; | |
+ }, | |
- // render a section | |
- rs: function(context, partials, section) { | |
- var tail = context[context.length - 1]; | |
+ // tries to find a partial in the current scope and render it | |
+ rp: function(symbol, context, partials, indent) { | |
+ var partial = this.ep(symbol, partials); | |
+ if (!partial) { | |
+ return ''; | |
+ } | |
- if (!isArray(tail)) { | |
- section(context, partials, this); | |
- return; | |
- } | |
+ return partial.ri(context, partials, indent); | |
+ }, | |
- for (var i = 0; i < tail.length; i++) { | |
- context.push(tail[i]); | |
- section(context, partials, this); | |
- context.pop(); | |
- } | |
- }, | |
+ // render a section | |
+ rs: function(context, partials, section) { | |
+ var tail = context[context.length - 1]; | |
- // maybe start a section | |
- s: function(val, ctx, partials, inverted, start, end, tags) { | |
- var pass; | |
+ if (!isArray(tail)) { | |
+ section(context, partials, this); | |
+ return; | |
+ } | |
- if (isArray(val) && val.length === 0) { | |
- return false; | |
- } | |
+ for (var i = 0; i < tail.length; i++) { | |
+ context.push(tail[i]); | |
+ section(context, partials, this); | |
+ context.pop(); | |
+ } | |
+ }, | |
- if (typeof val == 'function') { | |
- val = this.ms(val, ctx, partials, inverted, start, end, tags); | |
- } | |
+ // maybe start a section | |
+ s: function(val, ctx, partials, inverted, start, end, tags) { | |
+ var pass; | |
- pass = !!val; | |
+ if (isArray(val) && val.length === 0) { | |
+ return false; | |
+ } | |
- if (!inverted && pass && ctx) { | |
- ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]); | |
- } | |
+ if (typeof val == 'function') { | |
+ val = this.ms(val, ctx, partials, inverted, start, end, tags); | |
+ } | |
- return pass; | |
- }, | |
+ pass = !!val; | |
- // find values with dotted names | |
- d: function(key, ctx, partials, returnFound) { | |
- var found, | |
- names = key.split('.'), | |
- val = this.f(names[0], ctx, partials, returnFound), | |
- doModelGet = this.options.modelGet, | |
- cx = null; | |
+ if (!inverted && pass && ctx) { | |
+ ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]); | |
+ } | |
- if (key === '.' && isArray(ctx[ctx.length - 2])) { | |
- val = ctx[ctx.length - 1]; | |
- } else { | |
- for (var i = 1; i < names.length; i++) { | |
- found = findInScope(names[i], val, doModelGet); | |
- if (found != null) { | |
- cx = val; | |
- val = found; | |
- } else { | |
- val = ''; | |
- } | |
+ return pass; | |
+ }, | |
+ | |
+ // find values with dotted names | |
+ d: function(key, ctx, partials, returnFound) { | |
+ var found, | |
+ names = key.split('.'), | |
+ val = this.f(names[0], ctx, partials, returnFound), | |
+ doModelGet = this.options.modelGet, | |
+ cx = null; | |
+ | |
+ if (key === '.' && isArray(ctx[ctx.length - 2])) { | |
+ val = ctx[ctx.length - 1]; | |
+ } else { | |
+ for (var i = 1; i < names.length; i++) { | |
+ found = findInScope(names[i], val, doModelGet); | |
+ if (found != null) { | |
+ cx = val; | |
+ val = found; | |
+ } else { | |
+ val = ''; | |
} | |
} | |
+ } | |
- if (returnFound && !val) { | |
- return false; | |
- } | |
+ if (returnFound && !val) { | |
+ return false; | |
+ } | |
- if (!returnFound && typeof val == 'function') { | |
- ctx.push(cx); | |
- val = this.mv(val, ctx, partials); | |
- ctx.pop(); | |
- } | |
+ if (!returnFound && typeof val == 'function') { | |
+ ctx.push(cx); | |
+ val = this.mv(val, ctx, partials); | |
+ ctx.pop(); | |
+ } | |
- return val; | |
- }, | |
- | |
- // find values with normal names | |
- f: function(key, ctx, partials, returnFound) { | |
- var val = false, | |
- v = null, | |
- found = false, | |
- doModelGet = this.options.modelGet; | |
- | |
- for (var i = ctx.length - 1; i >= 0; i--) { | |
- v = ctx[i]; | |
- val = findInScope(key, v, doModelGet); | |
- if (val != null) { | |
- found = true; | |
- break; | |
- } | |
+ return val; | |
+ }, | |
+ | |
+ // find values with normal names | |
+ f: function(key, ctx, partials, returnFound) { | |
+ var val = false, | |
+ v = null, | |
+ found = false, | |
+ doModelGet = this.options.modelGet; | |
+ | |
+ for (var i = ctx.length - 1; i >= 0; i--) { | |
+ v = ctx[i]; | |
+ val = findInScope(key, v, doModelGet); | |
+ if (val != null) { | |
+ found = true; | |
+ break; | |
} | |
+ } | |
- if (!found) { | |
- return (returnFound) ? false : ""; | |
- } | |
+ if (!found) { | |
+ return (returnFound) ? false : ""; | |
+ } | |
- if (!returnFound && typeof val == 'function') { | |
- val = this.mv(val, ctx, partials); | |
- } | |
+ if (!returnFound && typeof val == 'function') { | |
+ val = this.mv(val, ctx, partials); | |
+ } | |
- return val; | |
- }, | |
+ return val; | |
+ }, | |
- // higher order templates | |
- ls: function(func, cx, partials, text, tags) { | |
- var oldTags = this.options.delimiters; | |
+ // higher order templates | |
+ ls: function(func, cx, partials, text, tags) { | |
+ var oldTags = this.options.delimiters; | |
- this.options.delimiters = tags; | |
- this.b(this.ct(coerceToString(func.call(cx, text)), cx, partials)); | |
- this.options.delimiters = oldTags; | |
+ this.options.delimiters = tags; | |
+ this.b(this.ct(coerceToString(func.call(cx, text)), cx, partials)); | |
+ this.options.delimiters = oldTags; | |
- return false; | |
- }, | |
+ return false; | |
+ }, | |
- // compile text | |
- ct: function(text, cx, partials) { | |
- if (this.options.disableLambda) { | |
- throw new Error('Lambda features disabled.'); | |
- } | |
- return this.c.compile(text, this.options).render(cx, partials); | |
- }, | |
+ // compile text | |
+ ct: function(text, cx, partials) { | |
+ if (this.options.disableLambda) { | |
+ throw new Error('Lambda features disabled.'); | |
+ } | |
+ return this.c.compile(text, this.options).render(cx, partials); | |
+ }, | |
- // template result buffering | |
- b: function(s) { this.buf += s; }, | |
+ // template result buffering | |
+ b: function(s) { this.buf += s; }, | |
- fl: function() { var r = this.buf; this.buf = ''; return r; }, | |
+ fl: function() { var r = this.buf; this.buf = ''; return r; }, | |
- // method replace section | |
- ms: function(func, ctx, partials, inverted, start, end, tags) { | |
- var textSource, | |
- cx = ctx[ctx.length - 1], | |
- result = func.call(cx); | |
+ // method replace section | |
+ ms: function(func, ctx, partials, inverted, start, end, tags) { | |
+ var textSource, | |
+ cx = ctx[ctx.length - 1], | |
+ result = func.call(cx); | |
- if (typeof result == 'function') { | |
- if (inverted) { | |
- return true; | |
- } else { | |
- textSource = (this.activeSub && this.subsText && this.subsText[this.activeSub]) ? this.subsText[this.activeSub] : this.text; | |
- return this.ls(result, cx, partials, textSource.substring(start, end), tags); | |
- } | |
+ if (typeof result == 'function') { | |
+ if (inverted) { | |
+ return true; | |
+ } else { | |
+ textSource = (this.activeSub && this.subsText && this.subsText[this.activeSub]) ? this.subsText[this.activeSub] : this.text; | |
+ return this.ls(result, cx, partials, textSource.substring(start, end), tags); | |
} | |
+ } | |
- return result; | |
- }, | |
+ return result; | |
+ }, | |
- // method replace variable | |
- mv: function(func, ctx, partials) { | |
- var cx = ctx[ctx.length - 1]; | |
- var result = func.call(cx); | |
+ // method replace variable | |
+ mv: function(func, ctx, partials) { | |
+ var cx = ctx[ctx.length - 1]; | |
+ var result = func.call(cx); | |
- if (typeof result == 'function') { | |
- return this.ct(coerceToString(result.call(cx)), cx, partials); | |
- } | |
+ if (typeof result == 'function') { | |
+ return this.ct(coerceToString(result.call(cx)), cx, partials); | |
+ } | |
- return result; | |
- }, | |
+ return result; | |
+ }, | |
- sub: function(name, context, partials, indent) { | |
- var f = this.subs[name]; | |
- if (f) { | |
- this.activeSub = name; | |
- f(context, partials, this, indent); | |
- this.activeSub = false; | |
- } | |
+ sub: function(name, context, partials, indent) { | |
+ var f = this.subs[name]; | |
+ if (f) { | |
+ this.activeSub = name; | |
+ f(context, partials, this, indent); | |
+ this.activeSub = false; | |
} | |
+ } | |
- }; | |
+}; | |
- //Find a key in an object | |
- function findInScope(key, scope, doModelGet) { | |
- var val, checkVal; | |
+//Find a key in an object | |
+function findInScope(key, scope, doModelGet) { | |
+ var val, checkVal; | |
- if (scope && typeof scope == 'object') { | |
+ if (scope && typeof scope == 'object') { | |
- if (scope[key] != null) { | |
- val = scope[key]; | |
+ if (scope[key] != null) { | |
+ val = scope[key]; | |
- // try lookup with get for backbone or similar model data | |
- } else if (doModelGet && scope.get && typeof scope.get == 'function') { | |
- val = scope.get(key); | |
- } | |
+ // try lookup with get for backbone or similar model data | |
+ } else if (doModelGet && scope.get && typeof scope.get == 'function') { | |
+ val = scope.get(key); | |
} | |
- | |
- return val; | |
} | |
- function createSpecializedPartial(instance, subs, partials, stackSubs, stackPartials, stackText) { | |
- function PartialTemplate() {}; | |
- PartialTemplate.prototype = instance; | |
- function Substitutions() {}; | |
- Substitutions.prototype = instance.subs; | |
- var key; | |
- var partial = new PartialTemplate(); | |
- partial.subs = new Substitutions(); | |
- partial.subsText = {}; //hehe. substext. | |
- partial.buf = ''; | |
- | |
- stackSubs = stackSubs || {}; | |
- partial.stackSubs = stackSubs; | |
- partial.subsText = stackText; | |
- for (key in subs) { | |
- if (!stackSubs[key]) stackSubs[key] = subs[key]; | |
- } | |
- for (key in stackSubs) { | |
- partial.subs[key] = stackSubs[key]; | |
- } | |
- | |
- stackPartials = stackPartials || {}; | |
- partial.stackPartials = stackPartials; | |
- for (key in partials) { | |
- if (!stackPartials[key]) stackPartials[key] = partials[key]; | |
- } | |
- for (key in stackPartials) { | |
- partial.partials[key] = stackPartials[key]; | |
- } | |
- | |
- return partial; | |
+ return val; | |
+} | |
+ | |
+function createSpecializedPartial(instance, subs, partials, stackSubs, stackPartials, stackText) { | |
+ function PartialTemplate() {}; | |
+ PartialTemplate.prototype = instance; | |
+ function Substitutions() {}; | |
+ Substitutions.prototype = instance.subs; | |
+ var key; | |
+ var partial = new PartialTemplate(); | |
+ partial.subs = new Substitutions(); | |
+ partial.subsText = {}; //hehe. substext. | |
+ partial.buf = ''; | |
+ | |
+ stackSubs = stackSubs || {}; | |
+ partial.stackSubs = stackSubs; | |
+ partial.subsText = stackText; | |
+ for (key in subs) { | |
+ if (!stackSubs[key]) stackSubs[key] = subs[key]; | |
} | |
- | |
- var rAmp = /&/g, | |
- rLt = /</g, | |
- rGt = />/g, | |
- rApos = /\'/g, | |
- rQuot = /\"/g, | |
- hChars = /[&<>\"\']/; | |
- | |
- function coerceToString(val) { | |
- return String((val === null || val === undefined) ? '' : val); | |
+ for (key in stackSubs) { | |
+ partial.subs[key] = stackSubs[key]; | |
} | |
- function hoganEscape(str) { | |
- str = coerceToString(str); | |
- return hChars.test(str) ? | |
- str | |
- .replace(rAmp, '&') | |
- .replace(rLt, '<') | |
- .replace(rGt, '>') | |
- .replace(rApos, ''') | |
- .replace(rQuot, '"') : | |
- str; | |
+ stackPartials = stackPartials || {}; | |
+ partial.stackPartials = stackPartials; | |
+ for (key in partials) { | |
+ if (!stackPartials[key]) stackPartials[key] = partials[key]; | |
+ } | |
+ for (key in stackPartials) { | |
+ partial.partials[key] = stackPartials[key]; | |
} | |
- var isArray = Array.isArray || function(a) { | |
- return Object.prototype.toString.call(a) === '[object Array]'; | |
- }; | |
- | |
-})(typeof exports !== 'undefined' ? exports : Hogan); | |
- | |
- | |
- | |
-(function (Hogan) { | |
- // Setup regex assignments | |
- // remove whitespace according to Mustache spec | |
- var rIsWhitespace = /\S/, | |
- rQuot = /\"/g, | |
- rNewline = /\n/g, | |
- rCr = /\r/g, | |
- rSlash = /\\/g; | |
- | |
- Hogan.tags = { | |
- '#': 1, '^': 2, '<': 3, '$': 4, | |
- '/': 5, '!': 6, '>': 7, '=': 8, '_v': 9, | |
- '{': 10, '&': 11, '_t': 12 | |
- }; | |
- | |
- Hogan.scan = function scan(text, delimiters) { | |
- var len = text.length, | |
- IN_TEXT = 0, | |
- IN_TAG_TYPE = 1, | |
- IN_TAG = 2, | |
- state = IN_TEXT, | |
- tagType = null, | |
- tag = null, | |
- buf = '', | |
- tokens = [], | |
- seenTag = false, | |
- i = 0, | |
- lineStart = 0, | |
- otag = '{{', | |
- ctag = '}}'; | |
- | |
- function addBuf() { | |
- if (buf.length > 0) { | |
- tokens.push({tag: '_t', text: new String(buf)}); | |
- buf = ''; | |
- } | |
+ return partial; | |
+} | |
+ | |
+var rAmp = /&/g, | |
+ rLt = /</g, | |
+ rGt = />/g, | |
+ rApos = /\'/g, | |
+ rQuot = /\"/g, | |
+ hChars = /[&<>\"\']/; | |
+ | |
+function coerceToString(val) { | |
+ return String((val === null || val === undefined) ? '' : val); | |
+} | |
+ | |
+function hoganEscape(str) { | |
+ str = coerceToString(str); | |
+ return hChars.test(str) ? | |
+ str | |
+ .replace(rAmp, '&') | |
+ .replace(rLt, '<') | |
+ .replace(rGt, '>') | |
+ .replace(rApos, ''') | |
+ .replace(rQuot, '"') : | |
+ str; | |
+} | |
+ | |
+var isArray = Array.isArray || function(a) { | |
+ return Object.prototype.toString.call(a) === '[object Array]'; | |
+}; | |
+ | |
+// Setup regex assignments | |
+// remove whitespace according to Mustache spec | |
+var rIsWhitespace = /\S/, | |
+ rQuot = /\"/g, | |
+ rNewline = /\n/g, | |
+ rCr = /\r/g, | |
+ rSlash = /\\/g; | |
+ | |
+Hogan.tags = { | |
+ '#': 1, '^': 2, '<': 3, '$': 4, | |
+ '/': 5, '!': 6, '>': 7, '=': 8, '_v': 9, | |
+ '{': 10, '&': 11, '_t': 12 | |
+}; | |
+ | |
+Hogan.scan = function scan(text, delimiters) { | |
+ var len = text.length, | |
+ IN_TEXT = 0, | |
+ IN_TAG_TYPE = 1, | |
+ IN_TAG = 2, | |
+ state = IN_TEXT, | |
+ tagType = null, | |
+ tag = null, | |
+ buf = '', | |
+ tokens = [], | |
+ seenTag = false, | |
+ i = 0, | |
+ lineStart = 0, | |
+ otag = '{{', | |
+ ctag = '}}'; | |
+ | |
+ function addBuf() { | |
+ if (buf.length > 0) { | |
+ tokens.push({tag: '_t', text: new String(buf)}); | |
+ buf = ''; | |
} | |
+ } | |
- function lineIsWhitespace() { | |
- var isAllWhitespace = true; | |
- for (var j = lineStart; j < tokens.length; j++) { | |
- isAllWhitespace = | |
- (Hogan.tags[tokens[j].tag] < Hogan.tags['_v']) || | |
- (tokens[j].tag == '_t' && tokens[j].text.match(rIsWhitespace) === null); | |
- if (!isAllWhitespace) { | |
- return false; | |
- } | |
+ function lineIsWhitespace() { | |
+ var isAllWhitespace = true; | |
+ for (var j = lineStart; j < tokens.length; j++) { | |
+ isAllWhitespace = | |
+ (Hogan.tags[tokens[j].tag] < Hogan.tags['_v']) || | |
+ (tokens[j].tag == '_t' && tokens[j].text.match(rIsWhitespace) === null); | |
+ if (!isAllWhitespace) { | |
+ return false; | |
} | |
- | |
- return isAllWhitespace; | |
} | |
- function filterLine(haveSeenTag, noNewLine) { | |
- addBuf(); | |
+ return isAllWhitespace; | |
+ } | |
+ | |
+ function filterLine(haveSeenTag, noNewLine) { | |
+ addBuf(); | |
- if (haveSeenTag && lineIsWhitespace()) { | |
- for (var j = lineStart, next; j < tokens.length; j++) { | |
- if (tokens[j].text) { | |
- if ((next = tokens[j+1]) && next.tag == '>') { | |
- // set indent to token value | |
- next.indent = tokens[j].text.toString() | |
- } | |
- tokens.splice(j, 1); | |
+ if (haveSeenTag && lineIsWhitespace()) { | |
+ for (var j = lineStart, next; j < tokens.length; j++) { | |
+ if (tokens[j].text) { | |
+ if ((next = tokens[j+1]) && next.tag == '>') { | |
+ // set indent to token value | |
+ next.indent = tokens[j].text.toString() | |
} | |
+ tokens.splice(j, 1); | |
} | |
- } else if (!noNewLine) { | |
- tokens.push({tag:'\n'}); | |
} | |
- | |
- seenTag = false; | |
- lineStart = tokens.length; | |
+ } else if (!noNewLine) { | |
+ tokens.push({tag:'\n'}); | |
} | |
- function changeDelimiters(text, index) { | |
- var close = '=' + ctag, | |
- closeIndex = text.indexOf(close, index), | |
- delimiters = trim( | |
- text.substring(text.indexOf('=', index) + 1, closeIndex) | |
- ).split(' '); | |
+ seenTag = false; | |
+ lineStart = tokens.length; | |
+ } | |
- otag = delimiters[0]; | |
- ctag = delimiters[delimiters.length - 1]; | |
+ function changeDelimiters(text, index) { | |
+ var close = '=' + ctag, | |
+ closeIndex = text.indexOf(close, index), | |
+ delimiters = trim( | |
+ text.substring(text.indexOf('=', index) + 1, closeIndex) | |
+ ).split(' '); | |
- return closeIndex + close.length - 1; | |
- } | |
+ otag = delimiters[0]; | |
+ ctag = delimiters[delimiters.length - 1]; | |
- if (delimiters) { | |
- delimiters = delimiters.split(' '); | |
- otag = delimiters[0]; | |
- ctag = delimiters[1]; | |
- } | |
+ return closeIndex + close.length - 1; | |
+ } | |
- for (i = 0; i < len; i++) { | |
- if (state == IN_TEXT) { | |
- if (tagChange(otag, text, i)) { | |
- --i; | |
- addBuf(); | |
- state = IN_TAG_TYPE; | |
+ if (delimiters) { | |
+ delimiters = delimiters.split(' '); | |
+ otag = delimiters[0]; | |
+ ctag = delimiters[1]; | |
+ } | |
+ | |
+ for (i = 0; i < len; i++) { | |
+ if (state == IN_TEXT) { | |
+ if (tagChange(otag, text, i)) { | |
+ --i; | |
+ addBuf(); | |
+ state = IN_TAG_TYPE; | |
+ } else { | |
+ if (text.charAt(i) == '\n') { | |
+ filterLine(seenTag); | |
} else { | |
- if (text.charAt(i) == '\n') { | |
- filterLine(seenTag); | |
- } else { | |
- buf += text.charAt(i); | |
- } | |
+ buf += text.charAt(i); | |
} | |
- } else if (state == IN_TAG_TYPE) { | |
- i += otag.length - 1; | |
- tag = Hogan.tags[text.charAt(i + 1)]; | |
- tagType = tag ? text.charAt(i + 1) : '_v'; | |
- if (tagType == '=') { | |
- i = changeDelimiters(text, i); | |
- state = IN_TEXT; | |
- } else { | |
- if (tag) { | |
+ } | |
+ } else if (state == IN_TAG_TYPE) { | |
+ i += otag.length - 1; | |
+ tag = Hogan.tags[text.charAt(i + 1)]; | |
+ tagType = tag ? text.charAt(i + 1) : '_v'; | |
+ if (tagType == '=') { | |
+ i = changeDelimiters(text, i); | |
+ state = IN_TEXT; | |
+ } else { | |
+ if (tag) { | |
+ i++; | |
+ } | |
+ state = IN_TAG; | |
+ } | |
+ seenTag = i; | |
+ } else { | |
+ if (tagChange(ctag, text, i)) { | |
+ tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag, | |
+ i: (tagType == '/') ? seenTag - otag.length : i + ctag.length}); | |
+ buf = ''; | |
+ i += ctag.length - 1; | |
+ state = IN_TEXT; | |
+ if (tagType == '{') { | |
+ if (ctag == '}}') { | |
i++; | |
+ } else { | |
+ cleanTripleStache(tokens[tokens.length - 1]); | |
} | |
- state = IN_TAG; | |
} | |
- seenTag = i; | |
} else { | |
- if (tagChange(ctag, text, i)) { | |
- tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag, | |
- i: (tagType == '/') ? seenTag - otag.length : i + ctag.length}); | |
- buf = ''; | |
- i += ctag.length - 1; | |
- state = IN_TEXT; | |
- if (tagType == '{') { | |
- if (ctag == '}}') { | |
- i++; | |
- } else { | |
- cleanTripleStache(tokens[tokens.length - 1]); | |
- } | |
- } | |
- } else { | |
- buf += text.charAt(i); | |
- } | |
+ buf += text.charAt(i); | |
} | |
} | |
+ } | |
+ | |
+ filterLine(seenTag, true); | |
- filterLine(seenTag, true); | |
+ return tokens; | |
+} | |
- return tokens; | |
+function cleanTripleStache(token) { | |
+ if (token.n.substr(token.n.length - 1) === '}') { | |
+ token.n = token.n.substring(0, token.n.length - 1); | |
} | |
+} | |
- function cleanTripleStache(token) { | |
- if (token.n.substr(token.n.length - 1) === '}') { | |
- token.n = token.n.substring(0, token.n.length - 1); | |
- } | |
+function trim(s) { | |
+ if (s.trim) { | |
+ return s.trim(); | |
} | |
- function trim(s) { | |
- if (s.trim) { | |
- return s.trim(); | |
- } | |
+ return s.replace(/^\s*|\s*$/g, ''); | |
+} | |
- return s.replace(/^\s*|\s*$/g, ''); | |
+function tagChange(tag, text, index) { | |
+ if (text.charAt(index) != tag.charAt(0)) { | |
+ return false; | |
} | |
- function tagChange(tag, text, index) { | |
- if (text.charAt(index) != tag.charAt(0)) { | |
+ for (var i = 1, l = tag.length; i < l; i++) { | |
+ if (text.charAt(index + i) != tag.charAt(i)) { | |
return false; | |
} | |
- | |
- for (var i = 1, l = tag.length; i < l; i++) { | |
- if (text.charAt(index + i) != tag.charAt(i)) { | |
- return false; | |
- } | |
- } | |
- | |
- return true; | |
} | |
- // the tags allowed inside super templates | |
- var allowedInSuper = {'_t': true, '\n': true, '$': true, '/': true}; | |
+ return true; | |
+} | |
- function buildTree(tokens, kind, stack, customTags) { | |
- var instructions = [], | |
- opener = null, | |
- tail = null, | |
- token = null; | |
+// the tags allowed inside super templates | |
+var allowedInSuper = {'_t': true, '\n': true, '$': true, '/': true}; | |
- tail = stack[stack.length - 1]; | |
+function buildTree(tokens, kind, stack, customTags) { | |
+ var instructions = [], | |
+ opener = null, | |
+ tail = null, | |
+ token = null; | |
- while (tokens.length > 0) { | |
- token = tokens.shift(); | |
- | |
- if (tail && tail.tag == '<' && !(token.tag in allowedInSuper)) { | |
- throw new Error('Illegal content in < super tag.'); | |
- } | |
+ tail = stack[stack.length - 1]; | |
- if (Hogan.tags[token.tag] <= Hogan.tags['$'] || isOpener(token, customTags)) { | |
- stack.push(token); | |
- token.nodes = buildTree(tokens, token.tag, stack, customTags); | |
- } else if (token.tag == '/') { | |
- if (stack.length === 0) { | |
- throw new Error('Closing tag without opener: /' + token.n); | |
- } | |
- opener = stack.pop(); | |
- if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) { | |
- throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n); | |
- } | |
- opener.end = token.i; | |
- return instructions; | |
- } else if (token.tag == '\n') { | |
- token.last = (tokens.length == 0) || (tokens[0].tag == '\n'); | |
- } | |
+ while (tokens.length > 0) { | |
+ token = tokens.shift(); | |
- instructions.push(token); | |
+ if (tail && tail.tag == '<' && !(token.tag in allowedInSuper)) { | |
+ throw new Error('Illegal content in < super tag.'); | |
} | |
- if (stack.length > 0) { | |
- throw new Error('missing closing tag: ' + stack.pop().n); | |
+ if (Hogan.tags[token.tag] <= Hogan.tags['$'] || isOpener(token, customTags)) { | |
+ stack.push(token); | |
+ token.nodes = buildTree(tokens, token.tag, stack, customTags); | |
+ } else if (token.tag == '/') { | |
+ if (stack.length === 0) { | |
+ throw new Error('Closing tag without opener: /' + token.n); | |
+ } | |
+ opener = stack.pop(); | |
+ if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) { | |
+ throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n); | |
+ } | |
+ opener.end = token.i; | |
+ return instructions; | |
+ } else if (token.tag == '\n') { | |
+ token.last = (tokens.length == 0) || (tokens[0].tag == '\n'); | |
} | |
- return instructions; | |
+ instructions.push(token); | |
} | |
- function isOpener(token, tags) { | |
- for (var i = 0, l = tags.length; i < l; i++) { | |
- if (tags[i].o == token.n) { | |
- token.tag = '#'; | |
- return true; | |
- } | |
- } | |
+ if (stack.length > 0) { | |
+ throw new Error('missing closing tag: ' + stack.pop().n); | |
} | |
- function isCloser(close, open, tags) { | |
- for (var i = 0, l = tags.length; i < l; i++) { | |
- if (tags[i].c == close && tags[i].o == open) { | |
- return true; | |
- } | |
+ return instructions; | |
+} | |
+ | |
+function isOpener(token, tags) { | |
+ for (var i = 0, l = tags.length; i < l; i++) { | |
+ if (tags[i].o == token.n) { | |
+ token.tag = '#'; | |
+ return true; | |
} | |
} | |
+} | |
- function stringifySubstitutions(obj) { | |
- var items = []; | |
- for (var key in obj) { | |
- items.push('"' + esc(key) + '": function(c,p,t,i) {' + obj[key] + '}'); | |
+function isCloser(close, open, tags) { | |
+ for (var i = 0, l = tags.length; i < l; i++) { | |
+ if (tags[i].c == close && tags[i].o == open) { | |
+ return true; | |
} | |
- return "{ " + items.join(",") + " }"; | |
} | |
+} | |
- function stringifyPartials(codeObj) { | |
- var partials = []; | |
- for (var key in codeObj.partials) { | |
- partials.push('"' + esc(key) + '":{name:"' + esc(codeObj.partials[key].name) + '", ' + stringifyPartials(codeObj.partials[key]) + "}"); | |
- } | |
- return "partials: {" + partials.join(",") + "}, subs: " + stringifySubstitutions(codeObj.subs); | |
+function stringifySubstitutions(obj) { | |
+ var items = []; | |
+ for (var key in obj) { | |
+ items.push('"' + esc(key) + '": function(c,p,t,i) {' + obj[key] + '}'); | |
} | |
+ return "{ " + items.join(",") + " }"; | |
+} | |
- Hogan.stringify = function(codeObj, text, options) { | |
- return "{code: function (c,p,i) { " + Hogan.wrapMain(codeObj.code) + " }," + stringifyPartials(codeObj) + "}"; | |
+function stringifyPartials(codeObj) { | |
+ var partials = []; | |
+ for (var key in codeObj.partials) { | |
+ partials.push('"' + esc(key) + '":{name:"' + esc(codeObj.partials[key].name) + '", ' + stringifyPartials(codeObj.partials[key]) + "}"); | |
} | |
+ return "partials: {" + partials.join(",") + "}, subs: " + stringifySubstitutions(codeObj.subs); | |
+} | |
- var serialNo = 0; | |
- Hogan.generate = function(tree, text, options) { | |
- serialNo = 0; | |
- var context = { code: '', subs: {}, partials: {} }; | |
- Hogan.walk(tree, context); | |
+Hogan.stringify = function(codeObj, text, options) { | |
+ return "{code: function (c,p,i) { " + Hogan.wrapMain(codeObj.code) + " }," + stringifyPartials(codeObj) + "}"; | |
+} | |
- if (options.asString) { | |
- return this.stringify(context, text, options); | |
- } | |
+var serialNo = 0; | |
+Hogan.generate = function(tree, text, options) { | |
+ serialNo = 0; | |
+ var context = { code: '', subs: {}, partials: {} }; | |
+ Hogan.walk(tree, context); | |
- return this.makeTemplate(context, text, options); | |
+ if (options.asString) { | |
+ return this.stringify(context, text, options); | |
} | |
- Hogan.wrapMain = function(code) { | |
- return 'var t=this;t.b(i=i||"");' + code + 'return t.fl();'; | |
- } | |
+ return this.makeTemplate(context, text, options); | |
+} | |
- Hogan.template = Hogan.Template; | |
+Hogan.wrapMain = function(code) { | |
+ return 'var t=this;t.b(i=i||"");' + code + 'return t.fl();'; | |
+} | |
- Hogan.makeTemplate = function(codeObj, text, options) { | |
- var template = this.makePartials(codeObj); | |
- template.code = new Function('c', 'p', 'i', this.wrapMain(codeObj.code)); | |
- return new this.template(template, text, this, options); | |
- } | |
+Hogan.template = Hogan.Template; | |
- Hogan.makePartials = function(codeObj) { | |
- var key, template = {subs: {}, partials: codeObj.partials, name: codeObj.name}; | |
- for (key in template.partials) { | |
- template.partials[key] = this.makePartials(template.partials[key]); | |
- } | |
- for (key in codeObj.subs) { | |
- template.subs[key] = new Function('c', 'p', 't', 'i', codeObj.subs[key]); | |
- } | |
- return template; | |
- } | |
+Hogan.makeTemplate = function(codeObj, text, options) { | |
+ var template = this.makePartials(codeObj); | |
+ template.code = new Function('c', 'p', 'i', this.wrapMain(codeObj.code)); | |
+ return new this.template(template, text, this, options); | |
+} | |
- function esc(s) { | |
- return s.replace(rSlash, '\\\\') | |
- .replace(rQuot, '\\\"') | |
- .replace(rNewline, '\\n') | |
- .replace(rCr, '\\r'); | |
+Hogan.makePartials = function(codeObj) { | |
+ var key, template = {subs: {}, partials: codeObj.partials, name: codeObj.name}; | |
+ for (key in template.partials) { | |
+ template.partials[key] = this.makePartials(template.partials[key]); | |
} | |
- | |
- function chooseMethod(s) { | |
- return (~s.indexOf('.')) ? 'd' : 'f'; | |
+ for (key in codeObj.subs) { | |
+ template.subs[key] = new Function('c', 'p', 't', 'i', codeObj.subs[key]); | |
} | |
+ return template; | |
+} | |
+ | |
+function esc(s) { | |
+ return s.replace(rSlash, '\\\\') | |
+ .replace(rQuot, '\\\"') | |
+ .replace(rNewline, '\\n') | |
+ .replace(rCr, '\\r'); | |
+} | |
+ | |
+function chooseMethod(s) { | |
+ return (~s.indexOf('.')) ? 'd' : 'f'; | |
+} | |
+ | |
+function createPartial(node, context) { | |
+ var prefix = "<" + (context.prefix || ""); | |
+ var sym = prefix + node.n + serialNo++; | |
+ context.partials[sym] = {name: node.n, partials: {}}; | |
+ context.code += 't.b(t.rp("' + esc(sym) + '",c,p,"' + (node.indent || '') + '"));'; | |
+ return sym; | |
+} | |
+ | |
+Hogan.codegen = { | |
+ '#': function(node, context) { | |
+ context.code += 'if(t.s(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,1),' + | |
+ 'c,p,0,' + node.i + ',' + node.end + ',"' + node.otag + " " + node.ctag + '")){' + | |
+ 't.rs(c,p,' + 'function(c,p,t){'; | |
+ Hogan.walk(node.nodes, context); | |
+ context.code += '});c.pop();}'; | |
+ }, | |
+ | |
+ '^': function(node, context) { | |
+ context.code += 'if(!t.s(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,1),c,p,1,0,0,"")){'; | |
+ Hogan.walk(node.nodes, context); | |
+ context.code += '};'; | |
+ }, | |
+ | |
+ '>': createPartial, | |
+ '<': function(node, context) { | |
+ var ctx = {partials: {}, code: '', subs: {}, inPartial: true}; | |
+ Hogan.walk(node.nodes, ctx); | |
+ var template = context.partials[createPartial(node, context)]; | |
+ template.subs = ctx.subs; | |
+ template.partials = ctx.partials; | |
+ }, | |
+ | |
+ '$': function(node, context) { | |
+ var ctx = {subs: {}, code: '', partials: context.partials, prefix: node.n}; | |
+ Hogan.walk(node.nodes, ctx); | |
+ context.subs[node.n] = ctx.code; | |
+ if (!context.inPartial) { | |
+ context.code += 't.sub("' + esc(node.n) + '",c,p,i);'; | |
+ } | |
+ }, | |
- function createPartial(node, context) { | |
- var prefix = "<" + (context.prefix || ""); | |
- var sym = prefix + node.n + serialNo++; | |
- context.partials[sym] = {name: node.n, partials: {}}; | |
- context.code += 't.b(t.rp("' + esc(sym) + '",c,p,"' + (node.indent || '') + '"));'; | |
- return sym; | |
- } | |
- | |
- Hogan.codegen = { | |
- '#': function(node, context) { | |
- context.code += 'if(t.s(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,1),' + | |
- 'c,p,0,' + node.i + ',' + node.end + ',"' + node.otag + " " + node.ctag + '")){' + | |
- 't.rs(c,p,' + 'function(c,p,t){'; | |
- Hogan.walk(node.nodes, context); | |
- context.code += '});c.pop();}'; | |
- }, | |
- | |
- '^': function(node, context) { | |
- context.code += 'if(!t.s(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,1),c,p,1,0,0,"")){'; | |
- Hogan.walk(node.nodes, context); | |
- context.code += '};'; | |
- }, | |
- | |
- '>': createPartial, | |
- '<': function(node, context) { | |
- var ctx = {partials: {}, code: '', subs: {}, inPartial: true}; | |
- Hogan.walk(node.nodes, ctx); | |
- var template = context.partials[createPartial(node, context)]; | |
- template.subs = ctx.subs; | |
- template.partials = ctx.partials; | |
- }, | |
- | |
- '$': function(node, context) { | |
- var ctx = {subs: {}, code: '', partials: context.partials, prefix: node.n}; | |
- Hogan.walk(node.nodes, ctx); | |
- context.subs[node.n] = ctx.code; | |
- if (!context.inPartial) { | |
- context.code += 't.sub("' + esc(node.n) + '",c,p,i);'; | |
- } | |
- }, | |
- | |
- '\n': function(node, context) { | |
- context.code += write('"\\n"' + (node.last ? '' : ' + i')); | |
- }, | |
+ '\n': function(node, context) { | |
+ context.code += write('"\\n"' + (node.last ? '' : ' + i')); | |
+ }, | |
- '_v': function(node, context) { | |
- context.code += 't.b(t.v(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,0)));'; | |
- }, | |
+ '_v': function(node, context) { | |
+ context.code += 't.b(t.v(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,0)));'; | |
+ }, | |
- '_t': function(node, context) { | |
- context.code += write('"' + esc(node.text) + '"'); | |
- }, | |
+ '_t': function(node, context) { | |
+ context.code += write('"' + esc(node.text) + '"'); | |
+ }, | |
- '{': tripleStache, | |
+ '{': tripleStache, | |
- '&': tripleStache | |
- } | |
+ '&': tripleStache | |
+} | |
- function tripleStache(node, context) { | |
- context.code += 't.b(t.t(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,0)));'; | |
- } | |
+function tripleStache(node, context) { | |
+ context.code += 't.b(t.t(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,0)));'; | |
+} | |
- function write(s) { | |
- return 't.b(' + s + ');'; | |
- } | |
+function write(s) { | |
+ return 't.b(' + s + ');'; | |
+} | |
- Hogan.walk = function(nodelist, context) { | |
- var func; | |
- for (var i = 0, l = nodelist.length; i < l; i++) { | |
- func = Hogan.codegen[nodelist[i].tag]; | |
- func && func(nodelist[i], context); | |
- } | |
- return context; | |
+Hogan.walk = function(nodelist, context) { | |
+ var func; | |
+ for (var i = 0, l = nodelist.length; i < l; i++) { | |
+ func = Hogan.codegen[nodelist[i].tag]; | |
+ func && func(nodelist[i], context); | |
} | |
+ return context; | |
+} | |
- Hogan.parse = function(tokens, text, options) { | |
- options = options || {}; | |
- return buildTree(tokens, '', [], options.sectionTags || []); | |
- } | |
+Hogan.parse = function(tokens, text, options) { | |
+ options = options || {}; | |
+ return buildTree(tokens, '', [], options.sectionTags || []); | |
+} | |
- Hogan.cache = {}; | |
+Hogan.cache = {}; | |
- Hogan.cacheKey = function(text, options) { | |
- return [text, !!options.asString, !!options.disableLambda, options.delimiters, !!options.modelGet].join('||'); | |
- } | |
+Hogan.cacheKey = function(text, options) { | |
+ return [text, !!options.asString, !!options.disableLambda, options.delimiters, !!options.modelGet].join('||'); | |
+} | |
- Hogan.compile = function(text, options) { | |
- options = options || {}; | |
- var key = Hogan.cacheKey(text, options); | |
- var template = this.cache[key]; | |
+Hogan.compile = function(text, options) { | |
+ options = options || {}; | |
+ var key = Hogan.cacheKey(text, options); | |
+ var template = this.cache[key]; | |
- if (template) { | |
- var partials = template.partials; | |
- for (var name in partials) { | |
- delete partials[name].instance; | |
- } | |
- return template; | |
+ if (template) { | |
+ var partials = template.partials; | |
+ for (var name in partials) { | |
+ delete partials[name].instance; | |
} | |
- | |
- template = this.generate(this.parse(this.scan(text, options.delimiters), text, options), text, options); | |
- return this.cache[key] = template; | |
+ return template; | |
} | |
-})(typeof exports !== 'undefined' ? exports : Hogan); | |
+ template = this.generate(this.parse(this.scan(text, options.delimiters), text, options), text, options); | |
+ return this.cache[key] = template; | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment