Subramanya Sastry has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/89227


Change subject: Bug fix in aboutId assignment during DOM Fragment unpacking
......................................................................

Bug fix in aboutId assignment during DOM Fragment unpacking

* Page native dom-fragment content that is part of an encapsulation
  wrapper (say, transclusions) will have to assigned the about id
  of the dom-fragment wrapper.

* Added code to recognize when a node is an encapsulation wrapper
  node -- also renamed older badly named isEncapsulatedElt helper
  to isFirstEncapsulationWrapperNode.

* As far as foreign content goes, <figure> captions that get reused
  can have multiple independent encapsulated objects whose about ids
  will all have to be renamed. This requires an about-id map to
  correctly reassign about ids. Added this documentation in the
  code itself.

* No change in parser tests.

  TODO: We need a parser test with extensions in them.

  {{echo|<div>foo</div> <math>1+2</math> <div>bar</div>}} would
  not RT properly before this patch because the inner <math> node
  did not have the about-id as the surrounding <div>s. This patch
  fixes this.

  This should also fix a lot of the <timeline> regressions seen
  in latest RT testing.

Change-Id: I595e9f46d8ce789a05e4b7dd8b58e443e4c02f98
---
M js/lib/dom.cleanup.js
M js/lib/dom.minimizeTags.js
M js/lib/dom.minimizeWTQuoteTags.js
M js/lib/dom.t.TableFixups.js
M js/lib/dom.t.unpackDOMFragments.js
M js/lib/ext.core.TemplateHandler.js
M js/lib/mediawiki.DOMUtils.js
M js/lib/mediawiki.WikitextSerializer.js
8 files changed, 75 insertions(+), 24 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Parsoid 
refs/changes/27/89227/1

diff --git a/js/lib/dom.cleanup.js b/js/lib/dom.cleanup.js
index b51ec2d..e023b31 100644
--- a/js/lib/dom.cleanup.js
+++ b/js/lib/dom.cleanup.js
@@ -74,7 +74,7 @@
                        //
                        // But, do not zero it out if the node has template 
encapsulation
                        // information.  That will be disastrous (see bug 
52638, 52488).
-                       if (dp.fostered && dp.dsr && 
!DU.isEncapsulatedElt(node)) {
+                       if (dp.fostered && dp.dsr && 
!DU.isFirstEncapsulationWrapperNode(node)) {
                                dp.dsr[0] = dp.dsr[1];
                        }
                }
diff --git a/js/lib/dom.minimizeTags.js b/js/lib/dom.minimizeTags.js
index 2d61054..ca9963f 100644
--- a/js/lib/dom.minimizeTags.js
+++ b/js/lib/dom.minimizeTags.js
@@ -55,7 +55,7 @@
                var P = [];
                for (var i = 0; i < n; i++) {
                        var s = children[i];
-                       if (DU.isElt(s) && DU.isEncapsulatedElt(s)) {
+                       if (DU.isFirstEncapsulationWrapperNode(s)) {
                                // Dont descend into template generated content
                                P.push({path: [], orig_parent: node, children: 
[s]});
                        } else if (DU.isElt(s)) {
@@ -100,7 +100,7 @@
                // Do not cross into templates and block tags
                while (DU.isElt(node) &&
                        !DU.isBlockTag(node.nodeName) &&
-                       !DU.isEncapsulatedElt(node))
+                       !DU.isFirstEncapsulationWrapperNode(node))
                {
                        path.push(node);
                        children = node.childNodes;
diff --git a/js/lib/dom.minimizeWTQuoteTags.js 
b/js/lib/dom.minimizeWTQuoteTags.js
index f35f37a..a69a05f 100644
--- a/js/lib/dom.minimizeWTQuoteTags.js
+++ b/js/lib/dom.minimizeWTQuoteTags.js
@@ -61,7 +61,7 @@
  *    ==> <i>A<b>XY</b>Z</i>
  */
 function minimizeTags(node, rewriteablePair, recurse) {
-       if (DU.isEncapsulatedElt(node) || !node.firstChild) {
+       if (DU.isFirstEncapsulationWrapperNode(node) || !node.firstChild) {
                return;
        }
 
@@ -86,7 +86,10 @@
 
                // 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.isEncapsulatedElt(a) && 
!DU.isEncapsulatedElt(b)) {
+               if (rewriteablePair(a, b) &&
+                       !DU.isFirstEncapsulationWrapperNode(a) &&
+                       !DU.isFirstEncapsulationWrapperNode(b))
+               {
                        if (mergable(a, b)) {
                                a = merge(a, b);
                                // the new a's children have new siblings.  so 
let's look
diff --git a/js/lib/dom.t.TableFixups.js b/js/lib/dom.t.TableFixups.js
index ff08009..22b2021 100644
--- a/js/lib/dom.t.TableFixups.js
+++ b/js/lib/dom.t.TableFixups.js
@@ -49,7 +49,7 @@
            !DU.isLiteralHTMLNode(nextNode) &&
                DU.nodeEssentiallyEmpty(node) &&
                (// FIXME: will not be set for nested templates
-                DU.isEncapsulatedElt(nextNode) ||
+                DU.isFirstEncapsulationWrapperNode(nextNode) ||
                 // Hacky work-around for nested templates
                 /^{{.*?}}$/.test(nextNode.data.parsoid.src))
            )
@@ -92,7 +92,7 @@
 TableFixups.prototype.hasOnlyOneTransclusionChild = function (node) {
        var n = 0;
        node.childNodes.forEach(function(n) {
-               if(DU.isElt(n) && DU.isEncapsulatedElt(n)) {
+               if (DU.isFirstEncapsulationWrapperNode(n)) {
                        n++;
                }
                if (n > 1) {
diff --git a/js/lib/dom.t.unpackDOMFragments.js 
b/js/lib/dom.t.unpackDOMFragments.js
index 89b1810..a3aed49 100644
--- a/js/lib/dom.t.unpackDOMFragments.js
+++ b/js/lib/dom.t.unpackDOMFragments.js
@@ -139,28 +139,40 @@
                        }
 
                        var isForeignContent = 
node.data.parsoid.tmp.isForeignContent,
-                               aboutIdMap = {},
+                               isEncapsulatedContent = 
DU.isEncapsulationWrapper(node),
+                               aboutIdMap = new Map(),
                                n = dummyNode.firstChild;
                        while (n) {
-                               var next = n.nextSibling,
-                                       nAbout = n.getAttribute("about");
+                               var next = n.nextSibling;
 
-                               if (isForeignContent && nAbout) {
+                               if (isEncapsulatedContent) {
+                                       // Set about-id always to ensure the 
unwrapped node
+                                       // is recognized as encapsulated 
content as well.
+                                       n.setAttribute("about", about);
+                               } else if (isForeignContent) {
                                        // Replace old about-id with new 
about-id that is
-                                       // unique to the global page 
environment object
-                                       var newAbout = aboutIdMap[nAbout];
-                                       if (!newAbout) {
-                                               newAbout = env.newAboutId();
-                                               aboutIdMap[nAbout] = newAbout;
+                                       // unique to the global page 
environment object.
+                                       //
+                                       // <figure>s are reused from cache. 
Note that figure captions
+                                       // can contain multiple independent 
transclusions. Each one
+                                       // of those individual transclusions 
should get a new unique
+                                       // about id. Hence a need for an 
aboutIdMap.
+                                       var nAbout = n.getAttribute("about");
+                                       if (nAbout) {
+                                               var newAbout = 
aboutIdMap.get(nAbout);
+                                               if (!newAbout) {
+                                                       newAbout = 
env.newAboutId();
+                                                       aboutIdMap.set(nAbout, 
newAbout);
+                                               }
+                                               n.setAttribute("about", 
newAbout);
                                        }
-                                       n.setAttribute("about", newAbout);
                                } else {
                                        // Discard unnecessary span wrappers.
                                        //
                                        // If the node has an about-id on it, 
it is part of
                                        // transclusion or other generated 
content and is required.
                                        DU.loadDataParsoid(n);
-                                       if (n.data.parsoid.tmp.wrapper && 
!nAbout) {
+                                       if (n.data.parsoid.tmp.wrapper && 
!n.getAttribute("about")) {
                                                DU.migrateChildren(n, 
n.parentNode, n);
                                                DU.deleteNode(n);
                                        }
diff --git a/js/lib/ext.core.TemplateHandler.js 
b/js/lib/ext.core.TemplateHandler.js
index 7fa6448..6b06e05 100644
--- a/js/lib/ext.core.TemplateHandler.js
+++ b/js/lib/ext.core.TemplateHandler.js
@@ -108,7 +108,7 @@
                                // cache hit: reuse the expansion DOM
                                //console.log('cache hit for', 
JSON.stringify(text.substr(0, 50)));
                                var expansion = env.transclusionCache[text],
-                                       opts = {isForeignContent: true },
+                                       opts = { isForeignContent: true },
                                        toks = DU.encapsulateExpansionHTML(env, 
token, expansion, opts);
 
                                cb({ tokens: toks });
diff --git a/js/lib/mediawiki.DOMUtils.js b/js/lib/mediawiki.DOMUtils.js
index 599afc3..fb58fd4 100644
--- a/js/lib/mediawiki.DOMUtils.js
+++ b/js/lib/mediawiki.DOMUtils.js
@@ -636,10 +636,6 @@
                }
        },
 
-       isEncapsulatedElt: function(node) {
-               return this.isElt(node) && 
(/(?:^|\s)mw:(?:Transclusion(?=$|\s)|Param(?=$|\s)|Extension\/[^\s]+)/).test(node.getAttribute('typeof'));
-       },
-
        /**
         * Check if node is an ELEMENT node belongs to a template/extension.
         *
@@ -999,6 +995,46 @@
        },
 
        /**
+        * Is node the first wrapper element of encapsulated content?
+        */
+       isFirstEncapsulationWrapperNode: function(node) {
+               return this.isElt(node) && 
(/(?:^|\s)mw:(?:Transclusion(?=$|\s)|Param(?=$|\s)|Extension\/[^\s]+)/).test(node.getAttribute('typeof'));
+       },
+
+       /**
+        * Is node an encapsulation wrapper elt?
+        *
+        * All root-level nodes of generated content are considered
+        * encapsulation wrappers and share an about-id.
+        */
+       isEncapsulationWrapper: function(node) {
+               // True if it has an encapsulation type or while walking 
backwards
+               // over elts with identical about ids, we run into a node with 
an
+               // encapsulation type.
+               function hasRightType(n) {
+                       return 
(/(?:^|\s)mw:(?:Transclusion(?=$|\s)|Param(?=$|\s)|Extension\/[^\s]+)/).test(n.getAttribute("typeof"));
+               }
+
+               if (!this.isElt(node)) {
+                       return false;
+               }
+
+               var about = node.getAttribute('about');
+               if (!about) {
+                       return false;
+               }
+
+               while (!hasRightType(node)) {
+                       node = node.previousSibling;
+                       if (!node || !this.isElt(node) || 
node.getAttribute('about') !== about) {
+                               return false;
+                       }
+               }
+
+               return node !== null;
+       },
+
+       /**
         * Gets all siblings that follow 'node' that have an 'about' as
         * their about id.
         *
diff --git a/js/lib/mediawiki.WikitextSerializer.js 
b/js/lib/mediawiki.WikitextSerializer.js
index 8fc740d..aff76a0 100644
--- a/js/lib/mediawiki.WikitextSerializer.js
+++ b/js/lib/mediawiki.WikitextSerializer.js
@@ -2169,7 +2169,7 @@
 function wtListEOL(node, otherNode) {
        if (otherNode.nodeName === 'BODY' ||
                !DU.isElt(otherNode) ||
-               DU.isEncapsulatedElt(otherNode))
+               DU.isFirstEncapsulationWrapperNode(otherNode))
        {
                return {min:0, max:2};
        }

-- 
To view, visit https://gerrit.wikimedia.org/r/89227
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I595e9f46d8ce789a05e4b7dd8b58e443e4c02f98
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

Reply via email to