json-joy
Version:
Collection of libraries for building collaborative editing apps.
117 lines (116 loc) • 4.93 kB
JavaScript
import { OpAdd } from '../../op/OpAdd';
import { OpRemove } from '../../op/OpRemove';
import { OpReplace } from '../../op/OpReplace';
import { OpMove } from '../../op/OpMove';
import { OpCopy } from '../../op/OpCopy';
import { OpTest } from '../../op/OpTest';
import { OpFlip } from '../../op/OpFlip';
import { OpInc } from '../../op/OpInc';
import { OpStrIns } from '../../op/OpStrIns';
import { OpStrDel } from '../../op/OpStrDel';
import { OpSplit } from '../../op/OpSplit';
import { OpMerge } from '../../op/OpMerge';
import { OpExtend } from '../../op/OpExtend';
import { OpDefined } from '../../op/OpDefined';
import { OpUndefined } from '../../op/OpUndefined';
import { OpTestType } from '../../op/OpTestType';
import { OpTestString } from '../../op/OpTestString';
import { OpTestStringLen } from '../../op/OpTestStringLen';
import { OpContains } from '../../op/OpContains';
import { OpEnds } from '../../op/OpEnds';
import { OpStarts } from '../../op/OpStarts';
import { OpIn } from '../../op/OpIn';
import { OpLess } from '../../op/OpLess';
import { OpMore } from '../../op/OpMore';
import { OpAnd } from '../../op/OpAnd';
import { OpOr } from '../../op/OpOr';
import { OpNot } from '../../op/OpNot';
import { OpMatches } from '../../op/OpMatches';
import { OpType } from '../../op/OpType';
import { toPath } from '@jsonjoy.com/json-pointer';
import { createMatcherDefault } from '../../util';
export const operationToOp = (op, options) => {
switch (op.op) {
case 'add':
return new OpAdd(toPath(op.path), op.value);
case 'remove':
return new OpRemove(toPath(op.path), op.oldValue);
case 'replace':
return new OpReplace(toPath(op.path), op.value, op.oldValue);
case 'move':
return new OpMove(toPath(op.path), toPath(op.from));
case 'copy':
return new OpCopy(toPath(op.path), toPath(op.from));
case 'flip':
return new OpFlip(toPath(op.path));
case 'inc':
return new OpInc(toPath(op.path), op.inc);
case 'str_ins':
return new OpStrIns(toPath(op.path), op.pos, op.str);
case 'str_del':
return new OpStrDel(toPath(op.path), op.pos, op.str, op.len);
case 'split':
return new OpSplit(toPath(op.path), op.pos, op.props || null);
case 'merge':
return new OpMerge(toPath(op.path), op.pos, op.props || null);
case 'extend':
return new OpExtend(toPath(op.path), op.props, !!op.deleteNull);
default:
return operationToPredicateOp(op, options);
}
};
export const operationToPredicateOp = (op, options) => {
switch (op.op) {
case 'test':
return new OpTest(toPath(op.path), op.value, !!op.not);
case 'defined':
return new OpDefined(toPath(op.path));
case 'undefined':
return new OpUndefined(toPath(op.path));
case 'type':
return new OpType(toPath(op.path), op.value);
case 'test_type':
return new OpTestType(toPath(op.path), op.type);
case 'test_string':
return new OpTestString(toPath(op.path), op.pos, op.str, !!op.not);
case 'test_string_len':
return new OpTestStringLen(toPath(op.path), op.len, !!op.not);
case 'contains':
return new OpContains(toPath(op.path), op.value, !!op.ignore_case);
case 'ends':
return new OpEnds(toPath(op.path), op.value, !!op.ignore_case);
case 'starts':
return new OpStarts(toPath(op.path), op.value, !!op.ignore_case);
case 'matches':
return new OpMatches(toPath(op.path), op.value, !!op.ignore_case, options.createMatcher || createMatcherDefault);
case 'in':
return new OpIn(toPath(op.path), op.value);
case 'less':
return new OpLess(toPath(op.path), op.value);
case 'more':
return new OpMore(toPath(op.path), op.value);
case 'and': {
const path = toPath(op.path);
return new OpAnd(path, op.apply.map((x) => operationToPredicateOp({ ...x, path: [...path, ...toPath(x.path)] }, options)));
}
case 'or': {
const path = toPath(op.path);
return new OpOr(path, op.apply.map((x) => operationToPredicateOp({ ...x, path: [...path, ...toPath(x.path)] }, options)));
}
case 'not': {
const path = toPath(op.path);
return new OpNot(path, op.apply.map((x) => operationToPredicateOp({ ...x, path: [...path, ...toPath(x.path)] }, options)));
}
default:
throw new Error('OP_UNKNOWN');
}
};
export function decode(patch, options) {
const ops = [];
const length = patch.length;
for (let i = 0; i < length; i++) {
const op = operationToOp(patch[i], options);
ops.push(op);
}
return ops;
}