aboutsummaryrefslogtreecommitdiff
path: root/lib/html
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-06-09 22:32:30 +0100
committerMichael Williamson <mike@zwobble.org>2016-06-20 12:06:19 +0100
commitac3981df81148fad21c32b22496ecc145ad36e98 (patch)
treecfba69d2fedb0cacc7d544749f199bd339a1c6ad /lib/html
parent8617c85c8626354fff63eeaeb775402715fe63a4 (diff)
Use simpler structure for HTML without fragments
Diffstat (limited to 'lib/html')
-rw-r--r--lib/html/ast.js33
-rw-r--r--lib/html/index.js28
-rw-r--r--lib/html/simplify.js78
3 files changed, 58 insertions, 81 deletions
diff --git a/lib/html/ast.js b/lib/html/ast.js
index 30e65c7..db9e690 100644
--- a/lib/html/ast.js
+++ b/lib/html/ast.js
@@ -1,15 +1,6 @@
-var _ = require("underscore");
-
var htmlPaths = require("../html-paths");
-function fragment(children) {
- return {
- type: "fragment",
- children: collapseFragments(children)
- };
-}
-
function nonFreshElement(tagName, attributes, children) {
return elementWithTag(
htmlPaths.element(tagName, attributes, {fresh: false}),
@@ -26,18 +17,9 @@ function elementWithTag(tag, children) {
return {
type: "element",
tag: tag,
- children: collapseFragments(children),
- isEmpty: _.all(children, function(child) {
- return child.isEmpty;
- }),
- appendChild: appendChild
+ children: children || []
};
}
-
-function appendChild(child) {
- this.children.push(child);
- this.isEmpty = this.isEmpty && child.isEmpty;
-}
function selfClosingElement(tagName, attributes) {
return {
@@ -50,23 +32,14 @@ function selfClosingElement(tagName, attributes) {
function text(value) {
return {
type: "text",
- value: value,
- isEmpty: !value
+ value: value
};
}
var forceWrite = {
- type: "forceWrite",
- isEmpty: false
+ type: "forceWrite"
};
-function collapseFragments(elements) {
- return _.flatten((elements || []).map(function(element) {
- return element.type === "fragment" ? element.children : [element];
- }), true);
-}
-
-exports.fragment = fragment;
exports.freshElement = freshElement;
exports.nonFreshElement = nonFreshElement;
exports.elementWithTag = elementWithTag;
diff --git a/lib/html/index.js b/lib/html/index.js
index 8fa1fcf..edc8256 100644
--- a/lib/html/index.js
+++ b/lib/html/index.js
@@ -1,6 +1,5 @@
var ast = require("./ast");
-exports.fragment = ast.fragment;
exports.freshElement = ast.freshElement;
exports.nonFreshElement = ast.nonFreshElement;
exports.elementWithTag = ast.elementWithTag;
@@ -8,40 +7,37 @@ exports.selfClosingElement = ast.selfClosingElement;
exports.text = ast.text;
exports.forceWrite = ast.forceWrite;
-function pathToNode(path, children) {
- var result = ast.fragment(children);
+function pathToNodes(path, children) {
+ var result = children;
for (var index = path.length - 1; index >= 0; index--) {
- result = ast.elementWithTag(path[index], [result]);
+ result = [ast.elementWithTag(path[index], result)];
}
return result;
}
-exports.pathToNode = pathToNode;
+exports.pathToNodes = pathToNodes;
exports.simplify = require("./simplify");
-function write(writer, node) {
+function write(writer, nodes) {
+ nodes.forEach(function(node) {
+ writeNode(writer, node);
+ });
+}
+
+function writeNode(writer, node) {
toStrings[node.type](writer, node);
}
var toStrings = {
- fragment: generateFragmentString,
element: generateElementString,
selfClosingElement: generateSelfClosingElementString,
text: generateTextString,
forceWrite: function() { }
};
-function generateFragmentString(writer, node) {
- node.children.forEach(function(child) {
- write(writer, child);
- });
-}
-
function generateElementString(writer, node) {
writer.open(node.tag.tagName, node.tag.attributes);
- node.children.forEach(function(child) {
- write(writer, child);
- });
+ write(writer, node.children);
writer.close(node.tag.tagName);
}
diff --git a/lib/html/simplify.js b/lib/html/simplify.js
index 24a3447..081c3f8 100644
--- a/lib/html/simplify.js
+++ b/lib/html/simplify.js
@@ -1,79 +1,87 @@
+var _ = require("underscore");
+
var ast = require("./ast");
-function simplify(node) {
- return collapse(removeEmpty(node));
+function simplify(nodes) {
+ return collapse(removeEmpty(nodes));
+}
+
+function collapse(nodes) {
+ var children = [];
+
+ nodes.map(collapseNode).forEach(function(child) {
+ appendChild(children, child);
+ });
+ return children;
}
-function collapse(node) {
+function collapseNode(node) {
return collapsers[node.type](node);
}
var collapsers = {
- fragment: collapseFragment,
element: collapseElement,
selfClosingElement: identity,
text: identity,
forceWrite: identity
};
-function collapseFragment(node) {
- return ast.fragment(collapseNodes(node.children));
-}
-
function collapseElement(node) {
- return ast.elementWithTag(node.tag, collapseNodes(node.children));
+ return ast.elementWithTag(node.tag, collapse(node.children));
}
function identity(value) {
return value;
}
-function collapseNodes(nodes) {
- var children = [];
-
- nodes.map(collapse).forEach(function(child) {
- appendChild(children, child, children.push.bind(children));
- });
- return children;
-}
-
-function appendChild(children, child, append) {
+function appendChild(children, child) {
var lastChild = children[children.length - 1];
if (child.type === "element" && !child.tag.fresh && lastChild && lastChild.type === "element" && child.tag.matchesElement(lastChild.tag)) {
child.children.forEach(function(grandChild) {
// Mutation is fine since simplifying elements create a copy of the children.
- appendChild(lastChild.children, grandChild, lastChild.appendChild.bind(lastChild));
+ appendChild(lastChild.children, grandChild);
});
} else {
- append(child);
+ children.push(child);
}
}
-function removeEmpty(node) {
- return emptiers[node.type](node);
+function removeEmpty(nodes) {
+ return flatMap(nodes, function(node) {
+ return emptiers[node.type](node);
+ });
+}
+
+function flatMap(values, func) {
+ return _.flatten(_.map(values, func), true);
}
var emptiers = {
- fragment: fragmentEmptier,
element: elementEmptier,
- selfClosingElement: identity,
- text: identity,
- forceWrite: identity
+ selfClosingElement: neverEmpty,
+ text: textEmptier,
+ forceWrite: neverEmpty
};
-function fragmentEmptier(fragment) {
- return ast.fragment(listEmptier(fragment.children));
+function neverEmpty(node) {
+ return [node];
}
function elementEmptier(element) {
- return ast.elementWithTag(element.tag, listEmptier(element.children));
+ var children = removeEmpty(element.children);
+ if (children.length === 0) {
+ return [];
+ } else {
+ return ast.elementWithTag(element.tag, children);
+ }
}
-function listEmptier(elements) {
- return elements.map(removeEmpty).filter(function(child) {
- return !child.isEmpty;
- });
+function textEmptier(node) {
+ if (node.value.length === 0) {
+ return [];
+ } else {
+ return [node];
+ }
}
-
module.exports = simplify;