From 981340139fc0b4601b74392e2adf6b67a4343002 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Sun, 25 Jun 2023 12:46:02 +0200 Subject: [PATCH] skip iterating when there are no formatting items - replaces #547 --- src/structs/ContentFormat.js | 18 ++++++++++-------- src/types/YText.js | 11 ++++++++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/structs/ContentFormat.js b/src/structs/ContentFormat.js index 6ac4c29c..dbc06a53 100644 --- a/src/structs/ContentFormat.js +++ b/src/structs/ContentFormat.js @@ -1,6 +1,6 @@ import { - AbstractType, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Item, StructStore, Transaction // eslint-disable-line + YText, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Item, StructStore, Transaction // eslint-disable-line } from '../internals.js' import * as error from 'lib0/error' @@ -47,28 +47,30 @@ export class ContentFormat { } /** - * @param {number} offset + * @param {number} _offset * @return {ContentFormat} */ - splice (offset) { + splice (_offset) { throw error.methodUnimplemented() } /** - * @param {ContentFormat} right + * @param {ContentFormat} _right * @return {boolean} */ - mergeWith (right) { + mergeWith (_right) { return false } /** - * @param {Transaction} transaction + * @param {Transaction} _transaction * @param {Item} item */ - integrate (transaction, item) { + integrate (_transaction, item) { // @todo searchmarker are currently unsupported for rich text documents - /** @type {AbstractType} */ (item.parent)._searchMarker = null + const p = /** @type {YText} */ (item.parent) + p._searchMarker = null + p._hasFormatting = true } /** diff --git a/src/types/YText.js b/src/types/YText.js index 79430c1a..399a6ff3 100644 --- a/src/types/YText.js +++ b/src/types/YText.js @@ -505,7 +505,7 @@ export const cleanupYTextAfterTransaction = transaction => { // cleanup in a new transaction transact(doc, (t) => { iterateDeletedStructs(transaction, transaction.deleteSet, item => { - if (item instanceof GC || needFullCleanup.has(/** @type {YText} */ (item.parent))) { + if (item instanceof GC || !(/** @type {YText} */ (item.parent)._hasFormatting) || needFullCleanup.has(/** @type {YText} */ (item.parent))) { return } const parent = /** @type {YText} */ (item.parent) @@ -859,9 +859,14 @@ export class YText extends AbstractType { */ this._pending = string !== undefined ? [() => this.insert(0, string)] : [] /** - * @type {Array} + * @type {Array|null} */ this._searchMarker = [] + /** + * Whether this YText contains formatting attributes. + * This flag is updated when a formatting item is integrated (see ContentFormat.integrate) + */ + this._hasFormatting = false } /** @@ -911,7 +916,7 @@ export class YText extends AbstractType { const event = new YTextEvent(this, transaction, parentSubs) callTypeObservers(this, transaction, event) // If a remote change happened, we try to cleanup potential formatting duplicates. - if (!transaction.local) { + if (!transaction.local && this._hasFormatting) { transaction._needFormattingCleanup = true } }