fix: recover stale table editor transforms

This commit is contained in:
lucaronin
2026-05-23 15:28:35 +02:00
parent 7709ad1002
commit 5bb3fe0550
4 changed files with 48 additions and 7 deletions

View File

@@ -35,7 +35,11 @@ interface RepairableBlockNoteEditor {
replaceBlocks?: (currentBlocks: unknown[], nextBlocks: unknown[]) => unknown
}
type RecoveryReason = 'mismatched_transaction' | 'stale_transaction' | 'transform_error'
type RecoveryReason =
| 'mismatched_transaction'
| 'stale_transaction'
| 'table_position_out_of_range'
| 'transform_error'
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null
@@ -67,12 +71,20 @@ function isInvalidContentTransactionError(error: unknown): boolean {
return error instanceof RangeError && error.message.startsWith('Invalid content for node ')
}
function isTablePositionOutOfRangeError(error: unknown): boolean {
return error instanceof RangeError && /^Index \d+ out of range for <tableRow\(/.test(error.message)
}
function isTransformError(error: unknown): boolean {
return error instanceof Error && error.name === 'TransformError'
}
function isRecoverableRangeError(error: unknown): boolean {
return isInvalidContentTransactionError(error) || isTablePositionOutOfRangeError(error)
}
export function isRecoverableEditorTransformError(error: unknown): boolean {
return error instanceof Error && (
error.name === 'TransformError'
|| isMismatchedTransactionError(error)
|| isInvalidContentTransactionError(error)
)
return isTransformError(error) || isMismatchedTransactionError(error) || isRecoverableRangeError(error)
}
function recoveryReason(
@@ -82,9 +94,14 @@ function recoveryReason(
): RecoveryReason {
if (transactionDocIsStale(transaction, view)) return 'stale_transaction'
if (isMismatchedTransactionError(error)) return 'mismatched_transaction'
if (isTablePositionOutOfRangeError(error)) return 'table_position_out_of_range'
return 'transform_error'
}
function shouldRepairEditorDocument(error: unknown): boolean {
return isRecoverableRangeError(error)
}
export function reportRecoveredEditorTransformError(reason: RecoveryReason, error: unknown): void {
console.warn('[editor] Recovered rich-editor transform error:', error)
trackEvent('rich_editor_transform_error_recovered', { reason })
@@ -132,7 +149,7 @@ function createRecoveringDispatch(
} catch (error) {
if (!isRecoverableEditorTransformError(error)) throw error
if (isInvalidContentTransactionError(error)) {
if (shouldRepairEditorDocument(error)) {
activeRecoverDocument(recoveryState)?.()
}
reportRecoveredEditorTransformError(recoveryReason(error, transaction, view), error)