mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Cite
synced 2024-11-27 16:30:12 +00:00
Merge "[refactor] switch reflist rendering source of truth"
This commit is contained in:
commit
30de08bfe9
|
@ -71,6 +71,7 @@
|
|||
"localBasePath": "modules/ve-cite",
|
||||
"remoteExtPath": "Cite/modules/ve-cite",
|
||||
"scripts": [
|
||||
"ve.dm.MWDocumentReferences.js",
|
||||
"ve.dm.MWReferenceModel.js",
|
||||
"ve.dm.MWReferencesListNode.js",
|
||||
"ve.dm.MWReferenceNode.js",
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
"mw.": "https://doc.wikimedia.org/mediawiki-core/master/js/{type}.html"
|
||||
},
|
||||
"prefixMapIgnore": [
|
||||
"ve.dm.MWDocumentReferences",
|
||||
"ve.dm.MWReference",
|
||||
"ve.ce.MWReference",
|
||||
"ve.ui.MWReference"
|
||||
|
|
|
@ -27,6 +27,7 @@ ve.ce.MWReferencesListNode = function VeCeMWReferencesListNode() {
|
|||
this.internalList = null;
|
||||
this.listNode = null;
|
||||
this.modified = false;
|
||||
this.docRefs = null;
|
||||
|
||||
// DOM changes
|
||||
this.$element.addClass( 've-ce-mwReferencesListNode' );
|
||||
|
@ -174,6 +175,7 @@ ve.ce.MWReferencesListNode.prototype.update = function () {
|
|||
return;
|
||||
}
|
||||
|
||||
this.docRefs = ve.dm.MWDocumentReferences.static.refsForDoc( model.getDocument() );
|
||||
const internalList = model.getDocument().internalList;
|
||||
const refGroup = model.getAttribute( 'refGroup' );
|
||||
const listGroup = model.getAttribute( 'listGroup' );
|
||||
|
@ -238,9 +240,11 @@ ve.ce.MWReferencesListNode.prototype.update = function () {
|
|||
this.$refmsg.text( emptyText );
|
||||
this.$element.append( this.$refmsg );
|
||||
} else {
|
||||
const groupedByParent = this.docRefs.getGroupRefsByParents( listGroup );
|
||||
const topLevelNodes = groupedByParent[ '' ] || [];
|
||||
this.$reflist.append(
|
||||
nodes.indexOrder.map( ( index ) => this.renderListItem(
|
||||
nodes, internalList, refGroup, index
|
||||
topLevelNodes.map( ( node ) => this.renderListItem(
|
||||
nodes, internalList, refGroup, node
|
||||
) )
|
||||
);
|
||||
|
||||
|
@ -256,11 +260,12 @@ ve.ce.MWReferencesListNode.prototype.update = function () {
|
|||
* @param {Object} nodes Node group object, containing nodes and key order array
|
||||
* @param {ve.dm.InternalList} internalList Internal list
|
||||
* @param {string} refGroup Reference group
|
||||
* @param {number} index Item index
|
||||
* @return {jQuery} List item
|
||||
* @param {ve.dm.MWReferenceNode} node Reference node to render as a footnote body
|
||||
* @return {jQuery} Rendered list item
|
||||
*/
|
||||
ve.ce.MWReferencesListNode.prototype.renderListItem = function ( nodes, internalList, refGroup, index ) {
|
||||
const key = internalList.keys[ index ];
|
||||
ve.ce.MWReferencesListNode.prototype.renderListItem = function ( nodes, internalList, refGroup, node ) {
|
||||
const listIndex = node.getAttribute( 'listIndex' );
|
||||
const key = internalList.keys[ listIndex ];
|
||||
const keyedNodes = ( nodes.keyedNodes[ key ] || [] )
|
||||
.filter(
|
||||
// Exclude placeholders and references defined inside the references list node
|
||||
|
@ -271,7 +276,7 @@ ve.ce.MWReferencesListNode.prototype.renderListItem = function ( nodes, internal
|
|||
.append( this.renderBacklinks( keyedNodes, refGroup ), ' ' );
|
||||
|
||||
// Generate reference HTML from first item in key
|
||||
const modelNode = internalList.getItemNode( index );
|
||||
const modelNode = internalList.getItemNode( listIndex );
|
||||
if ( modelNode && modelNode.length ) {
|
||||
const refPreview = new ve.ui.MWPreviewElement( modelNode, { useView: true } );
|
||||
$li.append(
|
||||
|
@ -285,8 +290,7 @@ ve.ce.MWReferencesListNode.prototype.renderListItem = function ( nodes, internal
|
|||
// TODO: attach to the singleton click handler on the surface
|
||||
$li.on( 'mousedown', ( e ) => {
|
||||
if ( ve.isUnmodifiedLeftClick( e ) && modelNode && modelNode.length ) {
|
||||
const firstNode = nodes.firstNodes[ index ];
|
||||
const items = ve.ui.contextItemFactory.getRelatedItems( [ firstNode ] )
|
||||
const items = ve.ui.contextItemFactory.getRelatedItems( [ node ] )
|
||||
.filter( ( item ) => item.name !== 'mobileActions' );
|
||||
if ( items.length ) {
|
||||
const contextItem = ve.ui.contextItemFactory.lookup( items[ 0 ].name );
|
||||
|
@ -296,7 +300,7 @@ ve.ce.MWReferencesListNode.prototype.renderListItem = function ( nodes, internal
|
|||
if ( command ) {
|
||||
const fragmentArgs = {
|
||||
fragment: surface.getModel()
|
||||
.getLinearFragment( firstNode.getOuterRange(), true ),
|
||||
.getLinearFragment( node.getOuterRange(), true ),
|
||||
selectFragmentOnClose: false
|
||||
};
|
||||
const newArgs = ve.copy( command.args );
|
||||
|
|
68
modules/ve-cite/ve.dm.MWDocumentReferences.js
Normal file
68
modules/ve-cite/ve.dm.MWDocumentReferences.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
'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;
|
||||
};
|
||||
|
||||
/* 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
|
||||
* @return {ve.dm.MWDocumentReferences} Singleton docRefs
|
||||
*/
|
||||
ve.dm.MWDocumentReferences.static.refsForDoc = function ( doc ) {
|
||||
let docRefs = doc.getStorage( 'document-references-store' );
|
||||
if ( docRefs === undefined ) {
|
||||
docRefs = new ve.dm.MWDocumentReferences( doc );
|
||||
doc.setStorage( 'document-references-store', docRefs );
|
||||
}
|
||||
return docRefs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all refs for a group, organized by parent ref
|
||||
*
|
||||
* This is appropriate when rendering a reflist organized hierarchically by
|
||||
* subrefs using the `extends` feature.
|
||||
*
|
||||
* @param {string} groupName Filter by this group.
|
||||
* @return {Object.<string, ve.dm.MWReferenceNode[]>} Mapping from parent ref
|
||||
* name to a list of its subrefs. Note that the top-level refs are under the
|
||||
* `null` value.
|
||||
*/
|
||||
ve.dm.MWDocumentReferences.prototype.getGroupRefsByParents = function ( groupName ) {
|
||||
const nodeGroup = this.doc.getInternalList().getNodeGroup( groupName );
|
||||
return ( nodeGroup ? nodeGroup.indexOrder : [] )
|
||||
.reduce( ( acc, index ) => {
|
||||
const node = nodeGroup.firstNodes[ index ];
|
||||
const extendsRef = node.element.attributes.extendsRef || '';
|
||||
if ( acc[ extendsRef ] === undefined ) {
|
||||
acc[ extendsRef ] = [];
|
||||
}
|
||||
acc[ extendsRef ].push( node );
|
||||
return acc;
|
||||
}, {} );
|
||||
};
|
Loading…
Reference in a new issue