[MediaWiki-commits] [Gerrit] Add getDocumentSlice - change (mediawiki...VisualEditor)
jenkins-bot has submitted this change and it was merged. Change subject: Add getDocumentSlice .. Add getDocumentSlice A document slice is a document built from a data slice of an existing document. It's completely separate from the original document and has its own store and internalList. The new document's data also contains the entirety of the original document's internal list. It's possible to create a document slice of data located inside the internal list, in which case the resulting document will contain that data twice (one mutable copy at the top level, and one immutable copy in the internal list). ve.dm.Document.js: * Optionally take an internalList in the constructor. This allows us to create a document with a clone of an existing internalList rather than an empty one. * Add edgeMetadata flag to getFullData() ve.dm.IndexValueStore.js, ve.dm.InternalList.js: * Make these classes cloneable Change-Id: I93e06f764ace16aee9df941b07f8c2bff1a28e2b --- M modules/ve/dm/ve.dm.Document.js M modules/ve/dm/ve.dm.IndexValueStore.js M modules/ve/dm/ve.dm.InternalList.js M modules/ve/test/dm/ve.dm.Document.test.js 4 files changed, 134 insertions(+), 8 deletions(-) Approvals: Catrope: Looks good to me, approved jenkins-bot: Verified diff --git a/modules/ve/dm/ve.dm.Document.js b/modules/ve/dm/ve.dm.Document.js index 859e9f3..a30e486 100644 --- a/modules/ve/dm/ve.dm.Document.js +++ b/modules/ve/dm/ve.dm.Document.js @@ -18,8 +18,9 @@ * @constructor * @param {HTMLDocument|Array|ve.dm.LinearData} documentOrData HTML document, raw linear model data or LinearData to start with * @param {ve.dm.Document} [parentDocument] Document to use as root for created nodes + * @param {ve.dm.InternalList} [internalList] Internal list to clone; passed when creating a document slice */ -ve.dm.Document = function VeDmDocument( documentOrData, parentDocument ) { +ve.dm.Document = function VeDmDocument( documentOrData, parentDocument, internalList ) { // Parent constructor ve.Document.call( this, new ve.dm.DocumentNode() ); @@ -41,7 +42,7 @@ currentNode = this.documentNode; this.documentNode.setDocument( doc ); this.documentNode.setRoot( root ); - this.internalList = new ve.dm.InternalList( this ); + this.internalList = internalList ? internalList.clone( this ) : new ve.dm.InternalList( this ); // Properties this.parentDocument = parentDocument; @@ -293,6 +294,36 @@ }; /** + * Get a document from a slice of this document. The new document's store and internal list will be + * clones of the ones in this document. + * + * @param {ve.Range|ve.dm.Node} rangeOrNode Range of data to clone, or node whose contents should be cloned + * @returns {ve.dm.Document} New document + * @throws {Error} rangeOrNode must be a ve.Range or a ve.dm.Node + */ +ve.dm.Document.prototype.getDocumentSlice = function ( rangeOrNode ) { + var data, range, + store = this.store.clone(), + listRange = this.internalList.getListNode().getOuterRange(); + if ( rangeOrNode instanceof ve.dm.Node ) { + range = rangeOrNode.getRange(); + } else if ( rangeOrNode instanceof ve.Range ) { + range = rangeOrNode; + } else { + throw new Error( 'rangeOrNode must be a ve.Range or a ve.dm.Node' ); + } + data = ve.copyArray( this.getFullData( range, true ) ); + if ( range.start > listRange.start || range.end < listRange.end ) { + // The range does not include the entire internal list, so add it + data = data.concat( this.getFullData( listRange ) ); + } + return new this.constructor( + new ve.dm.ElementLinearData( store, data ), + undefined, this.internalList + ); +}; + +/** * Get the metadata replace operation required to keep data & metadata in sync after a splice * * @method @@ -349,14 +380,25 @@ /** * Get the full document data including metadata. * - * Metadata will be into the document data to produce the "full data" result. + * Metadata will be into the document data to produce the "full data" result. If a range is passed, + * metadata at the edges of the range won't be included unless edgeMetadata is set to true. If + * no range is passed, the entire document's data is returned and metadata at the edges is + * included. * + * @param {ve.Range} [range] Range to get full data for. If omitted, all data will be returned + * @param {boolean} [edgeMetadata=false] Include metadata at the edges of the range * @returns {Array} Data with metadata interleaved */ -ve.dm.Document.prototype.getFullData = function () { - var result = [], i, j, jLen, iLen = this.data.getLength(); - for ( i = 0; i <= iLen; i++ ) { - if ( this.metadata.getData( i ) ) { +ve.dm.Document.prototype.getFullDa
[MediaWiki-commits] [Gerrit] Add getDocumentSlice() - change (mediawiki...VisualEditor)
Catrope has uploaded a new change for review. https://gerrit.wikimedia.org/r/64958 Change subject: Add getDocumentSlice() .. Add getDocumentSlice() A document slice is a document built from a data slice of an existing document. It's completely separate from the original document and has its own store and internalList. The new document's data also contains the entirety of the original document's internal list. It's possible to create a document slice of data located inside the internal list, in which case the resulting document will contain that data twice (one mutable copy at the top level, and one immutable copy in the internal list). ve.dm.Document.js: * Optionally take an internalList in the constructor. This allows us to create a document with a clone of an existing internalList rather than an empty one. * Add edgeMetadata flag to getFullData() ve.dm.IndexValueStore.js, ve.dm.InternalList.js: * Make these classes cloneable Change-Id: I93e06f764ace16aee9df941b07f8c2bff1a28e2b --- M modules/ve/dm/ve.dm.Document.js M modules/ve/dm/ve.dm.IndexValueStore.js M modules/ve/dm/ve.dm.InternalList.js M modules/ve/test/dm/ve.dm.Document.test.js 4 files changed, 132 insertions(+), 8 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/58/64958/1 diff --git a/modules/ve/dm/ve.dm.Document.js b/modules/ve/dm/ve.dm.Document.js index 859e9f3..ab7bfe2 100644 --- a/modules/ve/dm/ve.dm.Document.js +++ b/modules/ve/dm/ve.dm.Document.js @@ -18,8 +18,9 @@ * @constructor * @param {HTMLDocument|Array|ve.dm.LinearData} documentOrData HTML document, raw linear model data or LinearData to start with * @param {ve.dm.Document} [parentDocument] Document to use as root for created nodes + * @param {ve.dm.InternalList} [internalList] Internal list to clone; passed when creating a document slice */ -ve.dm.Document = function VeDmDocument( documentOrData, parentDocument ) { +ve.dm.Document = function VeDmDocument( documentOrData, parentDocument, internalList ) { // Parent constructor ve.Document.call( this, new ve.dm.DocumentNode() ); @@ -41,7 +42,7 @@ currentNode = this.documentNode; this.documentNode.setDocument( doc ); this.documentNode.setRoot( root ); - this.internalList = new ve.dm.InternalList( this ); + this.internalList = internalList ? internalList.clone( this ) : new ve.dm.InternalList( this ); // Properties this.parentDocument = parentDocument; @@ -293,6 +294,35 @@ }; /** + * Get a document from a slice of this document. The new document's store and internal list will be + * clones of the ones in this document. + * + * @param {ve.Range|ve.dm.Node} rangeOrNode Range of data to clone, or node whose contents should be cloned + * @returns {ve.dm.Document} New document + */ +ve.dm.Document.prototype.getDocumentSlice = function ( rangeOrNode ) { + var data, range, + store = this.store.clone(), + listRange = this.internalList.getListNode().getOuterRange(); + if ( rangeOrNode instanceof ve.dm.Node ) { + range = rangeOrNode.getRange(); + } else if ( rangeOrNode instanceof ve.Range ) { + range = rangeOrNode; + } else { + throw new Error( 'rangeOrNode must be a ve.Range or a ve.dm.Node' ); + } + data = ve.copyArray( this.getFullData( range, true ) ); + if ( range.start > listRange.start || range.end < listRange.end ) { + // The range does not include the entire internal list, so add it + data = data.concat( this.getFullData( listRange ) ); + } + return new this.constructor( + new ve.dm.ElementLinearData( store, data ), + undefined, this.internalList + ); +}; + +/** * Get the metadata replace operation required to keep data & metadata in sync after a splice * * @method @@ -349,14 +379,25 @@ /** * Get the full document data including metadata. * - * Metadata will be into the document data to produce the "full data" result. + * Metadata will be into the document data to produce the "full data" result. If a range is passed, + * metadata at the edges of the range won't be included unless edgeMetadata is set to true. If + * no range is passed, the entire document's data is returned and metadata at the edges is + * included. * + * @param {ve.Range} [range] Range to get full data for. If omitted, all data will be returned + * @param {boolean} [edgeMetadata=fales] Include metadata at the edges of the range * @returns {Array} Data with metadata interleaved */ -ve.dm.Document.prototype.getFullData = function () { - var result = [], i, j, jLen, iLen = this.data.getLength(); - for ( i = 0; i <= iLen; i++ ) { - if ( this.metadata.getData( i ) ) { +ve.dm.Document.prototype.getFullData =