From 8916ee0891c5af544aa4adfecc1fabc3c56ade5b Mon Sep 17 00:00:00 2001 From: Ian Storm Taylor Date: Tue, 26 Jul 2016 11:51:20 -0700 Subject: [PATCH] fix to remove extra empty text nodes, closes #171 --- lib/models/node.js | 66 +++++++++---------- .../block-end/output.yaml | 2 - 2 files changed, 31 insertions(+), 37 deletions(-) diff --git a/lib/models/node.js b/lib/models/node.js index 3463e6ff0..ec0c63ad2 100644 --- a/lib/models/node.js +++ b/lib/models/node.js @@ -877,16 +877,17 @@ const Node = { normalize() { let node = this + let keys = new Set() + let removals = new Set() - // Map this node's descendants, ensuring... ensuring there are no duplicate keys. - const keys = [] - + // Map this node's descendants, ensuring... node = node.mapDescendants((desc) => { - // That there are no duplicate keys. - if (includes(keys, desc.key)) desc = desc.set('key', uid()) - keys.push(desc.key) - // That void nodes contain no text. + // ...that there are no duplicate keys. + if (keys.has(desc.key)) desc = desc.set('key', uid()) + keys = keys.add(desc.key) + + // ...that void nodes contain no text. if (desc.isVoid && desc.length) { let text = desc.getTexts().first() let characters = text.characters.clear() @@ -895,45 +896,40 @@ const Node = { desc = desc.merge({ nodes }) } - // That no block or inline node is empty. + // ...that no block or inline node is empty. if (desc.kind != 'text' && desc.nodes.size == 0) { const text = Text.create() const nodes = desc.nodes.push(text) desc = desc.merge({ nodes }) } + if (desc.kind == 'text') { + let next = node.getNextSibling(desc) + + // ...that there are no adjacent text nodes. + while (next && next.kind == 'text') { + const characters = desc.characters.concat(next.characters) + desc = desc.merge({ characters }) + removals = removals.add(next.key) + next = node.getNextSibling(next) + } + + // ...that there are no extra empty text nodes. + if (desc.length == 0) { + const parent = node.getParent(desc) + if (parent.nodes.size != 1) removals = removals.add(desc.key) + } + } + return desc }) - // See if there are any adjacent text nodes. - let first = node.findDescendant((child) => { - if (child.kind != 'text') return - const parent = node.getParent(child) - const next = parent.getNextSibling(child) - return next && next.kind == 'text' + // Remove any nodes marked for removal. + removals.forEach((key) => { + node = node.removeDescendant(key) }) - // If no text nodes are adjacent, abort. - if (!first) return node - - // Fix an adjacent text node if one exists. - let parent = node.getParent(first) - const isParent = node == parent - const second = parent.getNextSibling(first) - const characters = first.characters.concat(second.characters) - first = first.merge({ characters }) - parent = parent.updateDescendant(first) - - // Then remove the second text node. - parent = parent.removeDescendant(second) - - // And update the node. - node = isParent - ? parent - : node.updateDescendant(parent) - - // Recurse by normalizing again. - return node.normalize() + return node }, /** diff --git a/test/transforms/fixtures/insert-inline-at-range/block-end/output.yaml b/test/transforms/fixtures/insert-inline-at-range/block-end/output.yaml index d36cb71e5..762f23589 100644 --- a/test/transforms/fixtures/insert-inline-at-range/block-end/output.yaml +++ b/test/transforms/fixtures/insert-inline-at-range/block-end/output.yaml @@ -10,5 +10,3 @@ nodes: nodes: - kind: text text: "" - - kind: text - text: ""