Renamed keys to props in ESON model
This commit is contained in:
parent
1a6661fbb5
commit
7064578b31
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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'},
|
||||
|
|
35
src/eson.js
35
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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
})
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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(\', \')}]')
|
||||
|
|
Loading…
Reference in New Issue