UNPKG

@sanity/mutator

Version:

A set of models to make it easier to utilize the powerful real time collaborative features of Sanity

67 lines (53 loc) 1.92 kB
import {applyPatches, parsePatch, type Patch} from '@sanity/diff-match-patch' import {type Expression} from '../jsonpath' import {type ImmutableAccessor} from './ImmutableAccessor' function applyPatch(patch: Patch[], oldValue: unknown) { // Silently avoid patching if the value type is not string if (typeof oldValue !== 'string') return oldValue const [result] = applyPatches(patch, oldValue, {allowExceedingIndices: true}) return result } export class DiffMatchPatch { path: string dmpPatch: Patch[] id: string constructor(id: string, path: string, dmpPatchSrc: string) { this.id = id this.path = path this.dmpPatch = parsePatch(dmpPatchSrc) } apply(targets: Expression[], accessor: ImmutableAccessor): ImmutableAccessor { let result = accessor // The target must be a container type if (result.containerType() === 'primitive') { return result } for (const target of targets) { if (target.isIndexReference()) { for (const index of target.toIndicies(accessor)) { // Skip patching unless the index actually currently exists const item = result.getIndex(index) if (!item) { continue } const oldValue = item.get() const nextValue = applyPatch(this.dmpPatch, oldValue) result = result.setIndex(index, nextValue) } continue } if (target.isAttributeReference() && result.hasAttribute(target.name())) { const attribute = result.getAttribute(target.name()) if (!attribute) { continue } const oldValue = attribute.get() const nextValue = applyPatch(this.dmpPatch, oldValue) result = result.setAttribute(target.name(), nextValue) continue } throw new Error(`Unable to apply diffMatchPatch to target ${target.toString()}`) } return result } }