fix Y.Text formatting issue - closes #606
This commit is contained in:
parent
7a8ca6eaa5
commit
1cb52dc863
13
README.md
13
README.md
@ -34,8 +34,17 @@ on Yjs. [ - By contributing financially to the open-source Yjs project, you can receive professional support directly from the author. This includes the opportunity for weekly video calls to discuss your specific challenges.
|
||||
* [Synergy Codes](https://synergycodes.com/yjs-services/) - Specializing in consulting and developing real-time collaborative editing solutions for visual apps, Synergy Codes focuses on interactive diagrams, complex graphs, charts, and various data visualization types. Their expertise empowers developers to build engaging and interactive visual experiences leveraging the power of Yjs. See their work in action at [Visual Collaboration Showcase](https://yjs-diagram.synergy.codes/).
|
||||
* [Support Contract with the Maintainer](https://github.com/sponsors/dmonad) -
|
||||
By contributing financially to the open-source Yjs project, you can receive
|
||||
professional support directly from the author. This includes the opportunity for
|
||||
weekly video calls to discuss your specific challenges.
|
||||
* [Synergy Codes](https://synergycodes.com/yjs-services/) - Specializing in
|
||||
consulting and developing real-time collaborative editing solutions for visual
|
||||
apps, Synergy Codes focuses on interactive diagrams, complex graphs, charts, and
|
||||
various data visualization types. Their expertise empowers developers to build
|
||||
engaging and interactive visual experiences leveraging the power of Yjs. See
|
||||
their work in action at [Visual Collaboration
|
||||
Showcase](https://yjs-diagram.synergy.codes/).
|
||||
|
||||
## Who is using Yjs
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
export * from './utils/AbstractConnector.js'
|
||||
export * from './utils/DeleteSet.js'
|
||||
export * from './utils/Doc.js'
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
UpdateEncoderV1, UpdateEncoderV2, ID, Transaction // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
addToDeleteSet,
|
||||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
Doc, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, Item // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
YText, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Item, StructStore, Transaction // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
readYArray,
|
||||
readYMap,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
AbstractStruct,
|
||||
addStruct,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
GC,
|
||||
getState,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
AbstractStruct,
|
||||
UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, ID // eslint-disable-line
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
removeEventHandlerListener,
|
||||
callEventHandlerListeners,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* @module YMap
|
||||
*/
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* @module YText
|
||||
*/
|
||||
@ -118,14 +117,15 @@ const findNextPosition = (transaction, pos, count) => {
|
||||
* @param {Transaction} transaction
|
||||
* @param {AbstractType<any>} parent
|
||||
* @param {number} index
|
||||
* @param {boolean} useSearchMarker
|
||||
* @return {ItemTextListPosition}
|
||||
*
|
||||
* @private
|
||||
* @function
|
||||
*/
|
||||
const findPosition = (transaction, parent, index) => {
|
||||
const findPosition = (transaction, parent, index, useSearchMarker) => {
|
||||
const currentAttributes = new Map()
|
||||
const marker = findMarker(parent, index)
|
||||
const marker = useSearchMarker ? findMarker(parent, index) : null
|
||||
if (marker) {
|
||||
const pos = new ItemTextListPosition(marker.p.left, marker.p, marker.index, currentAttributes)
|
||||
return findNextPosition(transaction, pos, index - marker.index)
|
||||
@ -1120,7 +1120,7 @@ export class YText extends AbstractType {
|
||||
const y = this.doc
|
||||
if (y !== null) {
|
||||
transact(y, transaction => {
|
||||
const pos = findPosition(transaction, this, index)
|
||||
const pos = findPosition(transaction, this, index, !attributes)
|
||||
if (!attributes) {
|
||||
attributes = {}
|
||||
// @ts-ignore
|
||||
@ -1138,20 +1138,20 @@ export class YText extends AbstractType {
|
||||
*
|
||||
* @param {number} index The index to insert the embed at.
|
||||
* @param {Object | AbstractType<any>} embed The Object that represents the embed.
|
||||
* @param {TextAttributes} attributes Attribute information to apply on the
|
||||
* @param {TextAttributes} [attributes] Attribute information to apply on the
|
||||
* embed
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
insertEmbed (index, embed, attributes = {}) {
|
||||
insertEmbed (index, embed, attributes) {
|
||||
const y = this.doc
|
||||
if (y !== null) {
|
||||
transact(y, transaction => {
|
||||
const pos = findPosition(transaction, this, index)
|
||||
insertText(transaction, this, pos, embed, attributes)
|
||||
const pos = findPosition(transaction, this, index, !attributes)
|
||||
insertText(transaction, this, pos, embed, attributes || {})
|
||||
})
|
||||
} else {
|
||||
/** @type {Array<function>} */ (this._pending).push(() => this.insertEmbed(index, embed, attributes))
|
||||
/** @type {Array<function>} */ (this._pending).push(() => this.insertEmbed(index, embed, attributes || {}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1170,7 +1170,7 @@ export class YText extends AbstractType {
|
||||
const y = this.doc
|
||||
if (y !== null) {
|
||||
transact(y, transaction => {
|
||||
deleteText(transaction, findPosition(transaction, this, index), length)
|
||||
deleteText(transaction, findPosition(transaction, this, index, true), length)
|
||||
})
|
||||
} else {
|
||||
/** @type {Array<function>} */ (this._pending).push(() => this.delete(index, length))
|
||||
@ -1194,7 +1194,7 @@ export class YText extends AbstractType {
|
||||
const y = this.doc
|
||||
if (y !== null) {
|
||||
transact(y, transaction => {
|
||||
const pos = findPosition(transaction, this, index)
|
||||
const pos = findPosition(transaction, this, index, false)
|
||||
if (pos.right === null) {
|
||||
return
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
YEvent,
|
||||
YXmlText, YXmlElement, YXmlFragment, Transaction // eslint-disable-line
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
YMap,
|
||||
YXmlHookRefID,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
YText,
|
||||
YXmlTextRefID,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import { Observable } from 'lib0/observable'
|
||||
|
||||
import {
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
findIndexSS,
|
||||
getState,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import { AbstractType } from '../internals.js' // eslint-disable-line
|
||||
|
||||
import * as decoding from 'lib0/decoding'
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
YArray,
|
||||
YMap,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
writeID,
|
||||
readID,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
isDeleted,
|
||||
createDeleteSetFromStructStore,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
GC,
|
||||
splitItem,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
getState,
|
||||
writeStructsFromTransaction,
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import * as error from 'lib0/error'
|
||||
import * as encoding from 'lib0/encoding'
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
isDeleted,
|
||||
Item, AbstractType, Transaction, AbstractStruct // eslint-disable-line
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* @module encoding
|
||||
*/
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import { AbstractType, Item } from '../internals.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import {
|
||||
AbstractType // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import * as binary from 'lib0/binary'
|
||||
import * as decoding from 'lib0/decoding'
|
||||
import * as encoding from 'lib0/encoding'
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* Testing if encoding/decoding compatibility and integration compatiblity is given.
|
||||
* We expect that the document always looks the same, even if we upgrade the integration algorithm, or add additional encoding approaches.
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import * as Y from '../src/index.js'
|
||||
import * as t from 'lib0/testing'
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import * as Y from '../src/index.js'
|
||||
import * as t from 'lib0/testing'
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import * as t from 'lib0/testing'
|
||||
import * as prng from 'lib0/prng'
|
||||
import * as encoding from 'lib0/encoding'
|
||||
|
@ -3,6 +3,46 @@ import { init } from './testHelper.js' // eslint-disable-line
|
||||
import * as Y from '../src/index.js'
|
||||
import * as t from 'lib0/testing'
|
||||
|
||||
export const testInconsistentFormat = () => {
|
||||
/**
|
||||
* @param {Y.Doc} ydoc
|
||||
*/
|
||||
const testYjsMerge = ydoc => {
|
||||
const content = /** @type {Y.XmlText} */ (ydoc.get('text', Y.XmlText))
|
||||
content.format(0, 6, { bold: null })
|
||||
content.format(6, 4, { type: 'text' })
|
||||
t.compare(content.toDelta(), [
|
||||
{
|
||||
attributes: { type: 'text' },
|
||||
insert: 'Merge Test'
|
||||
},
|
||||
{
|
||||
attributes: { type: 'text', italic: true },
|
||||
insert: ' After'
|
||||
}
|
||||
])
|
||||
}
|
||||
const initializeYDoc = () => {
|
||||
const yDoc = new Y.Doc({ gc: false })
|
||||
|
||||
const content = /** @type {Y.XmlText} */ (yDoc.get('text', Y.XmlText))
|
||||
content.insert(0, ' After', { type: 'text', italic: true })
|
||||
content.insert(0, 'Test', { type: 'text' })
|
||||
content.insert(0, 'Merge ', { type: 'text', bold: true })
|
||||
return yDoc
|
||||
}
|
||||
{
|
||||
const yDoc = initializeYDoc()
|
||||
testYjsMerge(yDoc)
|
||||
}
|
||||
{
|
||||
const initialYDoc = initializeYDoc()
|
||||
const yDoc = new Y.Doc({ gc: false })
|
||||
Y.applyUpdate(yDoc, Y.encodeStateAsUpdate(initialYDoc))
|
||||
testYjsMerge(yDoc)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user