diff --git a/src/utils/Doc.js b/src/utils/Doc.js index 60c934e2..4a58fc2d 100644 --- a/src/utils/Doc.js +++ b/src/utils/Doc.js @@ -169,6 +169,24 @@ export class Doc extends Observable { return this.get(name, YXmlFragment) } + /** + * Converts the entire document into a js object, recursively traversing each yjs type + * + * @return {Object} + */ + toJSON () { + /** + * @type {Object} + */ + const doc = {} + + for (const [k, v] of this.share.entries()) { + doc[k] = v.toJSON() + } + + return doc + } + /** * Emit `destroy` event and unregister all event handlers. */ diff --git a/tests/doc.tests.js b/tests/doc.tests.js index d07e503c..1570587d 100644 --- a/tests/doc.tests.js +++ b/tests/doc.tests.js @@ -30,3 +30,30 @@ export const testGetTypeEmptyId = tc => { t.assert(doc2.getText().toString() === 'hi') t.assert(doc2.getText('').toString() === 'hi') } + +/** + * @param {t.TestCase} tc + */ +export const testToJSON = tc => { + const doc = new Y.Doc() + t.compare(doc.toJSON(), {}, 'doc.toJSON yields empty object') + + const arr = doc.getArray('array') + arr.push(['test1']) + + const map = doc.getMap('map') + map.set('k1', 'v1') + const map2 = new Y.Map() + map.set('k2', map2) + map2.set('m2k1', 'm2v1') + + t.compare(doc.toJSON(), { + array: ['test1'], + map: { + k1: 'v1', + k2: { + m2k1: 'm2v1' + } + } + }, 'doc.toJSON has array and recursive map') +} diff --git a/tests/index.js b/tests/index.js index c07f1677..710b6edb 100644 --- a/tests/index.js +++ b/tests/index.js @@ -1,6 +1,6 @@ -import * as array from './y-array.tests.js' import * as map from './y-map.tests.js' +import * as array from './y-array.tests.js' import * as text from './y-text.tests.js' import * as xml from './y-xml.tests.js' import * as encoding from './encoding.tests.js' @@ -16,7 +16,7 @@ if (isBrowser) { log.createVConsole(document.body) } runTests({ - map, array, text, xml, doc, encoding, undoredo, compatibility + doc, map, array, text, xml, encoding, undoredo, compatibility }).then(success => { /* istanbul ignore next */ if (isNode) {