From 7064578b312657b0f7f05ac152b01598d5d73439 Mon Sep 17 00:00:00 2001 From: jos Date: Fri, 15 Dec 2017 21:02:17 +0100 Subject: [PATCH] Renamed keys to props in ESON model --- src/actions.js | 29 ++++++++++++------------- src/components/JSONNode.js | 16 +++++++------- src/eson.js | 35 +++++++++++-------------------- src/patchEson.js | 11 +++++----- test/eson.test.js | 2 +- test/patchEson.test.js | 32 ++++++++++++++-------------- test/utils/assertDeepEqualEson.js | 2 +- 7 files changed, 56 insertions(+), 71 deletions(-) diff --git a/src/actions.js b/src/actions.js index 0571df1..3e48952 100644 --- a/src/actions.js +++ b/src/actions.js @@ -45,7 +45,7 @@ export function changeProperty (eson, parentPath, oldProp, newProp) { const parent = getIn(eson, parentPath) // prevent duplicate property names - const uniqueNewProp = findUniqueName(newProp, parent[META].keys) + const uniqueNewProp = findUniqueName(newProp, parent[META].props) return [{ op: 'move', @@ -110,11 +110,11 @@ export function duplicate (eson, selection) { })) } else { // object.type === 'Object' - const before = root[META].keys[maxIndex] || null + const before = root[META].props[maxIndex] || null return paths.map(path => { const prop = last(path) - const newProp = findUniqueName(prop, root[META].keys) + const newProp = findUniqueName(prop, root[META].props) return { op: 'copy', @@ -158,7 +158,7 @@ export function insertBefore (eson, path, values) { // TODO: find a better name else { // object.type === 'Object' const before = last(path) return values.map(entry => { - const newProp = findUniqueName(entry.name, parent[META].keys) + const newProp = findUniqueName(entry.name, parent[META].props) return { op: 'add', path: compileJSONPointer(parentPath.concat(newProp)), @@ -203,11 +203,11 @@ export function replace (eson, selection, values) { // TODO: find a better name return removeActions.concat(insertActions) } else { // object.type === 'Object' - const before = root[META].keys[maxIndex] || null + const before = root[META].props[maxIndex] || null const removeActions = removeAll(pathsFromSelection(eson, selection)) const insertActions = values.map(entry => { - const newProp = findUniqueName(entry.name, root[META].keys) + const newProp = findUniqueName(entry.name, root[META].props) return { op: 'add', path: compileJSONPointer(rootPath.concat(newProp)), @@ -252,7 +252,7 @@ export function append (eson, parentPath, type) { }] } else { // object.type === 'Object' - const newProp = findUniqueName('', parent[META].keys) + const newProp = findUniqueName('', parent[META].props) return [{ op: 'add', @@ -327,24 +327,21 @@ export function sort (eson, path, order = null) { else { // object.type === 'Object' // order the properties by key - const orderedKeys = object[META].keys.slice().sort((a, b) => compare(a.name, b.name)) + const orderedProps = object[META].props.slice().sort((a, b) => compare(a.name, b.name)) // when no order is provided, test whether ordering ascending // changed anything. If not, sort descending - if (!order && strictShallowEqual(object[META].keys, orderedKeys)) { - orderedKeys.reverse() + if (!order && strictShallowEqual(object[META].props, orderedProps)) { + orderedProps.reverse() } - const orderedProps = cloneWithSymbols(object) - orderedProps[META] = setIn(object[META], ['keys'], orderedKeys) + const orderedObject = cloneWithSymbols(object) + orderedObject[META] = setIn(object[META], ['props'], orderedProps) return [{ op: 'replace', path: compileJSONPointer(path), - value: esonToJson({ - type: 'Object', - props: orderedProps - }), + value: esonToJson(orderedObject), jsoneditor: { order: orderedProps.map(prop => prop.name) } diff --git a/src/components/JSONNode.js b/src/components/JSONNode.js index d261697..01f0207 100644 --- a/src/components/JSONNode.js +++ b/src/components/JSONNode.js @@ -58,7 +58,7 @@ export default class JSONNode extends PureComponent { } renderJSONObject ({prop, index, eson, options, events}) { - const keys = eson[META].keys + const props = eson[META].props const node = h('div', { key: 'node', onKeyDown: this.handleKeyDown, @@ -68,24 +68,24 @@ export default class JSONNode extends PureComponent { // this.renderActionMenu('update', this.state.menu, this.handleCloseActionMenu), // this.renderActionMenuButton(), this.renderProperty(prop, index, eson, options), - this.renderReadonly(`{${keys.length}}`, `Array containing ${keys.length} items`), + this.renderReadonly(`{${props.length}}`, `Array containing ${props.length} items`), // this.renderFloatingMenuButton(), this.renderError(eson[META].error) ]) let childs if (eson[META].expanded) { - if (keys.length > 0) { - const props = keys.map(key => h(this.constructor, { - key: eson[key][META].id, + if (props.length > 0) { + const propsChilds = props.map(prop => h(this.constructor, { + key: eson[prop][META].id, // parent: this, - prop: key, - eson: eson[key], + prop, + eson: eson[prop], options, events })) - childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, props) + childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, propsChilds) } else { childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, diff --git a/src/eson.js b/src/eson.js index 510b6f8..2a04f37 100644 --- a/src/eson.js +++ b/src/eson.js @@ -49,10 +49,9 @@ export function jsonToEson (json, path = []) { if (isObject(json)) { let eson = {} - const keys = Object.keys(json) - keys.forEach((key) => eson[key] = jsonToEson(json[key], path.concat(key))) - // TODO: rename keys to props - eson[META] = { id, path, type: 'Object', keys } + const props = Object.keys(json) + props.forEach((prop) => eson[prop] = jsonToEson(json[prop], path.concat(prop))) + eson[META] = { id, path, type: 'Object', props } return eson } else if (Array.isArray(json)) { @@ -80,7 +79,7 @@ export function esonToJson (eson: ESON) { case 'Object': const object = {} - eson[META].keys.forEach(prop => { + eson[META].props.forEach(prop => { object[prop] = esonToJson(eson[prop]) }) @@ -385,13 +384,13 @@ export function applySelection (eson, selection) { // TODO: simplify the update function. Use pathsFromSelection ? if (root[META].type === 'Object') { - const startIndex = root[META].keys.indexOf(start) - const endIndex = root[META].keys.indexOf(end) + const startIndex = root[META].props.indexOf(start) + const endIndex = root[META].props.indexOf(end) const minIndex = Math.min(startIndex, endIndex) const maxIndex = Math.max(startIndex, endIndex) + 1 // include max index itself - const selectedProps = root[META].keys.slice(minIndex, maxIndex) + const selectedProps = root[META].props.slice(minIndex, maxIndex) selectedPaths = selectedProps.map(prop => rootPath.concat(prop)) let updatedObj = cloneWithSymbols(root) selectedProps.forEach(prop => { @@ -441,8 +440,8 @@ export function findSelectionIndices (root, rootPath, selection) { const end = (selection.after || selection.before || selection.end)[rootPath.length] // if no object we assume it's an Array - const startIndex = root[META].type === 'Object' ? root[META].keys.indexOf(start) : parseInt(start) - const endIndex = root[META].type === 'Object' ? root[META].keys.indexOf(end) : parseInt(end) + const startIndex = root[META].type === 'Object' ? root[META].props.indexOf(start) : parseInt(start) + const endIndex = root[META].type === 'Object' ? root[META].props.indexOf(end) : parseInt(end) const minIndex = Math.min(startIndex, endIndex) const maxIndex = Math.max(startIndex, endIndex) + @@ -462,7 +461,7 @@ export function pathsFromSelection (eson, selection: Selection): JSONPath[] { const { minIndex, maxIndex } = findSelectionIndices(root, rootPath, selection) if (root[META].type === 'Object') { - return times(maxIndex - minIndex, i => rootPath.concat(root[META].keys[i + minIndex])) + return times(maxIndex - minIndex, i => rootPath.concat(root[META].props[i + minIndex])) } else { // root.type === 'Array' return times(maxIndex - minIndex, i => rootPath.concat(String(i + minIndex))) @@ -580,18 +579,8 @@ export function resolvePathIndex (eson, path) { * or null if there is none */ export function findNextProp (parent, prop) { - const index = parent[META].keys.indexOf(prop) - return parent[META].keys[index + 1] || null -} - -/** - * Find the index of a property - * @param {ESON} object - * @param {string} prop - * @return {number} Returns the index when found, -1 when not found - */ -export function findPropertyIndex (object, prop) { - return object[META].keys.indexOf(prop) + const index = parent[META].props.indexOf(prop) + return parent[META].props[index + 1] || null } // TODO: move parseJSONPointer and compileJSONPointer to a separate file diff --git a/src/patchEson.js b/src/patchEson.js index e82fb30..7309530 100644 --- a/src/patchEson.js +++ b/src/patchEson.js @@ -179,11 +179,11 @@ export function remove (data, path) { } else { // object.type === 'Object' const prop = last(pathArray) - const index = parent[META].keys.indexOf(prop) - const nextProp = parent[META].keys[index + 1] || null + const index = parent[META].props.indexOf(prop) + const nextProp = parent[META].props[index + 1] || null let updatedParent = deleteIn(parent, [prop]) - updatedParent[META] = deleteIn(parent[META], ['keys', index], parent[META].keys) + updatedParent[META] = deleteIn(parent[META], ['props', index], parent[META].props) return { data: setIn(data, parentPath, updatePaths(updatedParent, parentPath)), @@ -224,7 +224,7 @@ export function add (data, path, value, options) { else { // parent.type === 'Object' updatedEson = updateIn(data, parentPath, (parent) => { const oldValue = getIn(data, pathArray) - const props = parent[META].keys + const props = parent[META].props const existingIndex = props.indexOf(prop) if (existingIndex !== -1) { @@ -235,7 +235,6 @@ export function add (data, path, value, options) { newValue[META] = setIn(newValue[META], ['id'], oldValue[META].id) // console.log('copied id from existing value' + oldValue[META].id) - // TODO: update paths of existing value return setIn(parent, [prop], newValue) } else { @@ -247,7 +246,7 @@ export function add (data, path, value, options) { let updatedKeys = props.slice() updatedKeys.splice(index, 0, prop) const updatedParent = setIn(parent, [prop], updatePaths(value, parentPath.concat(prop))) - return setIn(updatedParent, [META, 'keys'], updatedKeys) + return setIn(updatedParent, [META, 'props'], updatedKeys) } }) } diff --git a/test/eson.test.js b/test/eson.test.js index b14e4ff..087cc00 100644 --- a/test/eson.test.js +++ b/test/eson.test.js @@ -23,7 +23,7 @@ test('jsonToEson', t => { assertDeepEqualEson(t, jsonToEson(null), {[META]: {id: '[ID]', path: [], type: 'value', value: null}}) assertDeepEqualEson(t, jsonToEson(false), {[META]: {id: '[ID]', path: [], type: 'value', value: false}}) assertDeepEqualEson(t, jsonToEson({a:1, b: 2}), { - [META]: {id: '[ID]', path: [], type: 'Object', keys: ['a', 'b']}, + [META]: {id: '[ID]', path: [], type: 'Object', props: ['a', 'b']}, a: {[META]: {id: '[ID]', path: ['a'], type: 'value', value: 1}}, b: {[META]: {id: '[ID]', path: ['b'], type: 'value', value: 2}} }) diff --git a/test/patchEson.test.js b/test/patchEson.test.js index d0a5103..4994685 100644 --- a/test/patchEson.test.js +++ b/test/patchEson.test.js @@ -394,22 +394,22 @@ test('jsonpatch move (keep id intact)', t => { t.is(patchedValueId, valueId) }) -// test('jsonpatch move and replace (keep ids intact)', t => { -// const json = { a: 2, b: 3 } -// const patch = [ -// {op: 'move', from: '/a', path: '/b'} -// ] -// -// const data = jsonToEson(json) -// const bId = data.b[META].id -// -// t.deepEqual(data[META].keys, ['a', 'b']) -// -// const patchedData = patchEson(data, patch).data -// -// t.is(patchedData.b[META].id, bId) -// t.deepEqual(data[META].keys, ['b']) -// }) +test('jsonpatch move and replace (keep ids intact)', t => { + const json = { a: 2, b: 3 } + const patch = [ + {op: 'move', from: '/a', path: '/b'} + ] + + const data = jsonToEson(json) + const bId = data.b[META].id + + t.deepEqual(data[META].props, ['a', 'b']) + + const patchedData = patchEson(data, patch).data + + t.is(patchedData.b[META].id, bId) + t.deepEqual(patchedData[META].props, ['b']) +}) test('jsonpatch test (ok)', t => { const json = { diff --git a/test/utils/assertDeepEqualEson.js b/test/utils/assertDeepEqualEson.js index 7917bd6..6d2b18a 100644 --- a/test/utils/assertDeepEqualEson.js +++ b/test/utils/assertDeepEqualEson.js @@ -20,7 +20,7 @@ export function assertDeepEqualEson (t, actual, expected, path = [], ignoreIds = } else if (actualMeta.type === 'Object') { t.deepEqual(Object.keys(actual).sort(), Object.keys(expected).sort(), 'Actual properties should be equal, path=[${path.join(\', \')}]') - actualMeta.keys.forEach(key => assertDeepEqualEson(t, actual[key], expected[key], path.concat(key)), ignoreIds) + actualMeta.props.forEach(key => assertDeepEqualEson(t, actual[key], expected[key], path.concat(key)), ignoreIds) } else { // actual[META].type === 'value' t.deepEqual(Object.keys(actual), [], 'Value should not contain additional properties, path=[${path.join(\', \')}]')