diff options
| author | Michael Williamson <mike@zwobble.org> | 2013-03-29 21:36:57 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2013-03-29 21:36:57 +0000 |
| commit | 53e7181e009efcdcad182d485972bfbfda982fc0 (patch) | |
| tree | 53a6793cc67a33c7fe9794eb5b1b6bbe863bfeca | |
| parent | d3a8fc6cf15038553f0d67e79c03afb64e826644 (diff) | |
Allow HTML elements to be reused in HTML generation
| -rw-r--r-- | lib/html-generator.js | 27 | ||||
| -rw-r--r-- | lib/styles.js | 23 | ||||
| -rw-r--r-- | tests/html-generator.tests.js | 17 |
3 files changed, 59 insertions, 8 deletions
diff --git a/lib/html-generator.js b/lib/html-generator.js index 247ca09..5f2befa 100644 --- a/lib/html-generator.js +++ b/lib/html-generator.js @@ -1,5 +1,7 @@ var util = require("util"); +var _ = require("underscore"); + exports.HtmlGenerator = HtmlGenerator; @@ -17,10 +19,20 @@ function HtmlGenerator() { } function style(style) { - popAll(); - style.forEach(function(tagName) { - push(tagName); + var firstFreshPartIndex = findIndex(style, function(part) { + return part.fresh; }); + + var partIndex = 0; + while (partIndex < firstFreshPartIndex && style[partIndex].tagName === stack[partIndex]) { + partIndex++; + } + while (stack.length > partIndex) { + pop(); + } + for (; partIndex < style.length; partIndex++) { + push(style[partIndex].tagName); + } } function push(element) { @@ -54,3 +66,12 @@ function escapeHtml(value) { .replace(/</g, '<') .replace(/>/g, '>'); } + +function findIndex(array, predicate) { + for (var i = 0; i < array.length; i++) { + if (predicate(array[i])) { + return i; + } + } + return -1; +} diff --git a/lib/styles.js b/lib/styles.js index d3aa0a4..06d63a8 100644 --- a/lib/styles.js +++ b/lib/styles.js @@ -1,10 +1,27 @@ +var _ = require("underscore"); + exports.topLevelElement = topLevelElement; exports.elements = elements; +exports.element = element; function topLevelElement(tagName) { - return elements([tagName]); + return elements([element(tagName, {fresh: true})]); +} + +function elements(elementStyles) { + return elementStyles.map(function(elementStyle) { + if (_.isString(elementStyle)) { + return element(elementStyle); + } else { + return elementStyle; + } + }); } -function elements(tagNames) { - return tagNames; +function element(tagName, options) { + options = options || {}; + return { + tagName: tagName, + fresh: options.fresh + }; } diff --git a/tests/html-generator.tests.js b/tests/html-generator.tests.js index 822aed9..a98ee70 100644 --- a/tests/html-generator.tests.js +++ b/tests/html-generator.tests.js @@ -14,13 +14,26 @@ describe('HtmlGenerator', function() { test('HTML-escapes text', function() { var generator = new HtmlGenerator(); generator.text("<"); - return assert.equal("<", generator.asString()); + return assert.equal(generator.asString(), "<"); }); test('asString closes all elements', function() { var generator = new HtmlGenerator(); generator.style(styles.elements(["p", "span"])); generator.text("Hello!"); - return assert.equal("<p><span>Hello!</span></p>", generator.asString()); + return assert.equal(generator.asString(), "<p><span>Hello!</span></p>"); + }); + + test('can leave some HTML elements for next style', function() { + var generator = new HtmlGenerator(); + var listStyle = styles.elements([ + styles.element("ul", {fresh: false}), + styles.element("li", {fresh: true}) + ]) + generator.style(listStyle); + generator.text("Apple"); + generator.style(listStyle); + generator.text("Banana"); + return assert.equal(generator.asString(), "<ul><li>Apple</li><li>Banana</li></ul>"); }); }) |
