jenkins-bot has submitted this change and it was merged.
Change subject: Restructure normalization code
......................................................................
Restructure normalization code
* Restructured the normalization code to not be solely
focused on the pairwise I/B tag minimization logic.
* Made it simpler to implement other normalizations.
* Fixed code styles for this file.
Change-Id: Ib82cf9ad3df4dd3dcce5ed7042aaca2b1619b1a7
---
M lib/wts.normalizeDOM.js
1 file changed, 113 insertions(+), 70 deletions(-)
Approvals:
Arlolra: Looks good to me, approved
jenkins-bot: Verified
diff --git a/lib/wts.normalizeDOM.js b/lib/wts.normalizeDOM.js
index 829e108..1a2e2ff 100644
--- a/lib/wts.normalizeDOM.js
+++ b/lib/wts.normalizeDOM.js
@@ -1,17 +1,17 @@
-"use strict";
+'use strict';
require('./core-upgrade.js');
-var DU = require('./mediawiki.DOMUtils.js').DOMUtils,
- Consts = require('./mediawiki.wikitext.constants.js').WikitextConstants;
+var DU = require('./mediawiki.DOMUtils.js').DOMUtils;
+var Consts = require('./mediawiki.wikitext.constants.js').WikitextConstants;
var ignoreableAttribs = new Set(['data-parsoid', 'data-parsoid-diff']);
function similar(a, b) {
- var isHtml_a = DU.isLiteralHTMLNode(a);
- var isHtml_b = DU.isLiteralHTMLNode(b);
+ var aIsHtml = DU.isLiteralHTMLNode(a);
+ var bIsHtml = DU.isLiteralHTMLNode(b);
- return (!isHtml_a && !isHtml_b) ||
- (isHtml_a && isHtml_b && DU.attribsEquals(a, b,
ignoreableAttribs));
+ return (!aIsHtml && !bIsHtml) ||
+ (aIsHtml && bIsHtml && DU.attribsEquals(a, b,
ignoreableAttribs));
}
/** Can a and b be merged into a single node? */
@@ -36,7 +36,7 @@
DU.migrateChildren(b, a);
b.parentNode.removeChild(b);
- DU.setDiffMark(a, env, "children-changed");
+ DU.setDiffMark(a, env, 'children-changed');
return a;
}
@@ -46,11 +46,42 @@
a.parentNode.insertBefore(b, a);
b.appendChild(a);
- DU.setDiffMark(a, env, "children-changed");
- DU.setDiffMark(b, env, "children-changed");
+ DU.setDiffMark(a, env, 'children-changed');
+ DU.setDiffMark(b, env, 'children-changed');
return b;
}
+
+// Forward declaration
+var _normalizeDOM;
+
+/**
+ * Normalizations implemented right now:
+ * -------------------------------------
+ * 1. Tag minimization (I/B tags) in normalizeSiblingPair
+ */
+
+function normalizeNode(env, node) {
+ // Nothing to see here right now.
+ return node;
+}
+
+/*
+ * Tag minimization
+ * ----------------
+ * Minimize a pair of tags in the dom tree rooted at node.
+ *
+ * This function merges adjacent nodes of the same type
+ * and swaps nodes where possible to enable further merging.
+ *
+ * See examples below for a (B, I) tag-pair:
+ *
+ * 1. <b>X</b><b>Y</b>
+ * ==> <b>XY</b>
+ *
+ * 2. <i>A</i><b><i>X</i></b><b><i>Y</i></b><i>Z</i>
+ * ==> <i>A<b>XY</b>Z</i>
+ */
function rewriteablePair(a, b) {
// Currently supported: 'a' and 'b' are both B/I tags
@@ -73,83 +104,95 @@
Consts.WTQuoteTags.has(b.nodeName);
}
-/**
- * The only normalization implemented right now is I/B tag minimization.
- *
- * Minimize a pair of tags in the dom tree rooted at node.
- *
- * This function merges adjacent nodes of the same type
- * and swaps nodes where possible to enable further merging.
- *
- * See examples below for a (B, I) tag-pair:
- *
- * 1. <b>X</b><b>Y</b>
- * ==> <b>XY</b>
- *
- * 2. <i>A</i><b><i>X</i></b><b><i>Y</i></b><i>Z</i>
- * ==> <i>A<b>XY</b>Z</i>
- */
-function _normalizeDOM(env, node, recurse) {
- if (DU.isFirstEncapsulationWrapperNode(node) || !node.firstChild) {
- return;
+function normalizeSiblingPair(env, a, b) {
+ // If 'a' and 'b' make a rewriteable tag-pair,
+ // we are good to go.
+ if (rewriteablePair(a, b)) {
+ if (mergable(a, b)) {
+ a = merge(env, a, b);
+ // The new a's children have new siblings. So let's look
+ // at a again. But their grandkids haven't changed,
+ // so we don't need to recurse further.
+ _normalizeDOM(env, a, false);
+ } else if (swappable(a, b)) {
+ a = merge(env, swap(env, a,
DU.firstNonDeletedChildNode(a)), b);
+ // Again, a has new children, but the grandkids have
already
+ // been minimized.
+ _normalizeDOM(env, a, false);
+ } else if (swappable(b, a)) {
+ a = merge(env, a, swap(env, b,
DU.firstNonDeletedChildNode(b)));
+ // Again, a has new children, but the grandkids have
already
+ // been minimized.
+ _normalizeDOM(env, a, false);
+ } else {
+ a = b;
+ }
+ } else {
+ a = b;
}
- // Minimize the children of `node`.
- // recurse = true => recurse to ensure the children are also minimized
- // recurse = false => assume the children are already minimized
- var a = node.firstChild, b;
+ return a;
+}
- if (DU.isElt(a) && recurse) {
- _normalizeDOM(env, a, true);
+function processNode(env, a, recurse) {
+ // Normalize 'a' and the subtree rooted at 'a'
+ // recurse = true => recurse and normalize subtree
+ // recurse = false => assume the subtree is already normalized
+
+ // Skip templated content
+ if (a && DU.isFirstEncapsulationWrapperNode(a)) {
+ a = DU.skipOverEncapsulatedContent(a);
}
+ if (a) {
+ // Normalize node till it stabilizes
+ var next = normalizeNode(env, a);
+ while (next !== a) {
+ if (!next) {
+ return null;
+ }
+ a = next;
+ next = normalizeNode(env, a);
+ }
+
+ // Process DOM rooted at 'a'
+ if (recurse && DU.isElt(a)) {
+ _normalizeDOM(env, a, true);
+ }
+ }
+
+ return a;
+}
+
+_normalizeDOM = function(env, node, recurse) {
+ // Process the first child outside the loop.
+ var a = DU.firstNonDeletedChildNode(node);
+ a = processNode(env, a, recurse);
while (a) {
- b = DU.nextNonDeletedSibling(a);
+ // We need a pair of adjacent siblings for tag minimization.
+ var b = DU.nextNonDeletedSibling(a);
if (!b) {
break;
}
- if (DU.isElt(b) && recurse) {
- _normalizeDOM(env, b, true);
- }
+ // Process subtree rooted at 'b'.
+ b = processNode(env, b, recurse);
- // If 'a' and 'b' make a rewriteable tag-pair and neither of
them
- // is an encapsulated element, we are good to go.
- if (rewriteablePair(a, b) &&
- !DU.isFirstEncapsulationWrapperNode(a) &&
- !DU.isFirstEncapsulationWrapperNode(b)) {
- if (mergable(a, b)) {
- a = merge(env, a, b);
- // The new a's children have new siblings. So
let's look
- // at a again. But the children themselves
haven't changed,
- // so we don't need to recurse.
- _normalizeDOM(env, a, false);
- } else if (swappable(a, b)) {
- a = merge(env, swap(env, a,
DU.firstNonDeletedChildNode(a)), b);
- // Again, a has new children, but the grandkids
have already
- // been minimized.
- _normalizeDOM(env, a, false);
- } else if (swappable(b, a)) {
- a = merge(env, a, swap(env, b,
DU.firstNonDeletedChildNode(b)));
- // Again, a has new children, but the grandkids
have already
- // been minimized.
- _normalizeDOM(env, a, false);
- } else {
- a = b;
- }
+ // If we skipped over a bunch of nodes in the middle,
+ // we no longer have a pair of adjacent siblings.
+ if (b && DU.previousNonDeletedSibling(b) === a) {
+ // Process the pair.
+ a = normalizeSiblingPair(env, a, b);
} else {
a = b;
}
}
+};
- // return node to enable chaining
- return node;
+function normalizeDOM(body, env) {
+ return _normalizeDOM(env, body, true);
}
-function normalizeDOM(node, env) {
- return _normalizeDOM(env, node, true);
-}
-
-if (typeof module === "object") {
+if (typeof module === 'object') {
module.exports.normalizeDOM = normalizeDOM;
}
--
To view, visit https://gerrit.wikimedia.org/r/201925
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ib82cf9ad3df4dd3dcce5ed7042aaca2b1619b1a7
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/services/parsoid
Gerrit-Branch: master
Gerrit-Owner: Subramanya Sastry <[email protected]>
Gerrit-Reviewer: Arlolra <[email protected]>
Gerrit-Reviewer: Cscott <[email protected]>
Gerrit-Reviewer: Marcoil <[email protected]>
Gerrit-Reviewer: Subramanya Sastry <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits