From 27cbe50e4339ba331424ac7deb3120ac97511ba5 Mon Sep 17 00:00:00 2001 From: Alec Gibson <12036746+alecgibson@users.noreply.github.com> Date: Thu, 16 Dec 2021 16:55:32 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20`invertWithDo?= =?UTF-8?q?c`=20for=20subtypes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change adds support for the [optional, but recommended][1] `invertWithDoc(op, doc) -> op'` method. `json0` itself already inverts fine without the doc, just using the `invert()` method, but this change adds support for subtypes, which only implement `invertWithDoc()`. [1]: https://github.com/ottypes/docs#optional-properties --- lib/json0.js | 21 +++++++++++++++++++-- test/json0.coffee | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/json0.js b/lib/json0.js index 9f538ee..b6a2ff9 100644 --- a/lib/json0.js +++ b/lib/json0.js @@ -65,13 +65,21 @@ json.create = function(data) { return data === undefined ? null : clone(data); }; -json.invertComponent = function(c) { +json.invertComponent = function(c, doc) { var c_ = {p: c.p}; + for (var i = 0; i < c.p.length; i++) { + var key = c.p[i]; + doc = doc && doc[key]; + } + // handle subtype ops if (c.t && subtypes[c.t]) { c_.t = c.t; - c_.o = subtypes[c.t].invert(c.o); + var subtype = subtypes[c.t]; + if (doc && typeof subtype.invertWithDoc === 'function') c_.o = subtype.invertWithDoc(c.o, doc); + else if (typeof subtype.invert === 'function') c_.o = subtype.invert(c.o); + else throw new Error("Subtype '" + c.t + "' is not invertible"); } if (c.si !== void 0) c_.sd = c.si; @@ -99,6 +107,15 @@ json.invert = function(op) { return iop; }; +json.invertWithDoc = function(op, doc) { + var op_ = op.slice().reverse(); + var iop = []; + for (var i = 0; i < op_.length; i++) { + iop.push(json.invertComponent(op_[i], doc)); + } + return iop; +} + json.checkValidOp = function(op) { for (var i = 0; i < op.length; i++) { if (!isArray(op[i].p)) throw new Error('Missing path'); diff --git a/test/json0.coffee b/test/json0.coffee index e2ee6df..019efdb 100644 --- a/test/json0.coffee +++ b/test/json0.coffee @@ -222,6 +222,27 @@ genTests = (type) -> assert.deepEqual [{p:[100], si:'hi'}], type.compose [{p:[100], si:'h'}], [{p:[101], si:'i'}] assert.deepEqual [{p:[], t:'text0', o:[{p:100, i:'hi'}]}], type.compose [{p:[], t:'text0', o:[{p:100, i:'h'}]}], [{p:[], t:'text0', o:[{p:101, i:'i'}]}] + describe '#invertWithDoc()', -> + it 'passes the doc to the subtype', -> + op = null + doc = null + + type.registerSubtype + name: 'invertible' + invertWithDoc: (o, d) -> + op = o + doc = d + + type.invertWithDoc [{p: ['foo', 'bar'], t: 'invertible', o: [{increment: 1}]}], {foo: {bar: 5}} + assert.deepEqual [{increment: 1}], op + assert.deepEqual 5, doc + + it 'throws if the subtype does not support inversion', -> + type.registerSubtype + name: 'not-invertible' + + assert.throws -> type.invertWithDoc [{p: ['foo'], t: 'not-invertible', o: [{increment: 1}]}], {foo: 5} + it 'moves ops on a moved element with the element', -> assert.deepEqual [{p:[10], ld:'x'}], type.transform [{p:[4], ld:'x'}], [{p:[4], lm:10}], 'left' assert.deepEqual [{p:[10, 1], si:'a'}], type.transform [{p:[4, 1], si:'a'}], [{p:[4], lm:10}], 'left'