mirror of
https://github.com/yjs/yjs.git
synced 2025-12-16 11:47:46 +01:00
fix suggestion issues with formatting by introducing an option to disable automattic formatting cleanups
This commit is contained in:
@@ -387,6 +387,7 @@ const insertText = (transaction, parent, currPos, text, attributes) => {
|
||||
* @function
|
||||
*/
|
||||
const cleanupFormattingGap = (transaction, start, curr, startAttributes, currAttributes) => {
|
||||
if (!transaction.doc.cleanupFormatting) return 0
|
||||
/**
|
||||
* @type {Item|null}
|
||||
*/
|
||||
@@ -417,6 +418,7 @@ const cleanupFormattingGap = (transaction, start, curr, startAttributes, currAtt
|
||||
if (endFormats.get(key) !== content || startAttrValue === value) {
|
||||
// Either this format is overwritten or it is not necessary because the attribute already existed.
|
||||
start.delete(transaction)
|
||||
transaction.cleanUps.add(start.id.client, start.id.clock, start.length)
|
||||
cleanups++
|
||||
if (!reachedCurr && (currAttributes.get(key) ?? null) === value && startAttrValue !== value) {
|
||||
if (startAttrValue === null) {
|
||||
@@ -443,6 +445,7 @@ const cleanupFormattingGap = (transaction, start, curr, startAttributes, currAtt
|
||||
* @param {Item | null} item
|
||||
*/
|
||||
const cleanupContextlessFormattingGap = (transaction, item) => {
|
||||
if (!transaction.doc.cleanupFormatting) return 0
|
||||
// iterate until item.right is null or content
|
||||
while (item && item.right && (item.right.deleted || !item.right.countable)) {
|
||||
item = item.right
|
||||
@@ -454,6 +457,7 @@ const cleanupContextlessFormattingGap = (transaction, item) => {
|
||||
const key = /** @type {ContentFormat} */ (item.content).key
|
||||
if (attrs.has(key)) {
|
||||
item.delete(transaction)
|
||||
transaction.cleanUps.add(item.id.client, item.id.clock, item.length)
|
||||
} else {
|
||||
attrs.add(key)
|
||||
}
|
||||
@@ -475,6 +479,7 @@ const cleanupContextlessFormattingGap = (transaction, item) => {
|
||||
* @return {number} How many formatting attributes have been cleaned up.
|
||||
*/
|
||||
export const cleanupYTextFormatting = type => {
|
||||
if (!type.doc?.cleanupFormatting) return 0
|
||||
let res = 0
|
||||
transact(/** @type {Doc} */ (type.doc), transaction => {
|
||||
let start = /** @type {Item} */ (type._start)
|
||||
|
||||
@@ -33,6 +33,9 @@ export const generateNewClientId = random.uint32
|
||||
* @property {any} [DocOpts.meta] Any kind of meta information you want to associate with this document. If this is a subdocument, remote peers will store the meta information as well.
|
||||
* @property {boolean} [DocOpts.autoLoad] If a subdocument, automatically load document. If this is a subdocument, remote peers will load the document as well automatically.
|
||||
* @property {boolean} [DocOpts.shouldLoad] Whether the document should be synced by the provider now. This is toggled to true when you call ydoc.load()
|
||||
* @property {boolean} [DocOpts.isSuggestionDoc] Set to true if this document merely suggests
|
||||
* changes. If this flag is not set in a suggestion document, automatic formatting changes will be
|
||||
* displayed as suggestions, which might not be intended.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -59,13 +62,15 @@ export class Doc extends ObservableV2 {
|
||||
/**
|
||||
* @param {DocOpts} opts configuration
|
||||
*/
|
||||
constructor ({ guid = random.uuidv4(), collectionid = null, gc = true, gcFilter = () => true, meta = null, autoLoad = false, shouldLoad = true } = {}) {
|
||||
constructor ({ guid = random.uuidv4(), collectionid = null, gc = true, gcFilter = () => true, meta = null, autoLoad = false, shouldLoad = true, isSuggestionDoc = true } = {}) {
|
||||
super()
|
||||
this.gc = gc
|
||||
this.gcFilter = gcFilter
|
||||
this.clientID = generateNewClientId()
|
||||
this.guid = guid
|
||||
this.collectionid = collectionid
|
||||
this.isSuggestionDoc = isSuggestionDoc
|
||||
this.cleanupFormatting = !isSuggestionDoc
|
||||
/**
|
||||
* @type {Map<string, AbstractType<YEvent<any>>>}
|
||||
*/
|
||||
@@ -350,9 +355,10 @@ export class Doc extends ObservableV2 {
|
||||
|
||||
/**
|
||||
* @param {Doc} ydoc
|
||||
* @param {DocOpts} [opts]
|
||||
*/
|
||||
export const cloneDoc = ydoc => {
|
||||
const clone = new Doc()
|
||||
export const cloneDoc = (ydoc, opts) => {
|
||||
const clone = new Doc(opts)
|
||||
applyUpdate(clone, encodeStateAsUpdate(ydoc))
|
||||
return clone
|
||||
}
|
||||
|
||||
@@ -62,6 +62,11 @@ export class Transaction {
|
||||
* Describes the set of deleted items by ids
|
||||
*/
|
||||
this.deleteSet = createIdSet()
|
||||
/**
|
||||
* Describes the set of items that are cleaned up / deleted by ids. It is a subset of
|
||||
* this.deleteSet
|
||||
*/
|
||||
this.cleanUps = createIdSet()
|
||||
/**
|
||||
* Describes the set of inserted items by ids
|
||||
*/
|
||||
@@ -354,7 +359,7 @@ const cleanupTransactions = (transactionCleanups, i) => {
|
||||
})
|
||||
fs.push(() => doc.emit('afterTransaction', [transaction, doc]))
|
||||
callAll(fs, [])
|
||||
if (transaction._needFormattingCleanup) {
|
||||
if (transaction._needFormattingCleanup && doc.cleanupFormatting) {
|
||||
cleanupYTextAfterTransaction(transaction)
|
||||
}
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user