jenkins-bot has submitted this change and it was merged.

Change subject: Make <ref>s nested in <references> editable.
......................................................................


Make <ref>s nested in <references> editable.

* Track <ref>s birthed in <references> tags and capture their
  HTML and set <references>.data-mw.body.html to the concatenated
  HTML for all those child <ref> tags.

* No change in parser-tests because our test normalization code
  strips data-mw before comparing results.  Since this patch
  only changes data-mw output for "References: 5. ..." test,
  there is no change.  In any case, this patch updates the
  data-mw output for the test in question so that if we do
  modify our normalization routines, the test will still pass.

Change-Id: Iaea752dec03e5e7f0d36baf3b7a9973f1b85e8a5
---
M js/lib/ext.Cite.js
M js/lib/ext.core.TemplateHandler.js
M js/tests/parserTests.txt
3 files changed, 87 insertions(+), 57 deletions(-)

Approvals:
  Cscott: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/js/lib/ext.Cite.js b/js/lib/ext.Cite.js
index 7bdb220..c7e6bab 100644
--- a/js/lib/ext.Cite.js
+++ b/js/lib/ext.Cite.js
@@ -102,7 +102,7 @@
 
        var inReferencesExt = pipelineOpts.extTag === "references",
                refOpts = $.extend({ name: null, group: null }, 
Util.KVtoHash(refTok.getAttribute("options"))),
-               about = inReferencesExt ? '' : manager.env.newAboutId(),
+               about = manager.env.newAboutId(),
                finalCB = function(toks, content) {
                        // Marker meta with ref content
                        var da = Util.clone(refTok.dataAttribs);
@@ -264,6 +264,21 @@
                setRefGroup(this.refGroups, group, undefined);
        } else {
                this.refGroups = {};
+               /* 
-----------------------------------------------------------------
+                * Map: references-about-id --> HTML of any nested refs
+                *
+                * Ex: Given this wikitext:
+                *
+                *   <references> <ref>foo</ref> </references>
+                *   <references> <ref>bar</ref> </references>
+                *
+                * during processing, each of the references tag gets an 
about-id
+                * assigned to it.  The ref-tags nested inside it have a 
data-attribute
+                * with the references about-id.  When processing the 
ref-tokens and
+                * generating the HTML, we then collect the HTML for each nested
+                * ref-token and add it to this map by about-id.
+                * 
----------------------------------------------------------------- */
+               this.nestedRefsHTMLMap = {};
        }
 };
 
@@ -287,16 +302,19 @@
                group = null;
        }
 
+       // Assign an about id and intialize the nested refs html
+       var referencesId = manager.env.newAboutId();
+       this.nestedRefsHTMLMap[referencesId] = ["\n"];
+
        // Emit a marker mw:DOMFragment for the references
        // token so that the dom post processor can generate
        // and emit references at this point in the DOM.
        var emitReferencesFragment = function() {
-               var about = manager.env.newAboutId(),
-                       type = refsTok.getAttribute('typeof');
+               var type = refsTok.getAttribute('typeof');
                var buf = [
                        "<ol class='references'",
                        " typeof='", "mw:Extension/references", "'",
-                       " about='", about, "'",
+                       " about='", referencesId, "'",
                        "></ol>"
                ];
 
@@ -308,6 +326,7 @@
                if (group) {
                        dp.group = group;
                }
+
                DU.setJSONAttribute(ol, "data-parsoid", dp);
 
                var expansion = {
@@ -321,7 +340,7 @@
                // into Util and pass env into it .. can avoid extending 
ExtensionHandler
                // as well.
                this.manager = manager;
-               cb({ tokens: this.encapsulateExpansionHTML(refsTok, expansion), 
async: false });
+               cb({ tokens: this.encapsulateExpansionHTML(refsTok, expansion, 
referencesId), async: false });
        }.bind(this);
 
        processExtSource(manager, refsTok, {
@@ -345,6 +364,7 @@
                                        t.name === 'meta' &&
                                        
/^mw:Extension\/ref\/Marker$/.test(t.getAttribute('typeof')))
                                {
+                                       t.setAttribute("references-id", 
referencesId);
                                        res.push(t);
                                }
                        }
@@ -357,7 +377,6 @@
 };
 
 References.prototype.extractRefFromNode = function(node) {
-
        var group = node.getAttribute("group"),
                refName = node.getAttribute("name"),
                about = node.getAttribute("about"),
@@ -367,52 +386,55 @@
                nodeType = (node.getAttribute("typeof") || 
'').replace(/mw:Extension\/ref\/Marker/, '');
 
        // Add ref-index linkback
-       if (!skipLinkback) {
-               var doc = node.ownerDocument,
-                       span = doc.createElement('span'),
-                       content = node.getAttribute("content"),
-                       dataMW = node.getAttribute('data-mw');
+       var doc = node.ownerDocument,
+               span = doc.createElement('span'),
+               content = node.getAttribute("content"),
+               dataMW = node.getAttribute('data-mw');
 
-               if (!dataMW) {
-                       dataMW = JSON.stringify({
-                               'name': 'ref',
-                               // Dont set body if this is a reused reference
-                               // like <ref name='..' /> with empty content.
-                               'body': content ? { 'html': content } : 
undefined,
-                               'attrs': {
-                                       // Dont emit empty keys
-                                       'group': group || undefined,
-                                       'name': refName || undefined
-                               }
-                       });
-               }
-
-               DU.addAttributes(span, {
-                       'about': about,
-                       'class': 'reference',
-                       'data-mw': dataMW,
-                       'id': ref.linkbacks[ref.linkbacks.length - 1],
-                       'rel': 'dc:references',
-                       'typeof': nodeType
-               });
-               DU.addTypeOf(span, "mw:Extension/ref");
-               span.data = {
-                       parsoid: {
-                               src: node.data.parsoid.src,
-                               dsr: node.data.parsoid.dsr
+       if (!dataMW) {
+               dataMW = JSON.stringify({
+                       'name': 'ref',
+                       // Dont set body if this is a reused reference
+                       // like <ref name='..' /> with empty content.
+                       'body': content ? { 'html': content } : undefined,
+                       'attrs': {
+                               // Dont emit empty keys
+                               'group': group || undefined,
+                               'name': refName || undefined
                        }
-               };
+               });
+       }
 
+       DU.addAttributes(span, {
+               'about': about,
+               'class': 'reference',
+               'data-mw': dataMW,
+               'id': skipLinkback ? undefined : 
ref.linkbacks[ref.linkbacks.length - 1],
+               'rel': 'dc:references',
+               'typeof': nodeType
+       });
+       DU.addTypeOf(span, "mw:Extension/ref");
+       span.data = {
+               parsoid: {
+                       src: node.data.parsoid.src,
+                       dsr: node.data.parsoid.dsr
+               }
+       };
+
+       // refIndex-a
+       var refIndex = doc.createElement('a');
+       refIndex.setAttribute('href', '#' + ref.target);
+       refIndex.appendChild(doc.createTextNode(
+               '[' + ((group === '') ? '' : group + ' ') + ref.groupIndex + ']'
+       ));
+       span.appendChild(refIndex);
+
+       if (!skipLinkback) {
                // refIndex-span
                node.parentNode.insertBefore(span, node);
-
-               // refIndex-a
-               var refIndex = doc.createElement('a');
-               refIndex.setAttribute('href', '#' + ref.target);
-               refIndex.appendChild(doc.createTextNode(
-                       '[' + ((group === '') ? '' : group + ' ') + 
ref.groupIndex + ']'
-               ));
-               span.appendChild(refIndex);
+       } else {
+               var referencesAboutId = node.getAttribute("references-id");
+               this.nestedRefsHTMLMap[referencesAboutId].push(span.outerHTML, 
"\n");
        }
 
        // This effectively ignores content from later references with the same 
name.
@@ -433,13 +455,21 @@
 
        var dataMW = refsNode.getAttribute('data-mw');
        if (!dataMW) {
+               var datamwBody;
+               // We'll have to output data-mw.body.extsrc in
+               // scenarios where original wikitext was of the form:
+               // "<references> lot of refs here </references>"
+               // Ex: See [[en:Barack Obama]]
+               if (body.length > 0) {
+                       datamwBody = {
+                               'extsrc': body,
+                               'html': this.nestedRefsHTMLMap[about].join('')
+                       };
+               }
+
                dataMW = JSON.stringify({
                        'name': 'references',
-                       // We'll have to output data-mw.body.extsrc in
-                       // scenarios where original wikitext was of the form:
-                       // "<references> lot of refs here </references>"
-                       // Ex: See [[en:Barack Obama]]
-                       'body': body.length > 0 ? { 'extsrc': body } : 
undefined,
+                       'body': datamwBody,
                        'attrs': {
                                // Dont emit empty keys
                                'group': group || undefined
@@ -471,9 +501,9 @@
        this.references = new References(this);
 };
 
-Cite.prototype.resetState = function(group) {
+Cite.prototype.resetState = function() {
        this.ref.reset();
-       this.references.reset(group);
+       this.references.reset();
 };
 
 if (typeof module === "object") {
diff --git a/js/lib/ext.core.TemplateHandler.js 
b/js/lib/ext.core.TemplateHandler.js
index e8ac1f3..eb529b4 100644
--- a/js/lib/ext.core.TemplateHandler.js
+++ b/js/lib/ext.core.TemplateHandler.js
@@ -50,9 +50,9 @@
  * wrapper that is later unpacked in the DOMPostProcessor. Used both for
  * transclusion and extension content.
  */
-TemplateHandler.prototype.encapsulateExpansionHTML = function(token, 
expansion) {
+TemplateHandler.prototype.encapsulateExpansionHTML = function(token, 
expansion, aboutId) {
        var toks = DU.getWrapperTokens(expansion.nodes),
-               about = this.manager.env.newAboutId();
+               about = aboutId || this.manager.env.newAboutId();
 
        // Assign the HTML fragment to the data-parsoid.html on the first 
wrapper token.
        toks[0].dataAttribs.html = expansion.html;
diff --git a/js/tests/parserTests.txt b/js/tests/parserTests.txt
index 6ee3ded..c3563df 100644
--- a/js/tests/parserTests.txt
+++ b/js/tests/parserTests.txt
@@ -15019,7 +15019,7 @@
 <p>A <span about="#mwt2" class="reference" 
data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-0" 
rel="dc:references" typeof="mw:Extension/ref"><a 
href="#cite_note-a-1">[1]</a></span>
 B <span about="#mwt4" class="reference" 
data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' 
id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref"><a 
href="#cite_note-b-2">[2]</a></span></p>
 
-<ol about="#mwt7" class="references" 
data-mw='{"name":"references","body":{"extsrc":"<ref name=\"a\">foo</ref>\nThis 
should just get lost."},"attrs":{}}' typeof="mw:Extension/references"><li 
about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy"><a 
href="#cite_ref-a-1-0">↑</a></span> foo</li><li about="#cite_note-b-2" 
id="cite_note-b-2"><span rel="mw:referencedBy"><a 
href="#cite_ref-b-2-0">↑</a></span> bar</li></ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" 
data-mw='{"name":"references","body":{"extsrc":"<ref name=\"a\">foo</ref>\nThis 
should just get lost.","html":"<span about=\"#mwt8\" class=\"reference\" 
data-mw=\"{&amp;quot;name&amp;quot;:&amp;quot;ref&amp;quot;,&amp;quot;body&amp;quot;:{&amp;quot;html&amp;quot;:&amp;quot;foo&amp;quot;},&amp;quot;attrs&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;a&amp;quot;}}\"
 rel=\"dc:references\" typeof=\"mw:Extension/ref\"><a 
href=\"#cite_note-a-1\">[1]</a></span>"},"attrs":{}}'><li 
about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy"><a 
href="#cite_ref-a-1-0">↑</a></span> foo</li><li about="#cite_note-b-2" 
id="cite_note-b-2"><span rel="mw:referencedBy"><a 
href="#cite_ref-b-2-0">↑</a></span> bar</li></ol>
 !!end
 
 !!test

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Iaea752dec03e5e7f0d36baf3b7a9973f1b85e8a5
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/extensions/Parsoid
Gerrit-Branch: master
Gerrit-Owner: Subramanya Sastry <[email protected]>
Gerrit-Reviewer: Cscott <[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

Reply via email to