Catrope has uploaded a new change for review.
https://gerrit.wikimedia.org/r/82784
Change subject: Allow replace operations to replace metadata as well
......................................................................
Allow replace operations to replace metadata as well
This was already possible in the operation structure by using
removeMetadata and insertMetadata, but no transaction builders
generated transactions like that.
With this change, pushReplace() can be instructed to overwrite the
metadata with arbitrary data rather than collapsing it by passing the
optional insertMeta parameter.
The actual logic for this is in getMetadataReplace(), which now returns
null rather than {} if no metadata needs to be replaced (allegedly
Ed made me do this in a code review from months ago that I can't find
now).
Change-Id: I0272fe38e053161c738591cf0a7b447a0827d4dc
---
M modules/ve/dm/ve.dm.Document.js
M modules/ve/dm/ve.dm.Transaction.js
2 files changed, 51 insertions(+), 23 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/84/82784/1
diff --git a/modules/ve/dm/ve.dm.Document.js b/modules/ve/dm/ve.dm.Document.js
index e85b372..216b30f 100644
--- a/modules/ve/dm/ve.dm.Document.js
+++ b/modules/ve/dm/ve.dm.Document.js
@@ -336,32 +336,62 @@
/**
* Get the metadata replace operation required to keep data & metadata in sync
after a splice
*
+ * If no metadata replacement is required, this function returns null.
+ *
* @method
* @param {number} offset Data offset to start at
* @param {number} remove Number of elements being removed
* @param {Array} insert Element data being inserted
- * @returns {Object} Metadata replace operation to keep data & metadata in sync
+ * @param {Array} [insertMeta] Metadata being inserted
+ * @returns {Object|null} Metadata replace operation to keep data & metadata
in sync
*/
-ve.dm.Document.prototype.getMetadataReplace = function ( offset, remove,
insert ) {
- var removeMetadata, insertMetadata, replace = {};
- if ( remove > insert.length ) {
+ve.dm.Document.prototype.getMetadataReplace = function ( offset, remove,
insert, insertMeta ) {
+ var i, len, retainMetadata, removeMetadata, insertMetadata;
+ if ( insertMeta ) {
+ // Find the first non-empty metadata insertion
+ len = insertMeta.length;
+ retainMetadata = len;
+ for ( i = 0; i < len; i++ ) {
+ if ( insertMeta[i] && insertMeta[i].length > 0 ) {
+ retainMetadata = i;
+ }
+ }
+
+ // See if there's a metadata removal before the first non-empty
metadata insertion
+ for ( i = 0; i < remove && i < retainMetadata; i++ ) {
+ if ( this.metadata.data[offset + i] &&
this.metadata.data[offset + i].length ) {
+ retainMetadata = i;
+ }
+ }
+
+ if ( retainMetadata === len ) {
+ // No metadata being inserted or removed
+ return null;
+ } else {
+ return {
+ 'retain': retainMetadata,
+ 'remove': retainMetadata < remove ?
+ this.getMetadata( new ve.Range( offset
+ retainMetadata, offset + remove + 1 ) ) :
+ [],
+ 'insert': insertMeta.slice( retainMetadata )
+ };
+ }
+ } else if ( remove > insert.length ) {
// if we are removing more than we are inserting we need to
collapse the excess metadata
removeMetadata = this.getMetadata( new ve.Range( offset +
insert.length, offset + remove + 1 ) );
// check removeMetadata is non-empty
if ( !ve.compare( removeMetadata, new Array(
removeMetadata.length ) ) ) {
insertMetadata = ve.dm.MetaLinearData.static.merge(
removeMetadata );
- replace.retain = insert.length;
- replace.remove = removeMetadata;
- replace.insert = insertMetadata;
+ return {
+ 'retain': insert.length,
+ 'remove': removeMetadata,
+ 'insert': insertMetadata
+ };
}
}
// if insert.length === remove metadata can just stay where it is
- if ( insert.length > remove ) {
- // if we are inserting more than we are removing then we need
to pad out with undefineds
- replace.retain = remove;
- replace.insert = new Array( insert.length - remove );
- }
- return replace;
+ // if insert.length > remove, then we need to pad out with undefineds,
but that's the default
+ return null;
};
/**
diff --git a/modules/ve/dm/ve.dm.Transaction.js
b/modules/ve/dm/ve.dm.Transaction.js
index 3f64305..b4fe275 100644
--- a/modules/ve/dm/ve.dm.Transaction.js
+++ b/modules/ve/dm/ve.dm.Transaction.js
@@ -877,8 +877,9 @@
* @param {number} offset Offset to start at
* @param {number} removeLength Number of data items to remove
* @param {Array} insert Data to insert
+ * @param {Array} [insertMeta] Metadata to insert
*/
-ve.dm.Transaction.prototype.pushReplace = function ( doc, offset,
removeLength, insert ) {
+ve.dm.Transaction.prototype.pushReplace = function ( doc, offset,
removeLength, insert, insertMeta ) {
if ( removeLength === 0 && insert.length === 0 ) {
// Don't push no-ops
return;
@@ -887,12 +888,9 @@
var op, end = this.operations.length - 1,
lastOp = end >= 0 ? this.operations[end] : null,
remove = doc.getData( new ve.Range( offset, offset +
removeLength ) ),
- metadataReplace = doc.getMetadataReplace( offset, removeLength,
insert ),
- retainMetadata = metadataReplace.retain,
- removeMetadata = metadataReplace.remove,
- insertMetadata = metadataReplace.insert;
+ metadataReplace = doc.getMetadataReplace( offset, removeLength,
insert, insertMeta );
- if ( lastOp && lastOp.type === 'replace' && !lastOp.removeMetadata &&
!removeMetadata ) {
+ if ( lastOp && lastOp.type === 'replace' && !lastOp.removeMetadata &&
!metadataReplace ) {
// simple replaces can just be concatenated
// TODO: allow replaces with meta to be merged?
lastOp.insert = lastOp.insert.concat( insert );
@@ -903,10 +901,10 @@
'remove': remove,
'insert': insert
};
- if ( removeMetadata !== undefined ) {
- op.retainMetadata = retainMetadata;
- op.removeMetadata = removeMetadata;
- op.insertMetadata = insertMetadata;
+ if ( metadataReplace ) {
+ op.retainMetadata = metadataReplace.retain;
+ op.removeMetadata = metadataReplace.remove;
+ op.insertMetadata = metadataReplace.insert;
}
this.operations.push( op );
}
--
To view, visit https://gerrit.wikimedia.org/r/82784
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0272fe38e053161c738591cf0a7b447a0827d4dc
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Catrope <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits