diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-10-13 23:29:41 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-10-13 23:49:31 +0100 |
| commit | 7b7ce0d563ddc07172b0f241a5c3baf344f256e8 (patch) | |
| tree | 43f5fddf920d47e281a30139bde99da5a689d667 /lib/html | |
| parent | e04d054a1b414e843fa6d6f5ee1ae75c0df533b1 (diff) | |
Collapse similar HTML elements
Diffstat (limited to 'lib/html')
| -rw-r--r-- | lib/html/ast.js | 31 | ||||
| -rw-r--r-- | lib/html/index.js | 38 | ||||
| -rw-r--r-- | lib/html/simplify.js | 43 |
3 files changed, 100 insertions, 12 deletions
diff --git a/lib/html/ast.js b/lib/html/ast.js index afecfce..96aa6c6 100644 --- a/lib/html/ast.js +++ b/lib/html/ast.js @@ -20,24 +20,49 @@ function elementWithTag(tag, children) { return { type: "element", tag: tag, - children: collapseFragments(children) + children: collapseFragments(children), + isEmpty: _.all(children, function(child) { + return child.isEmpty; + }), + appendChild: appendChild + }; +} + +function appendChild(child) { + this.children.push(child); + this.isEmpty = this.isEmpty && child.isEmpty; +} + +function selfClosingElement(tagName, attributes) { + return { + type: "selfClosingElement", + tagName: tagName, + attributes: attributes }; } function text(value) { return { type: "text", - value: value + value: value, + isEmpty: !value }; } +var forceWrite = { + type: "forceWrite", + isEmpty: false +}; + function collapseFragments(elements) { return _.flatten((elements || []).map(function(element) { return element.type === "fragment" ? element.children : [element]; - }), true) + }), true); } exports.fragment = fragment; exports.element = element; exports.elementWithTag = elementWithTag; +exports.selfClosingElement = selfClosingElement; exports.text = text; +exports.forceWrite = forceWrite; diff --git a/lib/html/index.js b/lib/html/index.js index 41d348f..f74a98f 100644 --- a/lib/html/index.js +++ b/lib/html/index.js @@ -3,7 +3,9 @@ var ast = require("./ast"); exports.fragment = ast.fragment; exports.element = ast.element; exports.elementWithTag = ast.elementWithTag; +exports.selfClosingElement = ast.selfClosingElement; exports.text = ast.text; +exports.forceWrite = ast.forceWrite; function pathToNode(path, children) { var result = ast.fragment(children); @@ -15,3 +17,39 @@ function pathToNode(path, children) { exports.pathToNode = pathToNode; exports.simplify = require("./simplify"); + +function write(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); + }); + writer.close(node.tag.tagName); +} + +function generateSelfClosingElementString(writer, node) { + writer.selfClosing(node.tagName, node.attributes); +} + +function generateTextString(writer, node) { + writer.text(node.value); +} + +exports.write = write; diff --git a/lib/html/simplify.js b/lib/html/simplify.js index 291e5d4..8ab4a1f 100644 --- a/lib/html/simplify.js +++ b/lib/html/simplify.js @@ -1,15 +1,15 @@ -var _ = require("underscore"); - var ast = require("./ast"); function simplify(node) { - return simplifiers[node.type](node); -}; + return removeEmpty(simplifiers[node.type](node)); +} var simplifiers = { fragment: simplifyFragment, element: simplifyElement, - text: simplifyText + selfClosingElement: identity, + text: identity, + forceWrite: identity }; function simplifyFragment(node) { @@ -20,8 +20,8 @@ function simplifyElement(node) { return ast.elementWithTag(node.tag, simplifyNodes(node.children)); } -function simplifyText(node) { - return node; +function identity(value) { + return value; } function simplifyNodes(nodes) { @@ -29,10 +29,10 @@ function simplifyNodes(nodes) { nodes.map(simplify).forEach(function(child) { var lastChild = children[children.length - 1]; - if (child.type === "element" && !child.tag.fresh && lastChild && child.tag.matchesElement(lastChild.tag)) { + 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. - lastChild.children.push(grandChild); + lastChild.appendChild(grandChild); }); } else { children.push(child); @@ -41,4 +41,29 @@ function simplifyNodes(nodes) { return children; } +function removeEmpty(node) { + return emptiers[node.type](node); +} + +var emptiers = { + fragment: fragmentEmptier, + element: elementEmptier, + selfClosingElement: identity, + text: identity, + forceWrite: identity +}; + +function fragmentEmptier(fragment) { + return ast.fragment(fragment.children.filter(function(child) { + return !child.isEmpty; + })); +} + +function elementEmptier(element) { + return ast.elementWithTag(element.tag, element.children.filter(function(child) { + return !child.isEmpty; + })); +} + + module.exports = simplify; |
