mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Cite
synced 2024-12-23 20:12:57 +00:00
b3e8737829
Cite's MWDocumentReferences included a Document, which caused auto-save serialization to fail silently on the cyclical reference. This patch moves the caching to per-instance scope, which was the better choice to begin with. The document refs are recalculated after each change anyway, and caching is only necessary to work around an awkward control flow in which each ReferenceNode is responsible for its footnote number. Bug: T377484 Change-Id: Iebe4befd603fe07d9da2a5bb6126228ec4d5dfea
136 lines
4 KiB
JavaScript
136 lines
4 KiB
JavaScript
'use strict';
|
|
|
|
/*!
|
|
* @copyright 2024 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt
|
|
* @license MIT
|
|
*/
|
|
|
|
/**
|
|
* A facade providing a simplified and safe interface to Cite `ref` and
|
|
* `references` tags in a document.
|
|
*
|
|
* @constructor
|
|
* @mixes OO.EventEmitter
|
|
* @param {ve.dm.Document} doc The document that reference tags will be embedded in.
|
|
*/
|
|
ve.dm.MWDocumentReferences = function VeDmMWDocumentReferences( doc ) {
|
|
// Mixin constructors
|
|
OO.EventEmitter.call( this );
|
|
|
|
// Properties
|
|
this.doc = doc;
|
|
/**
|
|
* Holds the information calculated for each group.
|
|
*
|
|
* @member {Object.<string, ve.dm.MWGroupReferences>}
|
|
*/
|
|
this.cachedByGroup = {};
|
|
|
|
doc.getInternalList().connect( this, { update: 'updateGroups' } );
|
|
this.updateAllGroups();
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.mixinClass( ve.dm.MWDocumentReferences, OO.EventEmitter );
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* Singleton MWDocumentReferences for a document.
|
|
*
|
|
* @param {ve.dm.Document} doc Source document associated with the
|
|
* singleton. May be a fragment in which case we only look at refs included in
|
|
* the fragment.
|
|
*
|
|
* @return {ve.dm.MWDocumentReferences} Singleton docRefs
|
|
*/
|
|
ve.dm.MWDocumentReferences.static.refsForDoc = function ( doc ) {
|
|
let docRefs;
|
|
// Only use cache if we're working with the full document.
|
|
if ( !doc.getOriginalDocument() ) {
|
|
docRefs = doc.extCiteDocumentReferences;
|
|
}
|
|
if ( docRefs === undefined ) {
|
|
docRefs = new ve.dm.MWDocumentReferences( doc );
|
|
}
|
|
if ( !doc.getOriginalDocument() ) {
|
|
doc.extCiteDocumentReferences = docRefs;
|
|
}
|
|
return docRefs;
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
ve.dm.MWDocumentReferences.prototype.updateAllGroups = function () {
|
|
this.updateGroups( this.getAllGroupNames() );
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {string[]} groupsChanged A list of group names which have changed in
|
|
* this transaction
|
|
*/
|
|
ve.dm.MWDocumentReferences.prototype.updateGroups = function ( groupsChanged ) {
|
|
groupsChanged.forEach( ( groupName ) => this.updateGroup( groupName ) );
|
|
};
|
|
|
|
/**
|
|
* @private
|
|
* @param {string[]} groupName Name of the reference group which needs to be
|
|
* updated, with prefix
|
|
*/
|
|
ve.dm.MWDocumentReferences.prototype.updateGroup = function ( groupName ) {
|
|
const nodeGroup = this.doc.getInternalList().getNodeGroup( groupName );
|
|
this.cachedByGroup[ groupName ] = ve.dm.MWGroupReferences.static.makeGroupRefs( nodeGroup );
|
|
};
|
|
|
|
/**
|
|
* @param {string} groupName with or without prefix
|
|
* @return {ve.dm.MWGroupReferences}
|
|
*/
|
|
ve.dm.MWDocumentReferences.prototype.getGroupRefs = function ( groupName ) {
|
|
return this.cachedByGroup[ groupName.startsWith( 'mwReference/' ) ? groupName : 'mwReference/' + groupName ] ||
|
|
new ve.dm.MWGroupReferences();
|
|
};
|
|
|
|
ve.dm.MWDocumentReferences.prototype.getAllGroupNames = function () {
|
|
return Object.keys( this.doc.getInternalList().getNodeGroups() );
|
|
};
|
|
|
|
ve.dm.MWDocumentReferences.prototype.hasRefs = function () {
|
|
return this.getAllGroupNames().some( ( groupName ) => !this.getGroupRefs( groupName ).isEmpty() );
|
|
};
|
|
|
|
/**
|
|
* Return a formatted number, in the content script, with no separators.
|
|
*
|
|
* Partial clone of mw.language.convertNumber .
|
|
*
|
|
* @param {number} num
|
|
* @return {string}
|
|
*/
|
|
ve.dm.MWDocumentReferences.static.contentLangDigits = function ( num ) {
|
|
const contentLang = mw.config.get( 'wgContentLanguage' );
|
|
const digitLookup = mw.config.get( 'wgTranslateNumerals' ) &&
|
|
mw.language.getData( contentLang, 'digitTransformTable' );
|
|
const numString = String( num );
|
|
if ( !digitLookup ) {
|
|
return numString;
|
|
}
|
|
return numString.split( '' ).map( ( numChar ) => digitLookup[ numChar ] ).join( '' );
|
|
};
|
|
|
|
/**
|
|
* @deprecated Should be refactored to store formatted index numbers as a simple
|
|
* property on each CE ref node after document transaction.
|
|
* @param {string} groupName Ref group without prefix
|
|
* @param {string} listKey Ref key with prefix
|
|
* @return {string} Rendered index number string which can be used as a footnote
|
|
* marker or reflist item number.
|
|
*/
|
|
ve.dm.MWDocumentReferences.prototype.getIndexLabel = function ( groupName, listKey ) {
|
|
return this.getGroupRefs( groupName ).getIndexLabel( listKey );
|
|
};
|