Subramanya Sastry has uploaded a new change for review.
https://gerrit.wikimedia.org/r/59421
Change subject: Fixes to DOMDiff and Selser code to better handle modified
content.
......................................................................
Fixes to DOMDiff and Selser code to better handle modified content.
* Deleted some dead code from DOMUtils.
* Used node.data loading to eliminate repeated parses of
data-parsoid-diff attribute.
* Improved dom-diff marking to distinguish between a modified
wrapper vs. a modified subtree.
Ex: modification of attributes of a node vs. modification of
the wrapper itself.
* So, dom-diff has two kinds of markers: markers that apply to
just the node vs. markers that apply to the entire subtree rooted
at a node. 'modified' and 'inserted' markers belong to the
second category -- this kind eliminates the need to litter all
nodes of a sub-tree with the same diff marker. If a node is
marked modified/inserted, WTS-selser treats the the entire
sub-tree as modified.
TODO: Possibly redo the marker naming scheme to better
reflect this difference.
* Since 'modified' and 'inserted' markers are now handled more
accurately both by dom-diff and the serializer, 7 more selser
tests are now passing.
Change-Id: I9895f079d607abcebee0ccee710f9a350411935e
---
M js/lib/mediawiki.DOMDiff.js
M js/lib/mediawiki.DOMUtils.js
M js/lib/mediawiki.WikitextSerializer.js
3 files changed, 44 insertions(+), 58 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Parsoid
refs/changes/21/59421/1
diff --git a/js/lib/mediawiki.DOMDiff.js b/js/lib/mediawiki.DOMDiff.js
index 28449ce..4be7ff9 100644
--- a/js/lib/mediawiki.DOMDiff.js
+++ b/js/lib/mediawiki.DOMDiff.js
@@ -10,12 +10,9 @@
*/
function DOMDiff ( env ) {
this.env = env;
- this.debug = env.conf.parsoid.debug ||
- (env.conf.parsoid.traceFlags &&
env.conf.parsoid.traceFlags.indexOf('selser') !== -1) ?
- console.error : function(){};
- this.currentId = 0;
- this.startPos = 0; // start offset of the current unmodified chunk
- this.curPos = 0; // end offset of the last processed node
+ this.debugging = env.conf.parsoid.debug ||
+ (env.conf.parsoid.traceFlags &&
env.conf.parsoid.traceFlags.indexOf('selser') !== -1);
+ this.debug = this.debugging ? console.log : function(){};
}
var DDP = DOMDiff.prototype;
@@ -28,12 +25,13 @@
// work on a cloned copy of the passed-in node
var workNode = node.cloneNode(true);
- // First do a quick check on the nodes themselves
+ // SSS FIXME: Is this required?
+ //
+ // First do a quick check on the top-level nodes themselves
if (!this.treeEquals(this.env.page.dom, workNode, false)) {
this.markNode(workNode, 'modified');
return { isEmpty: false, dom: workNode };
}
-
// The root nodes are equal, call recursive differ
var foundChange = this.doDOMDiff(this.env.page.dom, workNode);
@@ -173,8 +171,10 @@
lookaheadNode = null,
foundDiffOverall = false;
while ( baseNode && newNode ) {
- // console.warn("--> A: " + (DU.isElt(baseNode) ?
baseNode.outerHTML : JSON.stringify(baseNode.nodeValue)));
- // console.warn("--> B: " + (DU.isElt(newNode) ?
newNode.outerHTML : JSON.stringify(newNode.nodeValue)));
+ if (this.debugging) {
+ console.warn("--> A: " + (DU.isElt(baseNode) ?
baseNode.outerHTML : JSON.stringify(baseNode.nodeValue)));
+ console.warn("--> B: " + (DU.isElt(newNode) ?
newNode.outerHTML : JSON.stringify(newNode.nodeValue)));
+ }
// Quick shallow equality check first
if ( ! this.treeEquals(baseNode, newNode, false) ) {
@@ -186,7 +186,7 @@
// look-ahead in *new* DOM to detect insertions
if (!canBeIgnored(baseNode)) {
- // console.warn("--lookahead in new dom--");
+ this.debug("--lookahead in new dom--");
lookaheadNode = newNode.nextSibling;
while (lookaheadNode) {
if (!canBeIgnored(lookaheadNode) &&
@@ -208,7 +208,7 @@
// look-ahead in *base* DOM to detect deletions
if (!foundDiff && !canBeIgnored(newNode)) {
- // console.warn("--lookahead in old dom--");
+ this.debug("--lookahead in old dom--");
lookaheadNode = baseNode.nextSibling;
while (lookaheadNode) {
if (!canBeIgnored(lookaheadNode) &&
@@ -226,14 +226,19 @@
}
}
- // If we never found a diff through lookaheads,
reconsider
- // the original node, mark it modified, and recurse
into subtrees.
if (!foundDiff) {
- this.markNode(origNode, 'modified');
- this.doDOMDiff(baseNode, origNode);
+ if (origNode.nodeName === baseNode.nodeName) {
+ // Identical wrapper-type, but modified.
+ // Mark as modified, and recurse.
+ this.markNode(origNode,
'modified-wrapper');
+ this.doDOMDiff(baseNode, origNode);
+ } else {
+ // Mark the sub-tree as modified since
+ // we have two entirely different nodes
here
+ this.markNode(origNode, 'modified');
+ }
}
- // nothing found, mark new node as modified / differing
foundDiffOverall = true;
} else if(!DU.isTplElementNode(this.env, newNode)) {
// Recursively diff subtrees if not template-like
content
@@ -267,8 +272,6 @@
};
-
-
/******************************************************
* Helpers
*****************************************************/
@@ -279,7 +282,6 @@
// insert a meta tag marking the place where content used to be
DU.prependTypedMeta(node, 'mw:DiffMarker');
} else {
- // modification/insertion marker
if (node.nodeType === node.ELEMENT_NODE) {
DU.setDiffMark(node, this.env, change);
} else if (node.nodeType !== node.TEXT_NODE && node.nodeType
!== node.COMMENT_NODE) {
diff --git a/js/lib/mediawiki.DOMUtils.js b/js/lib/mediawiki.DOMUtils.js
index beabf9c..b23a677 100644
--- a/js/lib/mediawiki.DOMUtils.js
+++ b/js/lib/mediawiki.DOMUtils.js
@@ -419,12 +419,26 @@
);
},
- hasCurrentDiffMark: function(node, env) {
+ currentDiffMark: function(node, env) {
if (!node || !this.isElt(node)) {
return false;
}
- var dpd = this.getJSONAttribute(node, 'data-parsoid-diff',
null);
- return dpd !== null && dpd.id === env.page.id;
+ if ( !( node.data && node.data["parsoid-diff"] ) ) {
+ this.loadDataAttrib(node, "parsoid-diff");
+ }
+ var dpd = node.data["parsoid-diff"];
+ return dpd !== {} && dpd.id === env.page.id ? dpd : null;
+ },
+
+ hasCurrentDiffMark: function(node, env) {
+ return this.currentDiffMark(node, env) !== null;
+ },
+
+ hasInsertedOrModifiedDiffMark: function(node, env) {
+ var diffMark = this.currentDiffMark(node, env);
+ return diffMark &&
+ (diffMark.diff.indexOf('modified') >= 0 ||
+ diffMark.diff.indexOf('inserted') >= 0);
},
setDiffMark: function(node, env, change) {
@@ -452,40 +466,6 @@
return node.nodeType === node.TEXT_NODE &&
// ws-only
node.nodeValue.match(/^\s*$/);
- },
-
- isNonContentNode: function(node) {
- return node.nodeType === node.COMMENT_NODE ||
- this.isIEW(node) ||
- this.isMarkerMeta(node, "mw:DiffMarker");
- },
-
- /**
- * Get the first child element or non-IEW text node, ignoring
- * whitespace-only text nodes and comments.
- */
- getFirstNonSepChildNode: function(node) {
- var child = node.firstChild;
- while (child && this.isNonContentNode(child)) {
- child = child.nextSibling;
- }
- return child;
- },
-
- previousNonSepSibling: function (node) {
- var prev = node.previousSibling;
- while (prev && this.isNonContentNode(prev)) {
- prev = prev.previousSibling;
- }
- return prev;
- },
-
- nextNonSepSibling: function (node) {
- var next = node.nextSibling;
- while (next && this.isNonContentNode(next)) {
- next = next.nextSibling;
- }
- return next;
},
/**
diff --git a/js/lib/mediawiki.WikitextSerializer.js
b/js/lib/mediawiki.WikitextSerializer.js
index 21320f5..82f4cf4 100644
--- a/js/lib/mediawiki.WikitextSerializer.js
+++ b/js/lib/mediawiki.WikitextSerializer.js
@@ -3015,7 +3015,7 @@
}
var handled = false;
- if (state.selserMode) {
+ if (state.selserMode && !state.inModifiedContent) {
// To serialize from source, we need 2 things
of the node:
// -- it should not have a diff marker
// -- it should have valid, usable DSR
@@ -3073,6 +3073,9 @@
if ( !handled ) {
state.prevNodeUnmodified =
state.currNodeUnmodified;
state.currNodeUnmodified = false;
+ if (state.selserMode &&
DU.hasInsertedOrModifiedDiffMark(node, this.env)) {
+ state.inModifiedContent = true;
+ }
// console.warn("USED NEW");
if ( domHandler && domHandler.handle ) {
// DOM-based serialization
@@ -3089,6 +3092,7 @@
// Used to be token-based serialization
console.error('No dom handler found
for', node.outerHTML);
}
+ state.inModifiedContent = false;
}
// Update end separator constraints
--
To view, visit https://gerrit.wikimedia.org/r/59421
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9895f079d607abcebee0ccee710f9a350411935e
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Parsoid
Gerrit-Branch: master
Gerrit-Owner: Subramanya Sastry <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits