Skip to content
This repository
Browse code

Merge pull request #85 from pgte/master

Fixed #84 - properly matching closing tags when iterating
  • Loading branch information...
commit b45b460a1236ccdc1341e05194ee95db9d47395b 2 parents 34c73bc + 149c9fa
Arnout Kazemier authored September 03, 2012
38  lib/plates.js
@@ -93,6 +93,36 @@ var Plates = (typeof module !== 'undefined' && typeof module.exports !== 'undefi
93 93
     return mappings;
94 94
   }
95 95
 
  96
+//
  97
+// Matches a closing tag to a open tag
  98
+//
  99
+function matchClosing(input, tagname, html) {
  100
+  var closeTag = '</' + tagname + '>',
  101
+      openTag  = new RegExp('< *' + tagname + '( *|>)', 'g'),
  102
+      closeCount = 0,
  103
+      openCount = -1,
  104
+      from, to, chunk
  105
+      ;
  106
+  
  107
+  from = html.search(input);
  108
+  to = from;
  109
+
  110
+  while(to > -1 && closeCount !== openCount) {
  111
+    to = html.indexOf(closeTag, to);
  112
+    if (to > -1) {
  113
+      to += tagname.length + 3;
  114
+      closeCount ++;
  115
+      chunk = html.slice(from, to);
  116
+      openCount = chunk.match(openTag).length;
  117
+    }
  118
+  }
  119
+  if (to === -1) {
  120
+    throw new Error('Unmatched tag ' + tagname + ' in ' + html)
  121
+  }
  122
+
  123
+  return chunk;
  124
+}
  125
+
96 126
   var Merge = function Merge() {};
97 127
   Merge.prototype = {
98 128
     nest: [],
@@ -142,11 +172,9 @@ var Plates = (typeof module !== 'undefined' && typeof module.exports !== 'undefi
142 172
     iterate: function iterate(html, value, components, tagname, key, map) {
143 173
 
144 174
       var output  = '',
145  
-          segment = html.slice(
146  
-            html.search(components.input),
147  
-            html.lastIndexOf(tagname) + tagname.length + 1
148  
-          ),
149  
-          data = {};
  175
+          segment = matchClosing(components.input, tagname, html),
  176
+          data = {}
  177
+          ;
150 178
 
151 179
       // Is it an array?
152 180
       if (Array.isArray(value)) {
15  test/api-test.js
@@ -442,6 +442,7 @@ vows.describe('merge data into markup').addBatch({
442 442
         return common.createTest('test-37', map);
443 443
       }()
444 444
     ),
  445
+
445 446
     '(38) spaces in attributes': (
446 447
 
447 448
       function() {
@@ -452,6 +453,20 @@ vows.describe('merge data into markup').addBatch({
452 453
         return common.createTest('test-38', map);
453 454
      
454 455
       }()
  456
+    ),
  457
+
  458
+    '(39) Nesting arrays with objects with arrays should work': (
  459
+
  460
+
  461
+      function() {
  462
+
  463
+        var map = Plates.Map();
  464
+
  465
+        map.className('author').to('author');
  466
+
  467
+        return common.createTest('test-39', map);
  468
+      }()
  469
+
455 470
     )
456 471
   }
457 472
 
8  test/fixtures/test-39.html
... ...
@@ -0,0 +1,8 @@
  1
+<div class="row-fluid content">
  2
+  
  3
+  <div class="span4" role="complementary">
  4
+    <h2>Authors</h2>
  5
+    <div class="author"></div>
  6
+  </div>
  7
+    
  8
+</div>
3  test/fixtures/test-39.json
... ...
@@ -0,0 +1,3 @@
  1
+{
  2
+  "author":["ABC","DEF"]
  3
+}
8  test/fixtures/test-39.out
... ...
@@ -0,0 +1,8 @@
  1
+<div class="row-fluid content">
  2
+  
  3
+  <div class="span4" role="complementary">
  4
+    <h2>Authors</h2>
  5
+    <div class="author">ABC</div><div class="author">DEF</div>
  6
+  </div>
  7
+    
  8
+</div>
79  test/match-closing-test.js
... ...
@@ -0,0 +1,79 @@
  1
+var vows = require('vows'),
  2
+    assert = require('assert'),
  3
+    Plates = require('../lib/plates');
  4
+    common = require('./common');
  5
+
  6
+
  7
+
  8
+function matchClosing(input, tagname, html) {
  9
+  var closeTag = '</' + tagname + '>',
  10
+      openTag  = new RegExp('< *' + tagname + '( *|>)', 'g'),
  11
+      closeCount = 0,
  12
+      openCount = -1,
  13
+      from, to, chunk
  14
+      ;
  15
+  
  16
+  from = html.search(input);
  17
+  to = from;
  18
+
  19
+  while(to > -1 && closeCount !== openCount) {
  20
+    to = html.indexOf(closeTag, to);
  21
+    if (to > -1) {
  22
+      to += tagname.length + 3;
  23
+      closeCount ++;
  24
+      chunk = html.slice(from, to);
  25
+      openCount = chunk.match(openTag).length;
  26
+    }
  27
+  }
  28
+  if (to === -1) {
  29
+    throw new Error('Unmatched tag ' + tagname + ' in ' + html)
  30
+  }
  31
+
  32
+  return chunk;
  33
+}
  34
+
  35
+// Tests
  36
+
  37
+assert.equal(matchClosing('<div class="abc">', 'div', '<div class="abc"></div>'), '<div class="abc"></div>');
  38
+
  39
+assert.equal(matchClosing('<div class="abc">', 'div', '<div class="abc"></div><div class="def"></div>'), '<div class="abc"></div>');
  40
+
  41
+assert.equal(matchClosing('<div class="abc">', 'div', '<div><div class="abc"></div></div>'), '<div class="abc"></div>');
  42
+
  43
+assert.equal(matchClosing('<div class="abc">', 'div', '<div><div class="abc"><li></li><li></li></div></div>'), '<div class="abc"><li></li><li></li></div>');
  44
+
  45
+assert.equal(matchClosing('<li class="name">', 'li', '<li><ul><li class="name"><span abc></span></li></ul></li>'), '<li class="name"><span abc></span></li>');
  46
+
  47
+assert.throws(function() {
  48
+  matchClosing('<div class="abc">', 'div', '<div class="abc"></li>');
  49
+}, 'Unmatched tag div in <div class="abc"></li>');
  50
+
  51
+assert.equal(matchClosing('<li class="organizations">', 'li',
  52
+'<ul>\
  53
+  <li class="organizations">\
  54
+    <h3 class="name"></h3>\
  55
+    <ul>\
  56
+      <li class="staff">\
  57
+        <table>\
  58
+          <tr class="name">\
  59
+            <td class="first"></td>\
  60
+            <td class="last"></td>\
  61
+          </tr>\
  62
+        </table>\
  63
+      </li>\
  64
+    </ul>\
  65
+  </li>\
  66
+</ul>'),
  67
+'<li class="organizations">\
  68
+    <h3 class="name"></h3>\
  69
+    <ul>\
  70
+      <li class="staff">\
  71
+        <table>\
  72
+          <tr class="name">\
  73
+            <td class="first"></td>\
  74
+            <td class="last"></td>\
  75
+          </tr>\
  76
+        </table>\
  77
+      </li>\
  78
+    </ul>\
  79
+  </li>');

0 notes on commit b45b460

Please sign in to comment.
Something went wrong with that request. Please try again.