diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-06-09 22:32:30 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-06-20 12:06:19 +0100 |
| commit | ac3981df81148fad21c32b22496ecc145ad36e98 (patch) | |
| tree | cfba69d2fedb0cacc7d544749f199bd339a1c6ad /lib/html | |
| parent | 8617c85c8626354fff63eeaeb775402715fe63a4 (diff) | |
Use simpler structure for HTML without fragments
Diffstat (limited to 'lib/html')
| -rw-r--r-- | lib/html/ast.js | 33 | ||||
| -rw-r--r-- | lib/html/index.js | 28 | ||||
| -rw-r--r-- | lib/html/simplify.js | 78 |
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; |
