113 lines
2.3 KiB
JavaScript
113 lines
2.3 KiB
JavaScript
import {
|
||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Transaction, Item, StructStore // eslint-disable-line
|
||
} from '../internals.js'
|
||
|
||
/**
|
||
* @private
|
||
*/
|
||
export class ContentString {
|
||
/**
|
||
* @param {string} str
|
||
*/
|
||
constructor (str) {
|
||
/**
|
||
* @type {string}
|
||
*/
|
||
this.str = str
|
||
}
|
||
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength () {
|
||
return this.str.length
|
||
}
|
||
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent () {
|
||
return this.str.split('')
|
||
}
|
||
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable () {
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* @return {ContentString}
|
||
*/
|
||
copy () {
|
||
return new ContentString(this.str)
|
||
}
|
||
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentString}
|
||
*/
|
||
splice (offset) {
|
||
const right = new ContentString(this.str.slice(offset))
|
||
this.str = this.str.slice(0, offset)
|
||
|
||
// Prevent encoding invalid documents because of splitting of surrogate pairs: https://github.com/yjs/yjs/issues/248
|
||
const firstCharCode = this.str.charCodeAt(offset - 1)
|
||
if (firstCharCode >= 0xD800 && firstCharCode <= 0xDBFF) {
|
||
// Last character of the left split is the start of a surrogate utf16/ucs2 pair.
|
||
// We don't support splitting of surrogate pairs because this may lead to invalid documents.
|
||
// Replace the invalid character with a unicode replacement character (<28> / U+FFFD)
|
||
this.str = this.str.slice(0, offset - 1) + '<27>'
|
||
// replace right as well
|
||
right.str = '<27>' + right.str.slice(1)
|
||
}
|
||
return right
|
||
}
|
||
|
||
/**
|
||
* @param {ContentString} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith (right) {
|
||
this.str += right.str
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate (transaction, item) {}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete (transaction) {}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc (store) {}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write (encoder, offset) {
|
||
encoder.writeString(offset === 0 ? this.str : this.str.slice(offset))
|
||
}
|
||
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef () {
|
||
return 4
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @private
|
||
*
|
||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder
|
||
* @return {ContentString}
|
||
*/
|
||
export const readContentString = decoder => new ContentString(decoder.readString())
|