Skip to content
Browse files

Merge pull request #85 from pgte/master

Fixed #84 - properly matching closing tags when iterating
  • Loading branch information...
2 parents 34c73bc + 149c9fa commit b45b460a1236ccdc1341e05194ee95db9d47395b @3rd-Eden 3rd-Eden committed Sep 3, 2012
Showing with 146 additions and 5 deletions.
  1. +33 −5 lib/plates.js
  2. +15 −0 test/api-test.js
  3. +8 −0 test/fixtures/test-39.html
  4. +3 −0 test/fixtures/test-39.json
  5. +8 −0 test/fixtures/test-39.out
  6. +79 −0 test/match-closing-test.js
View
38 lib/plates.js
@@ -93,6 +93,36 @@ var Plates = (typeof module !== 'undefined' && typeof module.exports !== 'undefi
return mappings;
}
+//
+// Matches a closing tag to a open tag
+//
+function matchClosing(input, tagname, html) {
+ var closeTag = '</' + tagname + '>',
+ openTag = new RegExp('< *' + tagname + '( *|>)', 'g'),
+ closeCount = 0,
+ openCount = -1,
+ from, to, chunk
+ ;
+
+ from = html.search(input);
+ to = from;
+
+ while(to > -1 && closeCount !== openCount) {
+ to = html.indexOf(closeTag, to);
+ if (to > -1) {
+ to += tagname.length + 3;
+ closeCount ++;
+ chunk = html.slice(from, to);
+ openCount = chunk.match(openTag).length;
+ }
+ }
+ if (to === -1) {
+ throw new Error('Unmatched tag ' + tagname + ' in ' + html)
+ }
+
+ return chunk;
+}
+
var Merge = function Merge() {};
Merge.prototype = {
nest: [],
@@ -142,11 +172,9 @@ var Plates = (typeof module !== 'undefined' && typeof module.exports !== 'undefi
iterate: function iterate(html, value, components, tagname, key, map) {
var output = '',
- segment = html.slice(
- html.search(components.input),
- html.lastIndexOf(tagname) + tagname.length + 1
- ),
- data = {};
+ segment = matchClosing(components.input, tagname, html),
+ data = {}
+ ;
// Is it an array?
if (Array.isArray(value)) {
View
15 test/api-test.js
@@ -442,6 +442,7 @@ vows.describe('merge data into markup').addBatch({
return common.createTest('test-37', map);
}()
),
+
'(38) spaces in attributes': (
function() {
@@ -452,6 +453,20 @@ vows.describe('merge data into markup').addBatch({
return common.createTest('test-38', map);
}()
+ ),
+
+ '(39) Nesting arrays with objects with arrays should work': (
+
+
+ function() {
+
+ var map = Plates.Map();
+
+ map.className('author').to('author');
+
+ return common.createTest('test-39', map);
+ }()
+
)
}
View
8 test/fixtures/test-39.html
@@ -0,0 +1,8 @@
+<div class="row-fluid content">
+
+ <div class="span4" role="complementary">
+ <h2>Authors</h2>
+ <div class="author"></div>
+ </div>
+
+</div>
View
3 test/fixtures/test-39.json
@@ -0,0 +1,3 @@
+{
+ "author":["ABC","DEF"]
+}
View
8 test/fixtures/test-39.out
@@ -0,0 +1,8 @@
+<div class="row-fluid content">
+
+ <div class="span4" role="complementary">
+ <h2>Authors</h2>
+ <div class="author">ABC</div><div class="author">DEF</div>
+ </div>
+
+</div>
View
79 test/match-closing-test.js
@@ -0,0 +1,79 @@
+var vows = require('vows'),
+ assert = require('assert'),
+ Plates = require('../lib/plates');
+ common = require('./common');
+
+
+
+function matchClosing(input, tagname, html) {
+ var closeTag = '</' + tagname + '>',
+ openTag = new RegExp('< *' + tagname + '( *|>)', 'g'),
+ closeCount = 0,
+ openCount = -1,
+ from, to, chunk
+ ;
+
+ from = html.search(input);
+ to = from;
+
+ while(to > -1 && closeCount !== openCount) {
+ to = html.indexOf(closeTag, to);
+ if (to > -1) {
+ to += tagname.length + 3;
+ closeCount ++;
+ chunk = html.slice(from, to);
+ openCount = chunk.match(openTag).length;
+ }
+ }
+ if (to === -1) {
+ throw new Error('Unmatched tag ' + tagname + ' in ' + html)
+ }
+
+ return chunk;
+}
+
+// Tests
+
+assert.equal(matchClosing('<div class="abc">', 'div', '<div class="abc"></div>'), '<div class="abc"></div>');
+
+assert.equal(matchClosing('<div class="abc">', 'div', '<div class="abc"></div><div class="def"></div>'), '<div class="abc"></div>');
+
+assert.equal(matchClosing('<div class="abc">', 'div', '<div><div class="abc"></div></div>'), '<div class="abc"></div>');
+
+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>');
+
+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>');
+
+assert.throws(function() {
+ matchClosing('<div class="abc">', 'div', '<div class="abc"></li>');
+}, 'Unmatched tag div in <div class="abc"></li>');
+
+assert.equal(matchClosing('<li class="organizations">', 'li',
+'<ul>\
+ <li class="organizations">\
+ <h3 class="name"></h3>\
+ <ul>\
+ <li class="staff">\
+ <table>\
+ <tr class="name">\
+ <td class="first"></td>\
+ <td class="last"></td>\
+ </tr>\
+ </table>\
+ </li>\
+ </ul>\
+ </li>\
+</ul>'),
+'<li class="organizations">\
+ <h3 class="name"></h3>\
+ <ul>\
+ <li class="staff">\
+ <table>\
+ <tr class="name">\
+ <td class="first"></td>\
+ <td class="last"></td>\
+ </tr>\
+ </table>\
+ </li>\
+ </ul>\
+ </li>');

0 comments on commit b45b460

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