mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Cite
synced 2024-11-23 14:36:51 +00:00
Display reference preview with sub reference
Identify both parent and child reference (reference and extended reference) and display them in the reference preview popup. This is a very simple basic implementation so at least avoid that the sub referenc content is shown without context. Bug: T239228 Change-Id: I857e1be32db9fd72073015cbba1b1bd37e32085f
This commit is contained in:
parent
eeb4852be3
commit
7380a861f0
|
@ -11,9 +11,9 @@ module.exports = function createReferenceGateway() {
|
|||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @return {HTMLElement}
|
||||
* @return {HTMLElement|null}
|
||||
*/
|
||||
function scrapeReferenceText( id ) {
|
||||
function findReferenceTextElement( id ) {
|
||||
const idSelector = `#${ CSS.escape( id ) }`;
|
||||
|
||||
/**
|
||||
|
@ -24,19 +24,49 @@ module.exports = function createReferenceGateway() {
|
|||
return document.querySelector( `${ idSelector } .mw-reference-text, ${ idSelector } .reference-text` );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} el
|
||||
* @return {HTMLElement|null}
|
||||
*/
|
||||
function findParentReferenceTextElement( el ) {
|
||||
// This finds either the inner <ol class="mw-extended-references">, or the outer
|
||||
// <ol class="references">
|
||||
const ol = el.closest( 'ol' );
|
||||
|
||||
return ol && ol.classList.contains( 'mw-extended-references' ) ?
|
||||
ol.parentElement.querySelector( '.mw-reference-text, .reference-text' ) :
|
||||
null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} referenceElement
|
||||
* @param {(HTMLElement|null)} parentElement
|
||||
* @return {string}
|
||||
*/
|
||||
function scrapeReferenceText( referenceElement, parentElement ) {
|
||||
if ( !parentElement ) {
|
||||
return referenceElement.innerHTML;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="mw-reference-previews-parent">${ parentElement.innerHTML }</div>
|
||||
<div>${ referenceElement.innerHTML }</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find a single reference type identifier, limited to a list of known types.
|
||||
* - When a `class="…"` attribute mentions multiple known types, the last one is used, following
|
||||
* CSS semantics.
|
||||
* - When there are multiple <cite> tags, the first with a known type is used.
|
||||
*
|
||||
* @param {HTMLElement} referenceText
|
||||
* @param {HTMLElement} referenceElement
|
||||
* @return {string|null}
|
||||
*/
|
||||
function scrapeReferenceType( referenceText ) {
|
||||
function scrapeReferenceType( referenceElement ) {
|
||||
const KNOWN_TYPES = [ 'book', 'journal', 'news', 'note', 'web' ];
|
||||
let type = null;
|
||||
const citeTags = referenceText.querySelectorAll( 'cite[class]' );
|
||||
const citeTags = referenceElement.querySelectorAll( 'cite[class]' );
|
||||
Array.prototype.forEach.call( citeTags, ( element ) => {
|
||||
// don't need to keep scanning if one is found.
|
||||
if ( type ) {
|
||||
|
@ -60,24 +90,26 @@ module.exports = function createReferenceGateway() {
|
|||
*/
|
||||
function fetchPreviewForTitle( title, el ) {
|
||||
// Need to encode the fragment again as mw.Title returns it as decoded text
|
||||
const id = title.getFragment().replace( / /g, '_' ),
|
||||
referenceNode = scrapeReferenceText( id );
|
||||
const id = title.getFragment().replace( / /g, '_' );
|
||||
const referenceTextElement = findReferenceTextElement( id );
|
||||
|
||||
if ( !referenceNode ||
|
||||
if ( !referenceTextElement ||
|
||||
// Skip references that don't contain anything but whitespace, e.g. a single
|
||||
( !referenceNode.textContent.trim() && !referenceNode.children.length )
|
||||
( !referenceTextElement.textContent.trim() && !referenceTextElement.children.length )
|
||||
) {
|
||||
return Promise.reject(
|
||||
// Required to set `showNullPreview` to false and not open an error popup
|
||||
// Required to set showNullPreview to false and not open an error popup
|
||||
{ textStatus: 'abort', textContext: 'Footnote not found or empty', xhr: { readyState: 0 } }
|
||||
);
|
||||
}
|
||||
|
||||
const referenceParentTextElement = findParentReferenceTextElement( referenceTextElement );
|
||||
|
||||
const model = {
|
||||
url: `#${ id }`,
|
||||
extract: referenceNode.innerHTML,
|
||||
extract: scrapeReferenceText( referenceTextElement, referenceParentTextElement ),
|
||||
type: TYPE_REFERENCE,
|
||||
referenceType: scrapeReferenceType( referenceNode ),
|
||||
referenceType: scrapeReferenceType( referenceParentTextElement || referenceTextElement ),
|
||||
// Note: Even the top-most HTMLHtmlElement is guaranteed to have a parent.
|
||||
sourceElementId: el.parentNode.id
|
||||
};
|
||||
|
|
|
@ -86,4 +86,8 @@
|
|||
margin: 1em 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mw-reference-previews-parent {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue