aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2013-03-29 21:36:57 +0000
committerMichael Williamson <mike@zwobble.org>2013-03-29 21:36:57 +0000
commit53e7181e009efcdcad182d485972bfbfda982fc0 (patch)
tree53a6793cc67a33c7fe9794eb5b1b6bbe863bfeca
parentd3a8fc6cf15038553f0d67e79c03afb64e826644 (diff)
Allow HTML elements to be reused in HTML generation
-rw-r--r--lib/html-generator.js27
-rw-r--r--lib/styles.js23
-rw-r--r--tests/html-generator.tests.js17
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, '&lt;')
.replace(/>/g, '&gt;');
}
+
+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("&lt;", generator.asString());
+ return assert.equal(generator.asString(), "&lt;");
});
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>");
});
})