mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Cite
synced 2024-11-28 00:40:12 +00:00
Merge "Don't compute ref contents in converter preview mode"
This commit is contained in:
commit
2e13427f3d
|
@ -9,14 +9,13 @@ QUnit.module( 've.ui.DiffElement (Cite)' );
|
|||
QUnit.test( 'Diffing', function ( assert ) {
|
||||
var i, len,
|
||||
// spacer = '<div class="ve-ui-diffElement-spacer">⋮</div>',
|
||||
ref = function ( text, num, name ) {
|
||||
ref = function ( text, num ) {
|
||||
var dataMw = {
|
||||
name: 'ref',
|
||||
body: { html: text }
|
||||
// attrs doesn't get set in preview mode
|
||||
};
|
||||
if ( name ) {
|
||||
dataMw.attrs = { name: name };
|
||||
}
|
||||
|
||||
return '<sup typeof="mw:Extension/ref" data-mw="' + JSON.stringify( dataMw ).replace( /"/g, '"' ) + '" class="mw-ref">' +
|
||||
'<a style="counter-reset: mw-Ref ' + num + ';"><span class="mw-reflink-text">[' + num + ']</span></a>' +
|
||||
'</sup>';
|
||||
|
@ -37,10 +36,10 @@ QUnit.test( 'Diffing', function ( assert ) {
|
|||
'<p>' +
|
||||
ref( 'Foo', '1' ) +
|
||||
'<span data-diff-action="change-remove">' +
|
||||
ref( 'Bar', '2', ':0' ) +
|
||||
ref( 'Bar', '2' ) +
|
||||
'</span>' +
|
||||
'<span data-diff-action="change-insert">' +
|
||||
ref( 'Bar ish', '2', ':0' ) +
|
||||
ref( 'Bar ish', '2' ) +
|
||||
'</span>' +
|
||||
ref( 'Baz', '3' ) +
|
||||
'</p>' +
|
||||
|
|
|
@ -101,118 +101,124 @@ ve.dm.MWReferenceNode.static.toDataElement = function ( domElements, converter )
|
|||
};
|
||||
|
||||
ve.dm.MWReferenceNode.static.toDomElements = function ( dataElement, doc, converter ) {
|
||||
var itemNodeHtml, originalHtml, mwData, i, iLen, keyedNodes, setContents, contentsAlreadySet,
|
||||
var itemNode, itemNodeRange, itemNodeHtml, originalHtml, mwData, i, iLen, keyedNodes, setContents, contentsAlreadySet,
|
||||
originalMw, listKeyParts, name, group, $link,
|
||||
isForClipboard = converter.isForClipboard(),
|
||||
el = doc.createElement( 'sup' ),
|
||||
itemNodeWrapper = doc.createElement( 'div' ),
|
||||
originalHtmlWrapper = doc.createElement( 'div' ),
|
||||
itemNode = converter.internalList.getItemNode( dataElement.attributes.listIndex ),
|
||||
itemNodeRange = itemNode.getRange();
|
||||
originalHtmlWrapper = doc.createElement( 'div' );
|
||||
|
||||
el.setAttribute( 'typeof', 'mw:Extension/ref' );
|
||||
|
||||
mwData = dataElement.attributes.mw ? ve.copy( dataElement.attributes.mw ) : {};
|
||||
mwData.name = 'ref';
|
||||
|
||||
setContents = dataElement.attributes.contentsUsed;
|
||||
if ( isForClipboard || converter.isForParser() ) {
|
||||
setContents = dataElement.attributes.contentsUsed;
|
||||
|
||||
keyedNodes = converter.internalList
|
||||
.getNodeGroup( dataElement.attributes.listGroup )
|
||||
.keyedNodes[ dataElement.attributes.listKey ];
|
||||
// This call rebuilds the document tree if it isn't built already (e.g. on a
|
||||
// document slice), so only use when necessary (i.e. not in preview mode)
|
||||
itemNode = converter.internalList.getItemNode( dataElement.attributes.listIndex );
|
||||
itemNodeRange = itemNode.getRange();
|
||||
|
||||
if ( setContents ) {
|
||||
// Check if a previous node has already set the content. If so, we don't overwrite this
|
||||
// node's contents.
|
||||
contentsAlreadySet = false;
|
||||
if ( keyedNodes ) {
|
||||
for ( i = 0, iLen = keyedNodes.length; i < iLen; i++ ) {
|
||||
if ( keyedNodes[ i ].element === dataElement ) {
|
||||
break;
|
||||
}
|
||||
if ( keyedNodes[ i ].element.attributes.contentsUsed ) {
|
||||
contentsAlreadySet = true;
|
||||
break;
|
||||
keyedNodes = converter.internalList
|
||||
.getNodeGroup( dataElement.attributes.listGroup )
|
||||
.keyedNodes[ dataElement.attributes.listKey ];
|
||||
|
||||
if ( setContents ) {
|
||||
// Check if a previous node has already set the content. If so, we don't overwrite this
|
||||
// node's contents.
|
||||
contentsAlreadySet = false;
|
||||
if ( keyedNodes ) {
|
||||
for ( i = 0, iLen = keyedNodes.length; i < iLen; i++ ) {
|
||||
if ( keyedNodes[ i ].element === dataElement ) {
|
||||
break;
|
||||
}
|
||||
if ( keyedNodes[ i ].element.attributes.contentsUsed ) {
|
||||
contentsAlreadySet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if any other nodes with this key provided content. If not
|
||||
// then we attach the contents to the first reference with this key
|
||||
|
||||
// Check that this is the first reference with its key
|
||||
if ( keyedNodes && dataElement === keyedNodes[ 0 ].element ) {
|
||||
setContents = true;
|
||||
// Check no other reference originally defined the contents
|
||||
// As this is keyedNodes[0] we can start at 1
|
||||
for ( i = 1, iLen = keyedNodes.length; i < iLen; i++ ) {
|
||||
if ( keyedNodes[ i ].element.attributes.contentsUsed ) {
|
||||
setContents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( setContents && !contentsAlreadySet ) {
|
||||
converter.getDomSubtreeFromData(
|
||||
itemNode.getDocument().getFullData( itemNodeRange, true ),
|
||||
itemNodeWrapper
|
||||
);
|
||||
itemNodeHtml = itemNodeWrapper.innerHTML; // Returns '' if itemNodeWrapper is empty
|
||||
originalHtml = ve.getProp( mwData, 'body', 'html' ) ||
|
||||
( ve.getProp( mwData, 'body', 'id' ) !== undefined && itemNode.getAttribute( 'originalHtml' ) ) ||
|
||||
'';
|
||||
originalHtmlWrapper.innerHTML = originalHtml;
|
||||
// Only set body.html if itemNodeHtml and originalHtml are actually different,
|
||||
// or we are writing the clipboard for use in another VE instance
|
||||
if ( isForClipboard || !originalHtmlWrapper.isEqualNode( itemNodeWrapper ) ) {
|
||||
ve.setProp( mwData, 'body', 'html', itemNodeHtml );
|
||||
}
|
||||
}
|
||||
|
||||
// If we have no internal item data for this reference, don't let it get pasted into
|
||||
// another VE document. T110479
|
||||
if ( isForClipboard && itemNodeRange.isCollapsed() ) {
|
||||
el.setAttribute( 'data-ve-ignore', 'true' );
|
||||
}
|
||||
|
||||
// Generate name
|
||||
listKeyParts = dataElement.attributes.listKey.match( this.listKeyRegex );
|
||||
if ( listKeyParts[ 1 ] === 'auto' ) {
|
||||
// Only render a name if this key was reused
|
||||
if ( keyedNodes.length > 1 ) {
|
||||
// Allocate a unique list key, then strip the 'literal/'' prefix
|
||||
name = converter.internalList.getUniqueListKey(
|
||||
dataElement.attributes.listGroup,
|
||||
dataElement.attributes.listKey,
|
||||
// Generate a name starting with ':' to distinguish it from normal names
|
||||
'literal/:'
|
||||
).slice( 'literal/'.length );
|
||||
} else {
|
||||
name = undefined;
|
||||
}
|
||||
} else {
|
||||
// Use literal name
|
||||
name = listKeyParts[ 2 ];
|
||||
}
|
||||
// Set name
|
||||
if ( name !== undefined ) {
|
||||
ve.setProp( mwData, 'attrs', 'name', name );
|
||||
}
|
||||
// Check if any other nodes with this key provided content. If not
|
||||
// then we attach the contents to the first reference with this key
|
||||
|
||||
// Set or clear group
|
||||
if ( dataElement.attributes.refGroup !== '' ) {
|
||||
ve.setProp( mwData, 'attrs', 'group', dataElement.attributes.refGroup );
|
||||
} else if ( mwData.attrs ) {
|
||||
delete mwData.attrs.refGroup;
|
||||
// Check that this is the first reference with its key
|
||||
if ( keyedNodes && dataElement === keyedNodes[ 0 ].element ) {
|
||||
setContents = true;
|
||||
// Check no other reference originally defined the contents
|
||||
// As this is keyedNodes[0] we can start at 1
|
||||
for ( i = 1, iLen = keyedNodes.length; i < iLen; i++ ) {
|
||||
if ( keyedNodes[ i ].element.attributes.contentsUsed ) {
|
||||
setContents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add reference contents to data-mw.
|
||||
if ( setContents && !contentsAlreadySet ) {
|
||||
converter.getDomSubtreeFromData(
|
||||
itemNode.getDocument().getFullData( itemNodeRange, true ),
|
||||
itemNodeWrapper
|
||||
);
|
||||
itemNodeHtml = itemNodeWrapper.innerHTML; // Returns '' if itemNodeWrapper is empty
|
||||
originalHtml = ve.getProp( mwData, 'body', 'html' ) ||
|
||||
( ve.getProp( mwData, 'body', 'id' ) !== undefined && itemNode.getAttribute( 'originalHtml' ) ) ||
|
||||
'';
|
||||
originalHtmlWrapper.innerHTML = originalHtml;
|
||||
// Only set body.html if itemNodeHtml and originalHtml are actually different,
|
||||
// or we are writing the clipboard for use in another VE instance
|
||||
if ( isForClipboard || !originalHtmlWrapper.isEqualNode( itemNodeWrapper ) ) {
|
||||
ve.setProp( mwData, 'body', 'html', itemNodeHtml );
|
||||
}
|
||||
}
|
||||
|
||||
// If we have no internal item data for this reference, don't let it get pasted into
|
||||
// another VE document. T110479
|
||||
if ( isForClipboard && itemNodeRange.isCollapsed() ) {
|
||||
el.setAttribute( 'data-ve-ignore', 'true' );
|
||||
}
|
||||
|
||||
// Generate name
|
||||
listKeyParts = dataElement.attributes.listKey.match( this.listKeyRegex );
|
||||
if ( listKeyParts[ 1 ] === 'auto' ) {
|
||||
// Only render a name if this key was reused
|
||||
if ( keyedNodes.length > 1 ) {
|
||||
// Allocate a unique list key, then strip the 'literal/'' prefix
|
||||
name = converter.internalList.getUniqueListKey(
|
||||
dataElement.attributes.listGroup,
|
||||
dataElement.attributes.listKey,
|
||||
// Generate a name starting with ':' to distinguish it from normal names
|
||||
'literal/:'
|
||||
).slice( 'literal/'.length );
|
||||
} else {
|
||||
name = undefined;
|
||||
}
|
||||
} else {
|
||||
// Use literal name
|
||||
name = listKeyParts[ 2 ];
|
||||
}
|
||||
// Set name
|
||||
if ( name !== undefined ) {
|
||||
ve.setProp( mwData, 'attrs', 'name', name );
|
||||
}
|
||||
|
||||
// Set or clear group
|
||||
if ( dataElement.attributes.refGroup !== '' ) {
|
||||
ve.setProp( mwData, 'attrs', 'group', dataElement.attributes.refGroup );
|
||||
} else if ( mwData.attrs ) {
|
||||
delete mwData.attrs.refGroup;
|
||||
}
|
||||
}
|
||||
|
||||
// If mwAttr and originalMw are the same, use originalMw to prevent reserialization,
|
||||
// unless we are writing the clipboard for use in another VE instance
|
||||
// Reserialization has the potential to reorder keys and so change the DOM unnecessarily
|
||||
originalMw = dataElement.attributes.originalMw;
|
||||
if ( !isForClipboard && originalMw && ve.compare( mwData, JSON.parse( originalMw ) ) ) {
|
||||
if ( converter.isForParser() && originalMw && ve.compare( mwData, JSON.parse( originalMw ) ) ) {
|
||||
el.setAttribute( 'data-mw', originalMw );
|
||||
|
||||
// Return the original DOM elements if possible
|
||||
|
|
Loading…
Reference in a new issue