/src/honeynet_web/honeywall/static/twitter-bootstrap/docs/build/node_modules/hogan.js/web/builds/1.0.5/hogan-1.0.5.js

https://bitbucket.org/cpdean/pig · JavaScript · 572 lines · 434 code · 98 blank · 40 comment · 154 complexity · b4308bfebf8e9e58fac4c2605aaf0048 MD5 · raw file

  1. /*
  2. * Copyright 2011 Twitter, Inc.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. var Hogan = {};
  16. (function (Hogan) {
  17. Hogan.Template = function constructor(renderFunc, text, compiler) {
  18. if (renderFunc) {
  19. this.r = renderFunc;
  20. }
  21. this.c = compiler;
  22. this.text = text || '';
  23. }
  24. Hogan.Template.prototype = {
  25. // render: replaced by generated code.
  26. r: function (context, partials, indent) { return ''; },
  27. // variable escaping
  28. v: hoganEscape,
  29. render: function render(context, partials, indent) {
  30. return this.ri([context], partials || {}, indent);
  31. },
  32. // render internal -- a hook for overrides that catches partials too
  33. ri: function (context, partials, indent) {
  34. return this.r(context, partials, indent);
  35. },
  36. // tries to find a partial in the curent scope and render it
  37. rp: function(name, context, partials, indent) {
  38. var partial = partials[name];
  39. if (!partial) {
  40. return '';
  41. }
  42. if (this.c && typeof partial == 'string') {
  43. partial = this.c.compile(partial);
  44. }
  45. return partial.ri(context, partials, indent);
  46. },
  47. // render a section
  48. rs: function(context, partials, section) {
  49. var buf = '',
  50. tail = context[context.length - 1];
  51. if (!isArray(tail)) {
  52. return buf = section(context, partials);
  53. }
  54. for (var i = 0; i < tail.length; i++) {
  55. context.push(tail[i]);
  56. buf += section(context, partials);
  57. context.pop();
  58. }
  59. return buf;
  60. },
  61. // maybe start a section
  62. s: function(val, ctx, partials, inverted, start, end, tags) {
  63. var pass;
  64. if (isArray(val) && val.length === 0) {
  65. return false;
  66. }
  67. if (typeof val == 'function') {
  68. val = this.ls(val, ctx, partials, inverted, start, end, tags);
  69. }
  70. pass = (val === '') || !!val;
  71. if (!inverted && pass && ctx) {
  72. ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
  73. }
  74. return pass;
  75. },
  76. // find values with dotted names
  77. d: function(key, ctx, partials, returnFound) {
  78. var names = key.split('.'),
  79. val = this.f(names[0], ctx, partials, returnFound),
  80. cx = null;
  81. if (key === '.' && isArray(ctx[ctx.length - 2])) {
  82. return ctx[ctx.length - 1];
  83. }
  84. for (var i = 1; i < names.length; i++) {
  85. if (val && typeof val == 'object' && names[i] in val) {
  86. cx = val;
  87. val = val[names[i]];
  88. } else {
  89. val = '';
  90. }
  91. }
  92. if (returnFound && !val) {
  93. return false;
  94. }
  95. if (!returnFound && typeof val == 'function') {
  96. ctx.push(cx);
  97. val = this.lv(val, ctx, partials);
  98. ctx.pop();
  99. }
  100. return val;
  101. },
  102. // find values with normal names
  103. f: function(key, ctx, partials, returnFound) {
  104. var val = false,
  105. v = null,
  106. found = false;
  107. for (var i = ctx.length - 1; i >= 0; i--) {
  108. v = ctx[i];
  109. if (v && typeof v == 'object' && key in v) {
  110. val = v[key];
  111. found = true;
  112. break;
  113. }
  114. }
  115. if (!found) {
  116. return (returnFound) ? false : "";
  117. }
  118. if (!returnFound && typeof val == 'function') {
  119. val = this.lv(val, ctx, partials);
  120. }
  121. return val;
  122. },
  123. // higher order templates
  124. ho: function(val, cx, partials, text, tags) {
  125. var compiler = this.c;
  126. var t = val.call(cx, text, function(t) {
  127. return compiler.compile(t, {delimiters: tags}).render(cx, partials);
  128. });
  129. var s = compiler.compile(t.toString(), {delimiters: tags}).render(cx, partials);
  130. this.b = s;
  131. return false;
  132. },
  133. // higher order template result buffer
  134. b: '',
  135. // lambda replace section
  136. ls: function(val, ctx, partials, inverted, start, end, tags) {
  137. var cx = ctx[ctx.length - 1],
  138. t = null;
  139. if (!inverted && this.c && val.length > 0) {
  140. return this.ho(val, cx, partials, this.text.substring(start, end), tags);
  141. }
  142. t = val.call(cx);
  143. if (typeof t == 'function') {
  144. if (inverted) {
  145. return true;
  146. } else if (this.c) {
  147. return this.ho(t, cx, partials, this.text.substring(start, end), tags);
  148. }
  149. }
  150. return t;
  151. },
  152. // lambda replace variable
  153. lv: function(val, ctx, partials) {
  154. var cx = ctx[ctx.length - 1];
  155. var result = val.call(cx);
  156. if (typeof result == 'function') {
  157. result = result.call(cx);
  158. }
  159. result = result.toString();
  160. if (this.c && ~result.indexOf("{{")) {
  161. return this.c.compile(result).render(cx, partials);
  162. }
  163. return result;
  164. }
  165. };
  166. var rAmp = /&/g,
  167. rLt = /</g,
  168. rGt = />/g,
  169. rApos =/\'/g,
  170. rQuot = /\"/g,
  171. hChars =/[&<>\"\']/;
  172. function hoganEscape(str) {
  173. str = String((str === null || str === undefined) ? '' : str);
  174. return hChars.test(str) ?
  175. str
  176. .replace(rAmp,'&amp;')
  177. .replace(rLt,'&lt;')
  178. .replace(rGt,'&gt;')
  179. .replace(rApos,'&#39;')
  180. .replace(rQuot, '&quot;') :
  181. str;
  182. }
  183. var isArray = Array.isArray || function(a) {
  184. return Object.prototype.toString.call(a) === '[object Array]';
  185. };
  186. })(typeof exports !== 'undefined' ? exports : Hogan);
  187. (function (Hogan) {
  188. // Setup regex assignments
  189. // remove whitespace according to Mustache spec
  190. var rIsWhitespace = /\S/,
  191. rQuot = /\"/g,
  192. rNewline = /\n/g,
  193. rCr = /\r/g,
  194. rSlash = /\\/g,
  195. tagTypes = {
  196. '#': 1, '^': 2, '/': 3, '!': 4, '>': 5,
  197. '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
  198. };
  199. Hogan.scan = function scan(text, delimiters) {
  200. var len = text.length,
  201. IN_TEXT = 0,
  202. IN_TAG_TYPE = 1,
  203. IN_TAG = 2,
  204. state = IN_TEXT,
  205. tagType = null,
  206. tag = null,
  207. buf = '',
  208. tokens = [],
  209. seenTag = false,
  210. i = 0,
  211. lineStart = 0,
  212. otag = '{{',
  213. ctag = '}}';
  214. function addBuf() {
  215. if (buf.length > 0) {
  216. tokens.push(new String(buf));
  217. buf = '';
  218. }
  219. }
  220. function lineIsWhitespace() {
  221. var isAllWhitespace = true;
  222. for (var j = lineStart; j < tokens.length; j++) {
  223. isAllWhitespace =
  224. (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
  225. (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
  226. if (!isAllWhitespace) {
  227. return false;
  228. }
  229. }
  230. return isAllWhitespace;
  231. }
  232. function filterLine(haveSeenTag, noNewLine) {
  233. addBuf();
  234. if (haveSeenTag && lineIsWhitespace()) {
  235. for (var j = lineStart, next; j < tokens.length; j++) {
  236. if (!tokens[j].tag) {
  237. if ((next = tokens[j+1]) && next.tag == '>') {
  238. // set indent to token value
  239. next.indent = tokens[j].toString()
  240. }
  241. tokens.splice(j, 1);
  242. }
  243. }
  244. } else if (!noNewLine) {
  245. tokens.push({tag:'\n'});
  246. }
  247. seenTag = false;
  248. lineStart = tokens.length;
  249. }
  250. function changeDelimiters(text, index) {
  251. var close = '=' + ctag,
  252. closeIndex = text.indexOf(close, index),
  253. delimiters = trim(
  254. text.substring(text.indexOf('=', index) + 1, closeIndex)
  255. ).split(' ');
  256. otag = delimiters[0];
  257. ctag = delimiters[1];
  258. return closeIndex + close.length - 1;
  259. }
  260. if (delimiters) {
  261. delimiters = delimiters.split(' ');
  262. otag = delimiters[0];
  263. ctag = delimiters[1];
  264. }
  265. for (i = 0; i < len; i++) {
  266. if (state == IN_TEXT) {
  267. if (tagChange(otag, text, i)) {
  268. --i;
  269. addBuf();
  270. state = IN_TAG_TYPE;
  271. } else {
  272. if (text.charAt(i) == '\n') {
  273. filterLine(seenTag);
  274. } else {
  275. buf += text.charAt(i);
  276. }
  277. }
  278. } else if (state == IN_TAG_TYPE) {
  279. i += otag.length - 1;
  280. tag = tagTypes[text.charAt(i + 1)];
  281. tagType = tag ? text.charAt(i + 1) : '_v';
  282. if (tagType == '=') {
  283. i = changeDelimiters(text, i);
  284. state = IN_TEXT;
  285. } else {
  286. if (tag) {
  287. i++;
  288. }
  289. state = IN_TAG;
  290. }
  291. seenTag = i;
  292. } else {
  293. if (tagChange(ctag, text, i)) {
  294. tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
  295. i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
  296. buf = '';
  297. i += ctag.length - 1;
  298. state = IN_TEXT;
  299. if (tagType == '{') {
  300. if (ctag == '}}') {
  301. i++;
  302. } else {
  303. cleanTripleStache(tokens[tokens.length - 1]);
  304. }
  305. }
  306. } else {
  307. buf += text.charAt(i);
  308. }
  309. }
  310. }
  311. filterLine(seenTag, true);
  312. return tokens;
  313. }
  314. function cleanTripleStache(token) {
  315. if (token.n.substr(token.n.length - 1) === '}') {
  316. token.n = token.n.substring(0, token.n.length - 1);
  317. }
  318. }
  319. function trim(s) {
  320. if (s.trim) {
  321. return s.trim();
  322. }
  323. return s.replace(/^\s*|\s*$/g, '');
  324. }
  325. function tagChange(tag, text, index) {
  326. if (text.charAt(index) != tag.charAt(0)) {
  327. return false;
  328. }
  329. for (var i = 1, l = tag.length; i < l; i++) {
  330. if (text.charAt(index + i) != tag.charAt(i)) {
  331. return false;
  332. }
  333. }
  334. return true;
  335. }
  336. function buildTree(tokens, kind, stack, customTags) {
  337. var instructions = [],
  338. opener = null,
  339. token = null;
  340. while (tokens.length > 0) {
  341. token = tokens.shift();
  342. if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
  343. stack.push(token);
  344. token.nodes = buildTree(tokens, token.tag, stack, customTags);
  345. instructions.push(token);
  346. } else if (token.tag == '/') {
  347. if (stack.length === 0) {
  348. throw new Error('Closing tag without opener: /' + token.n);
  349. }
  350. opener = stack.pop();
  351. if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
  352. throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
  353. }
  354. opener.end = token.i;
  355. return instructions;
  356. } else {
  357. instructions.push(token);
  358. }
  359. }
  360. if (stack.length > 0) {
  361. throw new Error('missing closing tag: ' + stack.pop().n);
  362. }
  363. return instructions;
  364. }
  365. function isOpener(token, tags) {
  366. for (var i = 0, l = tags.length; i < l; i++) {
  367. if (tags[i].o == token.n) {
  368. token.tag = '#';
  369. return true;
  370. }
  371. }
  372. }
  373. function isCloser(close, open, tags) {
  374. for (var i = 0, l = tags.length; i < l; i++) {
  375. if (tags[i].c == close && tags[i].o == open) {
  376. return true;
  377. }
  378. }
  379. }
  380. function writeCode(tree) {
  381. return 'i = i || "";var b = i + "";var _ = this;' + walk(tree) + 'return b;';
  382. }
  383. Hogan.generate = function (code, text, options) {
  384. if (options.asString) {
  385. return 'function(c,p,i){' + code + ';}';
  386. }
  387. return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan);
  388. }
  389. function esc(s) {
  390. return s.replace(rSlash, '\\\\')
  391. .replace(rQuot, '\\\"')
  392. .replace(rNewline, '\\n')
  393. .replace(rCr, '\\r');
  394. }
  395. function chooseMethod(s) {
  396. return (~s.indexOf('.')) ? 'd' : 'f';
  397. }
  398. function walk(tree) {
  399. var code = '';
  400. for (var i = 0, l = tree.length; i < l; i++) {
  401. var tag = tree[i].tag;
  402. if (tag == '#') {
  403. code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
  404. tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
  405. } else if (tag == '^') {
  406. code += invertedSection(tree[i].nodes, tree[i].n,
  407. chooseMethod(tree[i].n));
  408. } else if (tag == '<' || tag == '>') {
  409. code += partial(tree[i]);
  410. } else if (tag == '{' || tag == '&') {
  411. code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
  412. } else if (tag == '\n') {
  413. code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
  414. } else if (tag == '_v') {
  415. code += variable(tree[i].n, chooseMethod(tree[i].n));
  416. } else if (tag === undefined) {
  417. code += text('"' + esc(tree[i]) + '"');
  418. }
  419. }
  420. return code;
  421. }
  422. function section(nodes, id, method, start, end, tags) {
  423. return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
  424. 'c,p,0,' + start + ',' + end + ', "' + tags + '")){' +
  425. 'b += _.rs(c,p,' +
  426. 'function(c,p){ var b = "";' +
  427. walk(nodes) +
  428. 'return b;});c.pop();}' +
  429. 'else{b += _.b; _.b = ""};';
  430. }
  431. function invertedSection(nodes, id, method) {
  432. return 'if (!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
  433. walk(nodes) +
  434. '};';
  435. }
  436. function partial(tok) {
  437. return 'b += _.rp("' + esc(tok.n) + '",c,p,"' + (tok.indent || '') + '");';
  438. }
  439. function tripleStache(id, method) {
  440. return 'b += (_.' + method + '("' + esc(id) + '",c,p,0));';
  441. }
  442. function variable(id, method) {
  443. return 'b += (_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
  444. }
  445. function text(id) {
  446. return 'b += ' + id + ';';
  447. }
  448. Hogan.parse = function(tokens, options) {
  449. options = options || {};
  450. return buildTree(tokens, '', [], options.sectionTags || []);
  451. },
  452. Hogan.cache = {};
  453. Hogan.compile = function(text, options) {
  454. // options
  455. //
  456. // asString: false (default)
  457. //
  458. // sectionTags: [{o: '_foo', c: 'foo'}]
  459. // An array of object with o and c fields that indicate names for custom
  460. // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
  461. //
  462. // delimiters: A string that overrides the default delimiters.
  463. // Example: "<% %>"
  464. //
  465. options = options || {};
  466. var key = text + '||' + !!options.asString;
  467. var t = this.cache[key];
  468. if (t) {
  469. return t;
  470. }
  471. t = this.generate(writeCode(this.parse(this.scan(text, options.delimiters), options)), text, options);
  472. return this.cache[key] = t;
  473. };
  474. })(typeof exports !== 'undefined' ? exports : Hogan);