Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 17x 17x 17x 17x 17x 55x 55x 55x 7x 4x 35x 35x 25x 20x 20x 20x 20x 20x 20x 20x 20x 20x 10x 10x 10x 10x 8x 8x | import type {CompactMergeOp, OPCODE_MERGE} from '../codec/compact/types'; import {AbstractOp} from './AbstractOp'; import type {OperationMerge} from '../types'; import {find, isArrayReference, type Path, formatJsonPointer} from '@jsonjoy.com/json-pointer'; import {isTextNode, isElementNode} from '../util'; import {OPCODE} from '../constants'; /** * @category JSON Patch Extended */ export class OpMerge extends AbstractOp<'merge'> { constructor( path: Path, public readonly pos: number, public readonly props: object | null, ) { super(path); } public op() { return 'merge' as const; } public code() { return OPCODE.merge; } public apply(doc: unknown) { const ref = find(doc, this.path); if (!isArrayReference(ref)) throw new Error('INVALID_TARGET'); if (ref.key <= 0) throw new Error('INVALID_KEY'); const one = ref.obj[ref.key - 1]; const two = ref.obj[ref.key]; const merged = this.merge(one, two); ref.obj[ref.key - 1] = merged; ref.obj.splice(ref.key, 1); return {doc, old: [one, two]}; } private merge<T>(one: T, two: T) { Iif (typeof one === 'string' && typeof two === 'string') return one + two; Iif (typeof one === 'number' && typeof two === 'number') return one + two; if (isTextNode(one) && isTextNode(two)) return {...one, ...two, text: one.text + two.text}; if (isElementNode(one) && isElementNode(two)) return {...one, ...two, children: [...one.children, ...two.children]}; return [one, two]; } public toJson(parent?: AbstractOp): OperationMerge { const op: OperationMerge = { op: 'merge', path: formatJsonPointer(this.path), pos: this.pos, }; if (this.props) op.props = this.props; return op; } public toCompact(parent: undefined | AbstractOp, verbose: boolean): CompactMergeOp { const opcode: OPCODE_MERGE = verbose ? 'merge' : OPCODE.merge; return this.props ? [opcode, this.path, this.pos, this.props] : [opcode, this.path, this.pos]; } } |