diff --git a/README.md b/README.md index 707ad36..a404729 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,27 @@ The JSON OT type can be used to edit arbitrary JSON documents. +Forked from [ottypes/json0](https://github.com/ottypes/json0) to implement [presence](https://github.com/ottypes/docs/issues/29). + +Current status: Presence is basically working, but it's only transformed by subtype ops. Remaining work includes transforming presence by ops that are not text (`si`, `sd`) or subtype ops. Includes `li`, `ld`, `lm`, `oi`, `od`. The goal is that one day this fork will be merged into ottypes/json0 via this PR: [ottypes/json0: Presence](https://github.com/ottypes/json0/pull/31). + +In the mean time, this fork is published on NPM as [@datavis-tech/ot-json0](https://www.npmjs.com/package/@datavis-tech/ot-json0). If you want to try it out: + +``` +npm install -S @datavis-tech/ot-json0 +``` + +To [use it as the default ShareDB OT Type](https://github.com/share/sharedb/issues/284), you'll need to do the following (in both client and server): + +```js +const json0 = require('fork-of-ot-json0'); +const ShareDB = require('sharedb'); // or require('sharedb/lib/client'); +ShareDB.types.register(json0.type); +ShareDB.types.defaultType = json0.type; +``` + +To use the presence feature, you'll need to use the [Teamwork fork of ShareDB](https://github.com/teamwork/sharedb#readme) until the [ShareDB Presence PR](https://github.com/share/sharedb/pull/207) is merged. + ## Features The JSON OT type supports the following operations: @@ -312,6 +333,13 @@ The shape of our presence data is as follows: } ``` +Here's a demo https://github.com/datavis-tech/json0-presence-demo + +![presence](https://user-images.githubusercontent.com/68416/56134824-ffac3400-5fac-11e9-89a1-c60064c3eb67.gif) + +![selections](https://user-images.githubusercontent.com/68416/56134832-033fbb00-5fad-11e9-9274-a19b2287c5b1.gif) + + # Commentary This library was written a couple of years ago by [Jeremy Apthorp](https://github.com/nornagon). It was diff --git a/lib/json0.js b/lib/json0.js index 08367b2..e0558ee 100644 --- a/lib/json0.js +++ b/lib/json0.js @@ -659,101 +659,6 @@ json.comparePresence = function(pres1, pres2) { return JSON.stringify(pres1) === JSON.stringify(pres2); }; -// var transformPosition = function(cursor, op, isOwnOp) { -// var cursor = clone(cursor); -// -// var opIsAncestor = cursor.length >= op.p.length; // true also if op is self -// var opIsSibling = cursor.length === op.p.length; // true also if op is self -// var opIsAncestorSibling = cursor.length >= op.p.length; // true also if op is self or sibling of self -// var equalUpTo = -1; -// for (var i = 0; i < op.p.length; i++) { -// if (op.p[i] !== cursor[i]) { -// opIsAncestor = false; -// if (i < op.p.length - 1) { -// opIsSibling = false; -// opIsAncestorSibling = false; -// } -// } -// if (equalUpTo === i - 1 && op.p[i] === cursor[i]) { -// equalUpTo += 1; -// } -// } -// -// if (opIsSibling) { -// if (op.sd) { -// cursor[cursor.length - 1] = text.transformCursor( -// cursor[cursor.length - 1], -// [{ p: op.p[op.p.length - 1], d: op.sd }], -// isOwnOp ? 'right' : 'left' -// ); -// } -// if (op.si) { -// cursor[cursor.length - 1] = text.transformCursor( -// cursor[cursor.length - 1], -// [{ p: op.p[op.p.length - 1], i: op.si }], -// isOwnOp ? 'right' : 'left' -// ); -// } -// } -// -// if (opIsAncestor) { -// if (op.lm !== undefined) { -// cursor[equalUpTo] = op.lm; -// } -// if (op.od && op.oi) { -// cursor = op.p.slice(0, op.p.length); -// } else if (op.od) { -// cursor = op.p.slice(0, op.p.length - 1); -// } else if (op.ld && op.li) { -// cursor = op.p.slice(0, op.p.length); -// } else if (op.ld) { -// cursor = op.p.slice(0, op.p.length - 1); -// } -// } -// -// if (opIsAncestorSibling) { -// var lastPathIdx = op.p.length - 1; -// if ( -// !opIsAncestor && -// op.ld && -// !op.li && -// op.p[lastPathIdx] < cursor[lastPathIdx] -// ) { -// cursor[lastPathIdx] -= 1; -// } else if (!op.ld && op.li && op.p[lastPathIdx] <= cursor[lastPathIdx]) { -// cursor[lastPathIdx] += 1; -// } -// -// // if move item in list from after to before -// if ( -// !opIsAncestor && -// op.lm !== undefined && -// op.p[lastPathIdx] > cursor[lastPathIdx] && -// op.lm <= cursor[lastPathIdx] -// ) { -// cursor[lastPathIdx] += 1; -// // if move item in list from before to after -// } else if ( -// !opIsAncestor && -// op.lm !== undefined && -// op.p[lastPathIdx] < cursor[lastPathIdx] && -// op.lm >= cursor[lastPathIdx] -// ) { -// cursor[lastPathIdx] -= 1; -// } -// } -// -// return cursor; -// }; -// -// json.transformCursor = function(cursor, op, isOwnOp) { -// for (var i = 0; i < op.length; i++) { -// cursor = transformPosition(cursor, op[i], isOwnOp); -// } -// return cursor; -// }; -// - json.transformPresence = function(presence, op, isOwnOp) { // Don't transform path-only presence objects. if(!presence.t) return presence; diff --git a/package.json b/package.json index b3cae36..d0ca82d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ot-json0", - "version": "1.1.0", + "version": "1.2.0", "description": "JSON OT type", "main": "lib/index.js", "directories": { diff --git a/test/json0-presence.js b/test/json0-presence.js index 03e5f19..e819fc0 100644 --- a/test/json0-presence.js +++ b/test/json0-presence.js @@ -29,8 +29,8 @@ const sampleTextPresence = Object.assign({}, samplePresence, { // the user has "joined" the document at the top level. const samplePathOnlyPresence = { p: [] }; -//// These tests are inspired by the ones found here: -//// https://github.com/Teamwork/ot-rich-text/blob/master/test/Operation.js +// These tests are inspired by the ones found here: +// https://github.com/Teamwork/ot-rich-text/blob/master/test/Operation.js describe('json0 presence', () => { describe('createPresence', () => { it('should return the passed in presence object', () => {