UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

64 lines (63 loc) 2.08 kB
import { clone as deepClone } from '@jsonjoy.com/util/lib/json-clone/clone'; import { operationToOp } from '../codec/json'; import { AbstractPredicateOp } from '../op'; import { compile } from '@jsonjoy.com/util/lib/codegen'; import { codegenOp } from './codegenOp'; export const apply = (patch, applyOptions, doc) => { const { mutate, createMatcher } = applyOptions; if (!mutate) doc = deepClone(doc); const length = patch.length; const opts = { createMatcher }; for (let i = 0; i < length; i++) { const op = operationToOp(patch[i], opts); const opResult = op.apply(doc); doc = opResult.doc; } return doc; }; export const $$apply = (operations, applyOptions) => { const { mutate, createMatcher } = applyOptions; const operationOptions = { createMatcher }; const fns = []; const length = operations.length; let hasNonPredicateOperations = false; for (let i = 0; i < length; i++) { const op = operationToOp(operations[i], operationOptions); const isPredicateOp = op instanceof AbstractPredicateOp; if (!isPredicateOp) hasNonPredicateOperations = true; fns.push(codegenOp(op)); } const needsToClone = !mutate && hasNonPredicateOperations; const deps = []; const depNames = []; if (needsToClone) { deps.push(deepClone); depNames.push('clone'); } let resultExpression = 'doc'; for (let i = 0; i < fns.length; i++) { const fn = fns[i]; const depName = `fn${i}`; deps.push(fn); depNames.push(depName); resultExpression = `${depName}(${resultExpression})`; } const js = /* js */ ` (function(${depNames.join(',')}) { return function(doc){ ${needsToClone ? /* js */ 'doc = clone(doc);' : ''} return ${resultExpression}; }; })`; return { deps, js: js, }; }; export const $apply = (operations, applyOptions) => { const fn = $$apply(operations, applyOptions); const compiled = compile(fn.js)(...fn.deps); return compiled; };