Renamed keys to props in ESON model

This commit is contained in:
jos 2017-12-15 21:02:17 +01:00
parent 1a6661fbb5
commit 7064578b31
7 changed files with 56 additions and 71 deletions

View File

@ -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)
}

View File

@ -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'},

View File

@ -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

View File

@ -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)
}
})
}

View File

@ -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}}
})

View File

@ -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 = {

View File

@ -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(\', \')}]')