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)
|
const parent = getIn(eson, parentPath)
|
||||||
|
|
||||||
// prevent duplicate property names
|
// prevent duplicate property names
|
||||||
const uniqueNewProp = findUniqueName(newProp, parent[META].keys)
|
const uniqueNewProp = findUniqueName(newProp, parent[META].props)
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
op: 'move',
|
op: 'move',
|
||||||
|
@ -110,11 +110,11 @@ export function duplicate (eson, selection) {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
else { // object.type === 'Object'
|
else { // object.type === 'Object'
|
||||||
const before = root[META].keys[maxIndex] || null
|
const before = root[META].props[maxIndex] || null
|
||||||
|
|
||||||
return paths.map(path => {
|
return paths.map(path => {
|
||||||
const prop = last(path)
|
const prop = last(path)
|
||||||
const newProp = findUniqueName(prop, root[META].keys)
|
const newProp = findUniqueName(prop, root[META].props)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
op: 'copy',
|
op: 'copy',
|
||||||
|
@ -158,7 +158,7 @@ export function insertBefore (eson, path, values) { // TODO: find a better name
|
||||||
else { // object.type === 'Object'
|
else { // object.type === 'Object'
|
||||||
const before = last(path)
|
const before = last(path)
|
||||||
return values.map(entry => {
|
return values.map(entry => {
|
||||||
const newProp = findUniqueName(entry.name, parent[META].keys)
|
const newProp = findUniqueName(entry.name, parent[META].props)
|
||||||
return {
|
return {
|
||||||
op: 'add',
|
op: 'add',
|
||||||
path: compileJSONPointer(parentPath.concat(newProp)),
|
path: compileJSONPointer(parentPath.concat(newProp)),
|
||||||
|
@ -203,11 +203,11 @@ export function replace (eson, selection, values) { // TODO: find a better name
|
||||||
return removeActions.concat(insertActions)
|
return removeActions.concat(insertActions)
|
||||||
}
|
}
|
||||||
else { // object.type === 'Object'
|
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 removeActions = removeAll(pathsFromSelection(eson, selection))
|
||||||
const insertActions = values.map(entry => {
|
const insertActions = values.map(entry => {
|
||||||
const newProp = findUniqueName(entry.name, root[META].keys)
|
const newProp = findUniqueName(entry.name, root[META].props)
|
||||||
return {
|
return {
|
||||||
op: 'add',
|
op: 'add',
|
||||||
path: compileJSONPointer(rootPath.concat(newProp)),
|
path: compileJSONPointer(rootPath.concat(newProp)),
|
||||||
|
@ -252,7 +252,7 @@ export function append (eson, parentPath, type) {
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
else { // object.type === 'Object'
|
else { // object.type === 'Object'
|
||||||
const newProp = findUniqueName('', parent[META].keys)
|
const newProp = findUniqueName('', parent[META].props)
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
op: 'add',
|
op: 'add',
|
||||||
|
@ -327,24 +327,21 @@ export function sort (eson, path, order = null) {
|
||||||
else { // object.type === 'Object'
|
else { // object.type === 'Object'
|
||||||
|
|
||||||
// order the properties by key
|
// 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
|
// when no order is provided, test whether ordering ascending
|
||||||
// changed anything. If not, sort descending
|
// changed anything. If not, sort descending
|
||||||
if (!order && strictShallowEqual(object[META].keys, orderedKeys)) {
|
if (!order && strictShallowEqual(object[META].props, orderedProps)) {
|
||||||
orderedKeys.reverse()
|
orderedProps.reverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderedProps = cloneWithSymbols(object)
|
const orderedObject = cloneWithSymbols(object)
|
||||||
orderedProps[META] = setIn(object[META], ['keys'], orderedKeys)
|
orderedObject[META] = setIn(object[META], ['props'], orderedProps)
|
||||||
|
|
||||||
return [{
|
return [{
|
||||||
op: 'replace',
|
op: 'replace',
|
||||||
path: compileJSONPointer(path),
|
path: compileJSONPointer(path),
|
||||||
value: esonToJson({
|
value: esonToJson(orderedObject),
|
||||||
type: 'Object',
|
|
||||||
props: orderedProps
|
|
||||||
}),
|
|
||||||
jsoneditor: {
|
jsoneditor: {
|
||||||
order: orderedProps.map(prop => prop.name)
|
order: orderedProps.map(prop => prop.name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ export default class JSONNode extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderJSONObject ({prop, index, eson, options, events}) {
|
renderJSONObject ({prop, index, eson, options, events}) {
|
||||||
const keys = eson[META].keys
|
const props = eson[META].props
|
||||||
const node = h('div', {
|
const node = h('div', {
|
||||||
key: 'node',
|
key: 'node',
|
||||||
onKeyDown: this.handleKeyDown,
|
onKeyDown: this.handleKeyDown,
|
||||||
|
@ -68,24 +68,24 @@ export default class JSONNode extends PureComponent {
|
||||||
// this.renderActionMenu('update', this.state.menu, this.handleCloseActionMenu),
|
// this.renderActionMenu('update', this.state.menu, this.handleCloseActionMenu),
|
||||||
// this.renderActionMenuButton(),
|
// this.renderActionMenuButton(),
|
||||||
this.renderProperty(prop, index, eson, options),
|
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.renderFloatingMenuButton(),
|
||||||
this.renderError(eson[META].error)
|
this.renderError(eson[META].error)
|
||||||
])
|
])
|
||||||
|
|
||||||
let childs
|
let childs
|
||||||
if (eson[META].expanded) {
|
if (eson[META].expanded) {
|
||||||
if (keys.length > 0) {
|
if (props.length > 0) {
|
||||||
const props = keys.map(key => h(this.constructor, {
|
const propsChilds = props.map(prop => h(this.constructor, {
|
||||||
key: eson[key][META].id,
|
key: eson[prop][META].id,
|
||||||
// parent: this,
|
// parent: this,
|
||||||
prop: key,
|
prop,
|
||||||
eson: eson[key],
|
eson: eson[prop],
|
||||||
options,
|
options,
|
||||||
events
|
events
|
||||||
}))
|
}))
|
||||||
|
|
||||||
childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, props)
|
childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, propsChilds)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
childs = h('div', {key: 'childs', className: 'jsoneditor-list'},
|
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)) {
|
if (isObject(json)) {
|
||||||
let eson = {}
|
let eson = {}
|
||||||
const keys = Object.keys(json)
|
const props = Object.keys(json)
|
||||||
keys.forEach((key) => eson[key] = jsonToEson(json[key], path.concat(key)))
|
props.forEach((prop) => eson[prop] = jsonToEson(json[prop], path.concat(prop)))
|
||||||
// TODO: rename keys to props
|
eson[META] = { id, path, type: 'Object', props }
|
||||||
eson[META] = { id, path, type: 'Object', keys }
|
|
||||||
return eson
|
return eson
|
||||||
}
|
}
|
||||||
else if (Array.isArray(json)) {
|
else if (Array.isArray(json)) {
|
||||||
|
@ -80,7 +79,7 @@ export function esonToJson (eson: ESON) {
|
||||||
case 'Object':
|
case 'Object':
|
||||||
const object = {}
|
const object = {}
|
||||||
|
|
||||||
eson[META].keys.forEach(prop => {
|
eson[META].props.forEach(prop => {
|
||||||
object[prop] = esonToJson(eson[prop])
|
object[prop] = esonToJson(eson[prop])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -385,13 +384,13 @@ export function applySelection (eson, selection) {
|
||||||
// TODO: simplify the update function. Use pathsFromSelection ?
|
// TODO: simplify the update function. Use pathsFromSelection ?
|
||||||
|
|
||||||
if (root[META].type === 'Object') {
|
if (root[META].type === 'Object') {
|
||||||
const startIndex = root[META].keys.indexOf(start)
|
const startIndex = root[META].props.indexOf(start)
|
||||||
const endIndex = root[META].keys.indexOf(end)
|
const endIndex = root[META].props.indexOf(end)
|
||||||
|
|
||||||
const minIndex = Math.min(startIndex, endIndex)
|
const minIndex = Math.min(startIndex, endIndex)
|
||||||
const maxIndex = Math.max(startIndex, endIndex) + 1 // include max index itself
|
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))
|
selectedPaths = selectedProps.map(prop => rootPath.concat(prop))
|
||||||
let updatedObj = cloneWithSymbols(root)
|
let updatedObj = cloneWithSymbols(root)
|
||||||
selectedProps.forEach(prop => {
|
selectedProps.forEach(prop => {
|
||||||
|
@ -441,8 +440,8 @@ export function findSelectionIndices (root, rootPath, selection) {
|
||||||
const end = (selection.after || selection.before || selection.end)[rootPath.length]
|
const end = (selection.after || selection.before || selection.end)[rootPath.length]
|
||||||
|
|
||||||
// if no object we assume it's an Array
|
// if no object we assume it's an Array
|
||||||
const startIndex = root[META].type === 'Object' ? root[META].keys.indexOf(start) : parseInt(start)
|
const startIndex = root[META].type === 'Object' ? root[META].props.indexOf(start) : parseInt(start)
|
||||||
const endIndex = root[META].type === 'Object' ? root[META].keys.indexOf(end) : parseInt(end)
|
const endIndex = root[META].type === 'Object' ? root[META].props.indexOf(end) : parseInt(end)
|
||||||
|
|
||||||
const minIndex = Math.min(startIndex, endIndex)
|
const minIndex = Math.min(startIndex, endIndex)
|
||||||
const maxIndex = Math.max(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)
|
const { minIndex, maxIndex } = findSelectionIndices(root, rootPath, selection)
|
||||||
|
|
||||||
if (root[META].type === 'Object') {
|
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'
|
else { // root.type === 'Array'
|
||||||
return times(maxIndex - minIndex, i => rootPath.concat(String(i + minIndex)))
|
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
|
* or null if there is none
|
||||||
*/
|
*/
|
||||||
export function findNextProp (parent, prop) {
|
export function findNextProp (parent, prop) {
|
||||||
const index = parent[META].keys.indexOf(prop)
|
const index = parent[META].props.indexOf(prop)
|
||||||
return parent[META].keys[index + 1] || null
|
return parent[META].props[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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move parseJSONPointer and compileJSONPointer to a separate file
|
// TODO: move parseJSONPointer and compileJSONPointer to a separate file
|
||||||
|
|
|
@ -179,11 +179,11 @@ export function remove (data, path) {
|
||||||
}
|
}
|
||||||
else { // object.type === 'Object'
|
else { // object.type === 'Object'
|
||||||
const prop = last(pathArray)
|
const prop = last(pathArray)
|
||||||
const index = parent[META].keys.indexOf(prop)
|
const index = parent[META].props.indexOf(prop)
|
||||||
const nextProp = parent[META].keys[index + 1] || null
|
const nextProp = parent[META].props[index + 1] || null
|
||||||
|
|
||||||
let updatedParent = deleteIn(parent, [prop])
|
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 {
|
return {
|
||||||
data: setIn(data, parentPath, updatePaths(updatedParent, parentPath)),
|
data: setIn(data, parentPath, updatePaths(updatedParent, parentPath)),
|
||||||
|
@ -224,7 +224,7 @@ export function add (data, path, value, options) {
|
||||||
else { // parent.type === 'Object'
|
else { // parent.type === 'Object'
|
||||||
updatedEson = updateIn(data, parentPath, (parent) => {
|
updatedEson = updateIn(data, parentPath, (parent) => {
|
||||||
const oldValue = getIn(data, pathArray)
|
const oldValue = getIn(data, pathArray)
|
||||||
const props = parent[META].keys
|
const props = parent[META].props
|
||||||
const existingIndex = props.indexOf(prop)
|
const existingIndex = props.indexOf(prop)
|
||||||
|
|
||||||
if (existingIndex !== -1) {
|
if (existingIndex !== -1) {
|
||||||
|
@ -235,7 +235,6 @@ export function add (data, path, value, options) {
|
||||||
newValue[META] = setIn(newValue[META], ['id'], oldValue[META].id)
|
newValue[META] = setIn(newValue[META], ['id'], oldValue[META].id)
|
||||||
// console.log('copied id from existing value' + oldValue[META].id)
|
// console.log('copied id from existing value' + oldValue[META].id)
|
||||||
|
|
||||||
// TODO: update paths of existing value
|
|
||||||
return setIn(parent, [prop], newValue)
|
return setIn(parent, [prop], newValue)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -247,7 +246,7 @@ export function add (data, path, value, options) {
|
||||||
let updatedKeys = props.slice()
|
let updatedKeys = props.slice()
|
||||||
updatedKeys.splice(index, 0, prop)
|
updatedKeys.splice(index, 0, prop)
|
||||||
const updatedParent = setIn(parent, [prop], updatePaths(value, parentPath.concat(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(null), {[META]: {id: '[ID]', path: [], type: 'value', value: null}})
|
||||||
assertDeepEqualEson(t, jsonToEson(false), {[META]: {id: '[ID]', path: [], type: 'value', value: false}})
|
assertDeepEqualEson(t, jsonToEson(false), {[META]: {id: '[ID]', path: [], type: 'value', value: false}})
|
||||||
assertDeepEqualEson(t, jsonToEson({a:1, b: 2}), {
|
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}},
|
a: {[META]: {id: '[ID]', path: ['a'], type: 'value', value: 1}},
|
||||||
b: {[META]: {id: '[ID]', path: ['b'], type: 'value', value: 2}}
|
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)
|
t.is(patchedValueId, valueId)
|
||||||
})
|
})
|
||||||
|
|
||||||
// test('jsonpatch move and replace (keep ids intact)', t => {
|
test('jsonpatch move and replace (keep ids intact)', t => {
|
||||||
// const json = { a: 2, b: 3 }
|
const json = { a: 2, b: 3 }
|
||||||
// const patch = [
|
const patch = [
|
||||||
// {op: 'move', from: '/a', path: '/b'}
|
{op: 'move', from: '/a', path: '/b'}
|
||||||
// ]
|
]
|
||||||
//
|
|
||||||
// const data = jsonToEson(json)
|
const data = jsonToEson(json)
|
||||||
// const bId = data.b[META].id
|
const bId = data.b[META].id
|
||||||
//
|
|
||||||
// t.deepEqual(data[META].keys, ['a', 'b'])
|
t.deepEqual(data[META].props, ['a', 'b'])
|
||||||
//
|
|
||||||
// const patchedData = patchEson(data, patch).data
|
const patchedData = patchEson(data, patch).data
|
||||||
//
|
|
||||||
// t.is(patchedData.b[META].id, bId)
|
t.is(patchedData.b[META].id, bId)
|
||||||
// t.deepEqual(data[META].keys, ['b'])
|
t.deepEqual(patchedData[META].props, ['b'])
|
||||||
// })
|
})
|
||||||
|
|
||||||
test('jsonpatch test (ok)', t => {
|
test('jsonpatch test (ok)', t => {
|
||||||
const json = {
|
const json = {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export function assertDeepEqualEson (t, actual, expected, path = [], ignoreIds =
|
||||||
}
|
}
|
||||||
else if (actualMeta.type === 'Object') {
|
else if (actualMeta.type === 'Object') {
|
||||||
t.deepEqual(Object.keys(actual).sort(), Object.keys(expected).sort(), 'Actual properties should be equal, path=[${path.join(\', \')}]')
|
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'
|
else { // actual[META].type === 'value'
|
||||||
t.deepEqual(Object.keys(actual), [], 'Value should not contain additional properties, path=[${path.join(\', \')}]')
|
t.deepEqual(Object.keys(actual), [], 'Value should not contain additional properties, path=[${path.join(\', \')}]')
|
||||||
|
|
Loading…
Reference in New Issue