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 67 68 69 70 71 72 73 74 75 | 15x 15x 15x 15x 15x 55x 55x 55x 7x 35x 35x 25x 20x 20x 20x 20x 20x 20x 20x 20x 20x 10x 10x 10x 10x 8x 8x 4x 4x 4x 4x 4x | 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'; import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @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]; } public encode(encoder: IMessagePackEncoder, parent?: AbstractOp) { encoder.encodeArrayHeader(this.props ? 4 : 3); encoder.writer.u8(OPCODE.merge); encoder.encodeArray(this.path as unknown[]); encoder.encodeNumber(this.pos); if (this.props) encoder.encodeAny(this.props); } } |