Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

210 lines
11KB

  1. require('./helper');
  2. // A map of templates to their expected token output. Tokens are in the format:
  3. // [type, value, startIndex, endIndex, subTokens].
  4. var expectations = {
  5. '' : [],
  6. '{{hi}}' : [ [ 'name', 'hi', 0, 6 ] ],
  7. '{{hi.world}}' : [ [ 'name', 'hi.world', 0, 12 ] ],
  8. '{{hi . world}}' : [ [ 'name', 'hi . world', 0, 14 ] ],
  9. '{{ hi}}' : [ [ 'name', 'hi', 0, 7 ] ],
  10. '{{hi }}' : [ [ 'name', 'hi', 0, 7 ] ],
  11. '{{ hi }}' : [ [ 'name', 'hi', 0, 8 ] ],
  12. '{{{hi}}}' : [ [ '&', 'hi', 0, 8 ] ],
  13. '{{!hi}}' : [ [ '!', 'hi', 0, 7 ] ],
  14. '{{! hi}}' : [ [ '!', 'hi', 0, 8 ] ],
  15. '{{! hi }}' : [ [ '!', 'hi', 0, 9 ] ],
  16. '{{ !hi}}' : [ [ '!', 'hi', 0, 8 ] ],
  17. '{{ ! hi}}' : [ [ '!', 'hi', 0, 9 ] ],
  18. '{{ ! hi }}' : [ [ '!', 'hi', 0, 10 ] ],
  19. 'a\n b' : [ [ 'text', 'a\n b', 0, 4 ] ],
  20. 'a{{hi}}' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ] ],
  21. 'a {{hi}}' : [ [ 'text', 'a ', 0, 2 ], [ 'name', 'hi', 2, 8 ] ],
  22. ' a{{hi}}' : [ [ 'text', ' a', 0, 2 ], [ 'name', 'hi', 2, 8 ] ],
  23. ' a {{hi}}' : [ [ 'text', ' a ', 0, 3 ], [ 'name', 'hi', 3, 9 ] ],
  24. 'a{{hi}}b' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', 'b', 7, 8 ] ],
  25. 'a{{hi}} b' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', ' b', 7, 9 ] ],
  26. 'a{{hi}}b ' : [ [ 'text', 'a', 0, 1 ], [ 'name', 'hi', 1, 7 ], [ 'text', 'b ', 7, 9 ] ],
  27. 'a\n{{hi}} b \n' : [ [ 'text', 'a\n', 0, 2 ], [ 'name', 'hi', 2, 8 ], [ 'text', ' b \n', 8, 12 ] ],
  28. 'a\n {{hi}} \nb' : [ [ 'text', 'a\n ', 0, 3 ], [ 'name', 'hi', 3, 9 ], [ 'text', ' \nb', 9, 12 ] ],
  29. 'a\n {{!hi}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '!', 'hi', 3, 10 ], [ 'text', 'b', 12, 13 ] ],
  30. 'a\n{{#a}}{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [], 8 ], [ 'text', 'b', 15, 16 ] ],
  31. 'a\n {{#a}}{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 9 ], [ 'text', 'b', 16, 17 ] ],
  32. 'a\n {{#a}}{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 9 ], [ 'text', 'b', 17, 18 ] ],
  33. 'a\n{{#a}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [], 9 ], [ 'text', 'b', 16, 17 ] ],
  34. 'a\n {{#a}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 10 ], [ 'text', 'b', 17, 18 ] ],
  35. 'a\n {{#a}}\n{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 10 ], [ 'text', 'b', 18, 19 ] ],
  36. 'a\n{{#a}}\n{{/a}}\n{{#b}}\n{{/b}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [], 9 ], [ '#', 'b', 16, 22, [], 23 ], [ 'text', 'b', 30, 31 ] ],
  37. 'a\n {{#a}}\n{{/a}}\n{{#b}}\n{{/b}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 10 ], [ '#', 'b', 17, 23, [], 24 ], [ 'text', 'b', 31, 32 ] ],
  38. 'a\n {{#a}}\n{{/a}}\n{{#b}}\n{{/b}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [], 10 ], [ '#', 'b', 17, 23, [], 24 ], [ 'text', 'b', 32, 33 ] ],
  39. 'a\n{{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [ [ '#', 'b', 9, 15, [], 16 ] ], 23 ], [ 'text', 'b', 30, 31 ] ],
  40. 'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [], 17 ] ], 24 ], [ 'text', 'b', 31, 32 ] ],
  41. 'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [], 17 ] ], 24 ], [ 'text', 'b', 32, 33 ] ],
  42. '{{>abc}}' : [ [ '>', 'abc', 0, 8, '', 0, false ] ],
  43. '{{> abc }}' : [ [ '>', 'abc', 0, 10, '', 0, false ] ],
  44. '{{ > abc }}' : [ [ '>', 'abc', 0, 11, '', 0, false ] ],
  45. ' {{> abc }}\n' : [ [ '>', 'abc', 2, 12, ' ', 0, false ] ],
  46. ' {{> abc }} {{> abc }}\n' : [ [ '>', 'abc', 2, 12, ' ', 0, false ], [ '>', 'abc', 13, 23, ' ', 1, false ] ],
  47. '{{ > abc }}' : [ [ '>', 'abc', 0, 11, '', 0, false ] ],
  48. '{{>*abc}}' : [ [ '>*', 'abc', 0, 9, '', 0, false ] ],
  49. '{{> *abc}}' : [ [ '>*', 'abc', 0, 10, '', 0, false ] ],
  50. '{{>* abc}}' : [ [ '>*', 'abc', 0, 10, '', 0, false ] ],
  51. '{{ > * abc }}' : [ [ '>*', 'abc', 0, 13, '', 0, false ] ],
  52. '{{=<% %>=}}' : [ [ '=', '<% %>', 0, 11 ] ],
  53. '{{= <% %> =}}' : [ [ '=', '<% %>', 0, 13 ] ],
  54. '{{=<% %>=}}<%={{ }}=%>' : [ [ '=', '<% %>', 0, 11 ], [ '=', '{{ }}', 11, 22 ] ],
  55. '{{=<% %>=}}<%hi%>' : [ [ '=', '<% %>', 0, 11 ], [ 'name', 'hi', 11, 17 ] ],
  56. '{{#a}}{{/a}}hi{{#b}}{{/b}}\n' : [ [ '#', 'a', 0, 6, [], 6 ], [ 'text', 'hi', 12, 14 ], [ '#', 'b', 14, 20, [], 20 ], [ 'text', '\n', 26, 27 ] ],
  57. '{{a}}\n{{b}}\n\n{{#c}}\n{{/c}}\n' : [ [ 'name', 'a', 0, 5 ], [ 'text', '\n', 5, 6 ], [ 'name', 'b', 6, 11 ], [ 'text', '\n\n', 11, 13 ], [ '#', 'c', 13, 19, [], 20 ] ],
  58. '{{#foo}}\n {{#a}}\n {{b}}\n {{/a}}\n{{/foo}}\n'
  59. : [ [ '#', 'foo', 0, 8, [ [ '#', 'a', 11, 17, [ [ 'text', ' ', 18, 22 ], [ 'name', 'b', 22, 27 ], [ 'text', '\n', 27, 28 ] ], 30 ] ], 37 ] ]
  60. };
  61. var originalTemplateCache;
  62. before(function () {
  63. originalTemplateCache = Mustache.templateCache;
  64. });
  65. beforeEach(function (){
  66. Mustache.clearCache();
  67. Mustache.templateCache = originalTemplateCache;
  68. });
  69. describe('Mustache.parse', function () {
  70. for (var template in expectations) {
  71. (function (template, tokens) {
  72. it('knows how to parse ' + JSON.stringify(template), function () {
  73. assert.deepEqual(Mustache.parse(template), tokens);
  74. });
  75. })(template, expectations[template]);
  76. }
  77. describe('when there is an unclosed tag', function () {
  78. it('throws an error', function () {
  79. assert.throws(function () {
  80. Mustache.parse('My name is {{name');
  81. }, /unclosed tag at 17/i);
  82. });
  83. });
  84. describe('when there is an unclosed section', function () {
  85. it('throws an error', function () {
  86. assert.throws(function () {
  87. Mustache.parse('A list: {{#people}}{{name}}');
  88. }, /unclosed section "people" at 27/i);
  89. });
  90. });
  91. describe('when there is an unopened section', function () {
  92. it('throws an error', function () {
  93. assert.throws(function () {
  94. Mustache.parse('The end of the list! {{/people}}');
  95. }, /unopened section "people" at 21/i);
  96. });
  97. });
  98. describe('when invalid tags are given as an argument', function () {
  99. it('throws an error', function () {
  100. assert.throws(function () {
  101. Mustache.parse('A template <% name %>', [ '<%' ]);
  102. }, /invalid tags/i);
  103. });
  104. });
  105. describe('when the template contains invalid tags', function () {
  106. it('throws an error', function () {
  107. assert.throws(function () {
  108. Mustache.parse('A template {{=<%=}}');
  109. }, /invalid tags/i);
  110. });
  111. });
  112. describe('when parsing a template without tags specified followed by the same template with tags specified', function () {
  113. it('returns different tokens for the latter parse', function () {
  114. var template = '{{foo}}[bar]';
  115. var parsedWithBraces = Mustache.parse(template);
  116. var parsedWithBrackets = Mustache.parse(template, ['[', ']']);
  117. assert.notDeepEqual(parsedWithBrackets, parsedWithBraces);
  118. });
  119. });
  120. describe('when parsing a template with tags specified followed by the same template with different tags specified', function () {
  121. it('returns different tokens for the latter parse', function () {
  122. var template = '(foo)[bar]';
  123. var parsedWithParens = Mustache.parse(template, ['(', ')']);
  124. var parsedWithBrackets = Mustache.parse(template, ['[', ']']);
  125. assert.notDeepEqual(parsedWithBrackets, parsedWithParens);
  126. });
  127. });
  128. describe('when parsing a template after already having parsed that template with a different Mustache.tags', function () {
  129. it('returns different tokens for the latter parse', function () {
  130. var template = '{{foo}}[bar]';
  131. var parsedWithBraces = Mustache.parse(template);
  132. var oldTags = Mustache.tags;
  133. Mustache.tags = ['[', ']'];
  134. var parsedWithBrackets = Mustache.parse(template);
  135. Mustache.tags = oldTags;
  136. assert.notDeepEqual(parsedWithBrackets, parsedWithBraces);
  137. });
  138. });
  139. describe('when parsing a template with the same tags second time, return the cached tokens', function () {
  140. it('returns the same tokens for the latter parse', function () {
  141. var template = '{{foo}}[bar]';
  142. var parsedResult1 = Mustache.parse(template);
  143. var parsedResult2 = Mustache.parse(template);
  144. assert.deepEqual(parsedResult1, parsedResult2);
  145. assert.ok(parsedResult1 === parsedResult2);
  146. });
  147. });
  148. describe('when parsing a template with caching disabled and the same tags second time, do not return the cached tokens', function () {
  149. it('returns different tokens for the latter parse', function () {
  150. Mustache.templateCache = undefined;
  151. var template = '{{foo}}[bar]';
  152. var parsedResult1 = Mustache.parse(template);
  153. var parsedResult2 = Mustache.parse(template);
  154. assert.deepEqual(parsedResult1, parsedResult2);
  155. assert.ok(parsedResult1 !== parsedResult2);
  156. });
  157. });
  158. describe('when parsing a template with custom caching and the same tags second time, do not return the cached tokens', function () {
  159. it('returns the same tokens for the latter parse', function () {
  160. Mustache.templateCache = {
  161. _cache: [],
  162. set: function set (key, value) {
  163. this._cache.push([key, value]);
  164. },
  165. get: function get (key) {
  166. var cacheLength = this._cache.length;
  167. for (var i = 0; i < cacheLength; i++) {
  168. var entry = this._cache[i];
  169. if (entry[0] === key) {
  170. return entry[1];
  171. }
  172. }
  173. return undefined;
  174. },
  175. clear: function clear () {
  176. this._cache = [];
  177. }
  178. };
  179. var template = '{{foo}}[bar]';
  180. var parsedResult1 = Mustache.parse(template);
  181. var parsedResult2 = Mustache.parse(template);
  182. assert.deepEqual(parsedResult1, parsedResult2);
  183. assert.ok(parsedResult1 === parsedResult2);
  184. });
  185. });
  186. });