jenkins-bot has submitted this change and it was merged. Change subject: T93973: Remove state from Cite extension ......................................................................
T93973: Remove state from Cite extension Keep all state in the DOM post-processor in dom.processRefs.js, so that there's no need to reset the extension and it can be safely used for multiple documents Change-Id: Iacf7e3003929f74b76774d3e765c792991700e51 --- M lib/dom.processRefs.js M lib/ext.Cite.js 2 files changed, 96 insertions(+), 97 deletions(-) Approvals: Subramanya Sastry: Looks good to me, approved jenkins-bot: Verified diff --git a/lib/dom.processRefs.js b/lib/dom.processRefs.js index 18a0b62..c73f56d 100644 --- a/lib/dom.processRefs.js +++ b/lib/dom.processRefs.js @@ -1,6 +1,7 @@ "use strict"; -var DU = require('./mediawiki.DOMUtils.js').DOMUtils; +var DU = require('./mediawiki.DOMUtils.js').DOMUtils, + ReferencesData = require('./ext.Cite.js').ReferencesData; /* -------------------------------------------- * This handles wikitext like this: @@ -10,17 +11,19 @@ * -------------------------------------------- */ var _processRefs, _processRefsInReferences; -_processRefsInReferences = function(cite, node, referencesId, referencesGroup, nestedRefsHTML) { +_processRefsInReferences = function(cite, refsData, node, referencesId, + referencesGroup, nestedRefsHTML) { var child = node.firstChild; while (child !== null) { var nextChild = child.nextSibling; if (DU.isElt(child)) { var typeOf = child.getAttribute('typeof'); if ((/(?:^|\s)mw:Extension\/ref\/Marker(?=$|\s)/).test(typeOf)) { - cite.references.extractRefFromNode(child, - _processRefs.bind(null, cite), referencesId, referencesGroup, nestedRefsHTML); + cite.references.extractRefFromNode(child, refsData, + _processRefs.bind(null, cite, refsData), + referencesId, referencesGroup, nestedRefsHTML); } else if (child.childNodes.length > 0) { - _processRefsInReferences(cite, + _processRefsInReferences(cite, refsData, child, referencesId, referencesGroup, nestedRefsHTML); } } @@ -29,23 +32,23 @@ } }; -_processRefs = function(cite, node) { +_processRefs = function(cite, refsData, node) { var child = node.firstChild; while (child !== null) { var nextChild = child.nextSibling; if (DU.isElt(child)) { var typeOf = child.getAttribute('typeof'); if ((/(?:^|\s)mw:Extension\/ref\/Marker(?=$|\s)/).test(typeOf)) { - cite.references.extractRefFromNode(child, _processRefs.bind(null, cite)); + cite.references.extractRefFromNode(child, refsData, _processRefs.bind(null, cite)); } else if ((/(?:^|\s)mw:Extension\/references(?=$|\s)/).test(typeOf)) { var referencesId = child.getAttribute("about"); var referencesGroup = DU.getDataParsoid(child).group; var nestedRefsHTML = ["\n"]; - _processRefsInReferences(cite, + _processRefsInReferences(cite, refsData, child, referencesId, referencesGroup, nestedRefsHTML); - cite.references.insertReferencesIntoDOM(child, nestedRefsHTML); + cite.references.insertReferencesIntoDOM(child, refsData, nestedRefsHTML); } else if (child.childNodes.length > 0) { - _processRefs(cite, child); + _processRefs(cite, refsData, child); } } @@ -55,15 +58,9 @@ function processRefs(cite, node, env, options, atTopLevel) { if (atTopLevel) { - _processRefs(cite, node); - cite.references.insertMissingReferencesIntoDOM(env, node); - // We have a broken design where all native extension objects - // are reused across all documents. So, given that Cite is - // maintaining object state (during a sync pass => it need not do that), - // we need to reset state so that other documents that are - // in the middle of being processed don't use that state. - // Future patches will fix both of these design issues. - cite.resetState({toplevel: true}); + var refsData = new ReferencesData(); + _processRefs(cite, refsData, node); + cite.references.insertMissingReferencesIntoDOM(env, refsData, node); } } diff --git a/lib/ext.Cite.js b/lib/ext.Cite.js index 0e11b86..80f6076 100644 --- a/lib/ext.Cite.js +++ b/lib/ext.Cite.js @@ -161,53 +161,6 @@ return encodeURIComponent(v).replace(/%/g,"."); } -RefGroup.prototype.add = function(references, refName, about, skipLinkback) { - var ref; - refName = makeValidIdAttr(refName); - if ( refName && this.indexByName.has( refName ) ) { - ref = this.indexByName.get( refName ); - if (ref.content) { - ref.hasMultiples = true; - } - } else { - // The ids produced Cite.php have some particulars: - // Simple refs get 'cite_ref-' + index - // Refs with names get 'cite_ref-' + name + '_' + index + (backlink num || 0) - // Notes (references) whose ref doesn't have a name are 'cite_note-' + index - // Notes whose ref has a name are 'cite_note-' + name + '-' + index - var n = references.index, - refKey = (1+n) + '', - refIdBase = 'cite_ref-' + (refName ? refName + '_' + refKey : refKey), - noteId = 'cite_note-' + (refName ? refName + '-' + refKey : refKey); - - // bump index - references.index += 1; - - ref = { - about: about, - content: null, - group: this.name, - groupIndex: this.refs.length + 1, - index: n, - key: refIdBase, - id: (refName ? refIdBase + '-0' : refIdBase), - linkbacks: [], - name: refName, - target: noteId - }; - this.refs.push( ref ); - if (refName) { - this.indexByName.set( refName, ref ); - } - } - - if (!skipLinkback) { - ref.linkbacks.push(ref.key + '-' + ref.linkbacks.length); - } - - return ref; -}; - RefGroup.prototype.renderLine = function(refsList, ref) { var ownerDoc = refsList.ownerDocument, arrow = ownerDoc.createTextNode('↑'), @@ -262,32 +215,80 @@ refsList.appendChild(li); }; -function getRefGroup(refGroups, groupName, allocIfMissing) { - groupName = groupName || ''; - if ( !refGroups.has( groupName ) && allocIfMissing ) { - refGroups.set( groupName, new RefGroup( groupName ) ); - } - return refGroups.get( groupName ); +function ReferencesData() { + this.index = 0; + this.refGroups = new Map(); } + +ReferencesData.prototype.getRefGroup = function (groupName, allocIfMissing) { + groupName = groupName || ''; + if ( !this.refGroups.has( groupName ) && allocIfMissing ) { + this.refGroups.set( groupName, new RefGroup( groupName ) ); + } + return this.refGroups.get( groupName ); +}; + +ReferencesData.prototype.removeRefGroup = function (groupName) { + if (groupName !== null && groupName !== undefined) { + // '' is a valid group (the default group) + this.refGroups.delete(groupName); + } +}; + +ReferencesData.prototype.add = function(groupName, refName, about, skipLinkback) { + var group = this.getRefGroup(groupName, true), + ref; + refName = makeValidIdAttr(refName); + if ( refName && group.indexByName.has( refName ) ) { + ref = group.indexByName.get( refName ); + if (ref.content) { + ref.hasMultiples = true; + } + } else { + // The ids produced Cite.php have some particulars: + // Simple refs get 'cite_ref-' + index + // Refs with names get 'cite_ref-' + name + '_' + index + (backlink num || 0) + // Notes (references) whose ref doesn't have a name are 'cite_note-' + index + // Notes whose ref has a name are 'cite_note-' + name + '-' + index + var n = this.index, + refKey = (1+n) + '', + refIdBase = 'cite_ref-' + (refName ? refName + '_' + refKey : refKey), + noteId = 'cite_note-' + (refName ? refName + '-' + refKey : refKey); + + // bump index + this.index += 1; + + ref = { + about: about, + content: null, + group: group.name, + groupIndex: group.refs.length + 1, + index: n, + key: refIdBase, + id: (refName ? refIdBase + '-0' : refIdBase), + linkbacks: [], + name: refName, + target: noteId + }; + group.refs.push( ref ); + if (refName) { + group.indexByName.set( refName, ref ); + } + } + + if (!skipLinkback) { + ref.linkbacks.push(ref.key + '-' + ref.linkbacks.length); + } + + return ref; +}; function References(cite) { this.cite = cite; - this.reset( null, true ); + this.reset(); } -References.prototype.reset = function( group, resetIndex ) { - if (group !== null && group !== undefined) { - // '' is a valid group (the default group) - this.refGroups.delete(group); - } else { - this.refGroups = new Map(); - } - - // restart reference counter - if ( resetIndex ) { - this.index = 0; - } -}; +References.prototype.reset = function() {}; /** * Sanitize the references tag and convert it into a meta-token @@ -357,7 +358,8 @@ }); }; -References.prototype.extractRefFromNode = function(node, refInRefProcessor, referencesAboutId, referencesGroup, refsInReferencesHTML) { +References.prototype.extractRefFromNode = function(node, refsData, + refInRefProcessor, referencesAboutId, referencesGroup, refsInReferencesHTML) { var nestedInReferences = referencesAboutId !== undefined, dp = DU.getDataParsoid( node ), // SSS FIXME: Need to clarify semantics here. @@ -366,8 +368,7 @@ group = dp.group || referencesGroup || '', refName = dp.name, about = node.getAttribute("about"), - refGroup = getRefGroup(this.refGroups, group, true), - ref = refGroup.add(this, refName, about, nestedInReferences), + ref = refsData.add(group, refName, about, nestedInReferences), nodeType = (node.getAttribute("typeof") || '').replace(/mw:Extension\/ref\/Marker/, ''); // Add ref-index linkback @@ -449,14 +450,14 @@ } }; -References.prototype.insertReferencesIntoDOM = function(refsNode, refsInReferencesHTML) { +References.prototype.insertReferencesIntoDOM = function(refsNode, refsData, refsInReferencesHTML) { var about = refsNode.getAttribute('about'), dp = DU.getDataParsoid( refsNode ), group = dp.group || '', src = dp.src || '<references/>', // fall back so we don't crash // Extract ext-source for <references>..</references> usage body = Util.extractExtBody("references", src).trim(), - refGroup = getRefGroup(this.refGroups, group); + refGroup = refsData.getRefGroup(group); var dataMW = DU.getDataMw(refsNode); if (!Object.keys(dataMW).length) { @@ -495,15 +496,15 @@ refGroup.refs.forEach(refGroup.renderLine.bind(refGroup, refsNode)); } - // reset - this.reset(group); + // Remove the group from refsData + refsData.removeRefGroup(group); }; -References.prototype.insertMissingReferencesIntoDOM = function (env, node) { +References.prototype.insertMissingReferencesIntoDOM = function (env, refsData, node) { var doc = node.ownerDocument, self = this; - this.refGroups.forEach(function (refsData, refsGroup) { + refsData.refGroups.forEach(function (refsValue, refsGroup) { var ol = doc.createElement('ol'), dp = DU.getDataParsoid(ol); DU.addAttributes(ol, { @@ -523,7 +524,7 @@ // each <references /> tag appears on its own line. node.appendChild(doc.createTextNode("\n")); node.appendChild(ol); - self.insertReferencesIntoDOM(ol, [""]); + self.insertReferencesIntoDOM(ol, refsData, [""]); }); }; @@ -539,10 +540,11 @@ Cite.prototype.resetState = function(opts) { if (opts && opts.toplevel) { this.ref.reset(); - this.references.reset( null, true ); + this.references.reset(); } }; if (typeof module === "object") { module.exports.Cite = Cite; + module.exports.ReferencesData = ReferencesData; } -- To view, visit https://gerrit.wikimedia.org/r/200881 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Iacf7e3003929f74b76774d3e765c792991700e51 Gerrit-PatchSet: 2 Gerrit-Project: mediawiki/services/parsoid Gerrit-Branch: master Gerrit-Owner: Marcoil <marc...@wikimedia.org> Gerrit-Reviewer: Arlolra <abrea...@wikimedia.org> Gerrit-Reviewer: Cscott <canan...@wikimedia.org> Gerrit-Reviewer: Marcoil <marc...@wikimedia.org> Gerrit-Reviewer: Subramanya Sastry <ssas...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits