Renamed 'jsonData' to 'ESON'

This commit is contained in:
jos 2017-09-08 13:36:15 +02:00
parent 2ee11399ec
commit 432e169f32
13 changed files with 390 additions and 361 deletions

View File

@ -1,4 +1,4 @@
import { compileJSONPointer, toDataPath, dataToJson, findNextProp } from './jsonData' import { compileJSONPointer, toEsonPath, esonToJson, findNextProp } from './eson'
import { findUniqueName } from './utils/stringUtils' import { findUniqueName } from './utils/stringUtils'
import { getIn } from './utils/immutabilityHelpers' import { getIn } from './utils/immutabilityHelpers'
import { isObject, stringConvert } from './utils/typeUtils' import { isObject, stringConvert } from './utils/typeUtils'
@ -7,7 +7,7 @@ import { compareAsc, compareDesc, strictShallowEqual } from './utils/arrayUtils'
/** /**
* Create a JSONPatch to change the value of a property or item * Create a JSONPatch to change the value of a property or item
* @param {JSONData} data * @param {ESON} data
* @param {Path} path * @param {Path} path
* @param {*} value * @param {*} value
* @return {Array} * @return {Array}
@ -15,8 +15,8 @@ import { compareAsc, compareDesc, strictShallowEqual } from './utils/arrayUtils'
export function changeValue (data, path, value) { export function changeValue (data, path, value) {
// console.log('changeValue', data, value) // console.log('changeValue', data, value)
const dataPath = toDataPath(data, path) const esonPath = toEsonPath(data, path)
const oldDataValue = getIn(data, dataPath) const oldDataValue = getIn(data, esonPath)
return [{ return [{
op: 'replace', op: 'replace',
@ -30,7 +30,7 @@ export function changeValue (data, path, value) {
/** /**
* Create a JSONPatch to change a property name * Create a JSONPatch to change a property name
* @param {JSONData} data * @param {ESON} data
* @param {Path} parentPath * @param {Path} parentPath
* @param {string} oldProp * @param {string} oldProp
* @param {string} newProp * @param {string} newProp
@ -39,8 +39,8 @@ export function changeValue (data, path, value) {
export function changeProperty (data, parentPath, oldProp, newProp) { export function changeProperty (data, parentPath, oldProp, newProp) {
// console.log('changeProperty', parentPath, oldProp, newProp) // console.log('changeProperty', parentPath, oldProp, newProp)
const dataPath = toDataPath(data, parentPath) const esonPath = toEsonPath(data, parentPath)
const parent = getIn(data, dataPath) const parent = getIn(data, esonPath)
// prevent duplicate property names // prevent duplicate property names
const uniqueNewProp = findUniqueName(newProp, parent.props.map(p => p.name)) const uniqueNewProp = findUniqueName(newProp, parent.props.map(p => p.name))
@ -57,14 +57,14 @@ export function changeProperty (data, parentPath, oldProp, newProp) {
/** /**
* Create a JSONPatch to change the type of a property or item * Create a JSONPatch to change the type of a property or item
* @param {JSONData} data * @param {ESON} data
* @param {Path} path * @param {Path} path
* @param {JSONDataType} type * @param {ESONType} type
* @return {Array} * @return {Array}
*/ */
export function changeType (data, path, type) { export function changeType (data, path, type) {
const dataPath = toDataPath(data, path) const esonPath = toEsonPath(data, path)
const oldValue = dataToJson(getIn(data, dataPath)) const oldValue = esonToJson(getIn(data, esonPath))
const newValue = convertType(oldValue, type) const newValue = convertType(oldValue, type)
// console.log('changeType', path, type, oldValue, newValue) // console.log('changeType', path, type, oldValue, newValue)
@ -86,7 +86,7 @@ export function changeType (data, path, type) {
* a unique property name for the duplicated node in case of duplicating * a unique property name for the duplicated node in case of duplicating
* and object property * and object property
* *
* @param {JSONData} data * @param {ESON} data
* @param {Path} path * @param {Path} path
* @return {Array} * @return {Array}
*/ */
@ -95,8 +95,8 @@ export function duplicate (data, path) {
const parentPath = path.slice(0, path.length - 1) const parentPath = path.slice(0, path.length - 1)
const dataPath = toDataPath(data, parentPath) const esonPath = toEsonPath(data, parentPath)
const parent = getIn(data, dataPath) const parent = getIn(data, esonPath)
if (parent.type === 'Array') { if (parent.type === 'Array') {
const index = parseInt(path[path.length - 1]) + 1 const index = parseInt(path[path.length - 1]) + 1
@ -128,17 +128,17 @@ export function duplicate (data, path) {
* a unique property name for the inserted node in case of duplicating * a unique property name for the inserted node in case of duplicating
* and object property * and object property
* *
* @param {JSONData} data * @param {ESON} data
* @param {Path} path * @param {Path} path
* @param {JSONDataType} type * @param {ESONType} type
* @return {Array} * @return {Array}
*/ */
export function insert (data, path, type) { export function insert (data, path, type) {
// console.log('insert', path, type) // console.log('insert', path, type)
const parentPath = path.slice(0, path.length - 1) const parentPath = path.slice(0, path.length - 1)
const dataPath = toDataPath(data, parentPath) const esonPath = toEsonPath(data, parentPath)
const parent = getIn(data, dataPath) const parent = getIn(data, esonPath)
const value = createEntry(type) const value = createEntry(type)
if (parent.type === 'Array') { if (parent.type === 'Array') {
@ -175,16 +175,16 @@ export function insert (data, path, type) {
* a unique property name for the inserted node in case of duplicating * a unique property name for the inserted node in case of duplicating
* and object property * and object property
* *
* @param {JSONData} data * @param {ESON} data
* @param {Path} parentPath * @param {Path} parentPath
* @param {JSONDataType} type * @param {ESONType} type
* @return {Array} * @return {Array}
*/ */
export function append (data, parentPath, type) { export function append (data, parentPath, type) {
// console.log('append', parentPath, value) // console.log('append', parentPath, value)
const dataPath = toDataPath(data, parentPath) const esonPath = toEsonPath(data, parentPath)
const parent = getIn(data, dataPath) const parent = getIn(data, esonPath)
const value = createEntry(type) const value = createEntry(type)
if (parent.type === 'Array') { if (parent.type === 'Array') {
@ -225,7 +225,7 @@ export function remove (path) {
/** /**
* Create a JSONPatch to order the items of an array or the properties of an object in ascending * Create a JSONPatch to order the items of an array or the properties of an object in ascending
* or descending order * or descending order
* @param {JSONData} data * @param {ESON} data
* @param {Path} path * @param {Path} path
* @param {'asc' | 'desc' | null} [order=null] If not provided, will toggle current ordering * @param {'asc' | 'desc' | null} [order=null] If not provided, will toggle current ordering
* @return {Array} * @return {Array}
@ -234,8 +234,8 @@ export function sort (data, path, order = null) {
// console.log('sort', path, order) // console.log('sort', path, order)
const compare = order === 'desc' ? compareDesc : compareAsc const compare = order === 'desc' ? compareDesc : compareAsc
const dataPath = toDataPath(data, path) const esonPath = toEsonPath(data, path)
const object = getIn(data, dataPath) const object = getIn(data, esonPath)
if (object.type === 'Array') { if (object.type === 'Array') {
const orderedItems = object.items.slice(0) const orderedItems = object.items.slice(0)
@ -252,7 +252,7 @@ export function sort (data, path, order = null) {
return [{ return [{
op: 'replace', op: 'replace',
path: compileJSONPointer(path), path: compileJSONPointer(path),
value: dataToJson({ value: esonToJson({
type: 'Array', type: 'Array',
items: orderedItems items: orderedItems
}) })
@ -273,7 +273,7 @@ export function sort (data, path, order = null) {
return [{ return [{
op: 'replace', op: 'replace',
path: compileJSONPointer(path), path: compileJSONPointer(path),
value: dataToJson({ value: esonToJson({
type: 'Object', type: 'Object',
props: orderedProps props: orderedProps
}), }),
@ -286,7 +286,7 @@ export function sort (data, path, order = null) {
/** /**
* Create a JSON entry * Create a JSON entry
* @param {JSONDataType} type * @param {ESONType} type
* @return {Array | Object | string} * @return {Array | Object | string}
*/ */
export function createEntry (type) { export function createEntry (type) {
@ -304,7 +304,7 @@ export function createEntry (type) {
/** /**
* Convert a JSON object into a different type. When possible, data is retained * Convert a JSON object into a different type. When possible, data is retained
* @param {*} value * @param {*} value
* @param {JSONDataType} type * @param {ESONType} type
* @return {*} * @return {*}
*/ */
export function convertType (value, type) { export function convertType (value, type) {

View File

@ -6,9 +6,9 @@ import ActionMenu from './menu/ActionMenu'
import { escapeHTML, unescapeHTML } from '../utils/stringUtils' import { escapeHTML, unescapeHTML } from '../utils/stringUtils'
import { getInnerText, insideRect, findParentWithAttribute } from '../utils/domUtils' import { getInnerText, insideRect, findParentWithAttribute } from '../utils/domUtils'
import { stringConvert, valueType, isUrl } from '../utils/typeUtils' import { stringConvert, valueType, isUrl } from '../utils/typeUtils'
import { compileJSONPointer } from '../jsonData' import { compileJSONPointer } from '../eson'
import type { PropertyData, JSONData, SearchResultStatus, Path } from '../types' import type { ESONObjectProperty, ESON, SearchResultStatus, Path } from '../types'
export default class JSONNode extends Component { export default class JSONNode extends Component {
static URL_TITLE = 'Ctrl+Click or Ctrl+Enter to open url' static URL_TITLE = 'Ctrl+Click or Ctrl+Enter to open url'
@ -165,7 +165,7 @@ export default class JSONNode extends Component {
} }
// TODO: simplify the method renderProperty // TODO: simplify the method renderProperty
renderProperty (prop?: PropertyData, index?: number, data: JSONData, options: {escapeUnicode: boolean, isPropertyEditable: (Path) => boolean}) { renderProperty (prop?: ESONObjectProperty, index?: number, data: ESON, options: {escapeUnicode: boolean, isPropertyEditable: (Path) => boolean}) {
const isIndex = typeof index === 'number' const isIndex = typeof index === 'number'
if (!prop && !isIndex) { if (!prop && !isIndex) {

View File

@ -2,7 +2,7 @@
import JSONNode from './JSONNode' import JSONNode from './JSONNode'
import type { PropertyData, JSONData, Path } from '../types' import type { ESONObjectProperty, ESON, Path } from '../types'
/** /**
* JSONNodeForm * JSONNodeForm
@ -22,7 +22,7 @@ export default class JSONNodeForm extends JSONNode {
} }
// render a readonly property // render a readonly property
renderProperty (prop?: PropertyData, index?: number, data: JSONData, options: {escapeUnicode: boolean, isPropertyEditable: (Path) => boolean}) { renderProperty (prop?: ESONObjectProperty, index?: number, data: ESON, options: {escapeUnicode: boolean, isPropertyEditable: (Path) => boolean}) {
const formOptions = Object.assign({}, options, { isPropertyEditable }) const formOptions = Object.assign({}, options, { isPropertyEditable })
return JSONNode.prototype.renderProperty.call(this, prop, index, data, formOptions) return JSONNode.prototype.renderProperty.call(this, prop, index, data, formOptions)

View File

@ -5,8 +5,8 @@ import Ajv from 'ajv'
import { parseJSON } from '../utils/jsonUtils' import { parseJSON } from '../utils/jsonUtils'
import { escapeUnicodeChars } from '../utils/stringUtils' import { escapeUnicodeChars } from '../utils/stringUtils'
import { enrichSchemaError, limitErrors } from '../utils/schemaUtils' import { enrichSchemaError, limitErrors } from '../utils/schemaUtils'
import { jsonToData, dataToJson } from '../jsonData' import { jsonToEson, esonToJson } from '../eson'
import { patchData } from '../jsonPatchData' import { patchEson } from '../patchEson'
import { createFindKeyBinding } from '../utils/keyBindings' import { createFindKeyBinding } from '../utils/keyBindings'
import { KEY_BINDINGS } from '../constants' import { KEY_BINDINGS } from '../constants'
@ -201,7 +201,7 @@ export default class TextMode extends Component {
// this is an ajv error message // this is an ajv error message
return h('tr', { key: index }, [ return h('tr', { key: index }, [
h('td', {key: 'icon'}, icon), h('td', {key: 'icon'}, icon),
h('td', {key: 'path'}, error.dataPath), h('td', {key: 'path'}, error.esonPath),
h('td', {key: 'message'}, error.message) h('td', {key: 'message'}, error.message)
]) ])
} }
@ -327,17 +327,17 @@ export default class TextMode extends Component {
/** /**
* Apply a JSONPatch to the current JSON document * Apply a JSONPatch to the current JSON document
* @param {JSONPatch} actions JSONPatch actions * @param {JSONPatch} actions JSONPatch actions
* @return {JSONPatchResult} Returns a JSONPatch result containing the * @return {ESONPatchAction} Returns a JSONPatch result containing the
* patch, a patch to revert the action, and * patch, a patch to revert the action, and
* an error object which is null when successful * an error object which is null when successful
*/ */
patch (actions) { patch (actions) {
const json = this.get() const json = this.get()
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, actions) const result = patchEson(data, actions)
this.set(dataToJson(result.data)) this.set(esonToJson(result.data))
return { return {
patch: actions, patch: actions,

View File

@ -9,12 +9,12 @@ import { parseJSON } from '../utils/jsonUtils'
import { allButLast } from '../utils/arrayUtils' import { allButLast } from '../utils/arrayUtils'
import { enrichSchemaError } from '../utils/schemaUtils' import { enrichSchemaError } from '../utils/schemaUtils'
import { import {
jsonToData, dataToJson, toDataPath, pathExists, jsonToEson, esonToJson, toEsonPath, pathExists,
expand, expandPath, addErrors, expand, expandPath, addErrors,
search, addSearchResults, nextSearchResult, previousSearchResult, search, addSearchResults, nextSearchResult, previousSearchResult,
compileJSONPointer compileJSONPointer
} from '../jsonData' } from '../eson'
import { patchData } from '../jsonPatchData' import { patchEson } from '../patchEson'
import { import {
duplicate, insert, append, remove, duplicate, insert, append, remove,
changeType, changeValue, changeProperty, sort changeType, changeValue, changeProperty, sort
@ -31,7 +31,7 @@ import {
import { createFindKeyBinding } from '../utils/keyBindings' import { createFindKeyBinding } from '../utils/keyBindings'
import { KEY_BINDINGS } from '../constants' import { KEY_BINDINGS } from '../constants'
import type { JSONData, JSONPatch } from '../types' import type { ESON, ESONPatch } from '../types'
const AJV_OPTIONS = { const AJV_OPTIONS = {
allErrors: true, allErrors: true,
@ -64,7 +64,7 @@ export default class TreeMode extends Component {
constructor (props) { constructor (props) {
super(props) super(props)
const data = jsonToData(this.props.data || {}, TreeMode.expandAll, []) const data = jsonToEson(this.props.data || {}, TreeMode.expandAll, [])
this.id = Math.round(Math.random() * 1e5) // TODO: create a uuid here? this.id = Math.round(Math.random() * 1e5) // TODO: create a uuid here?
@ -270,7 +270,7 @@ export default class TreeMode extends Component {
*/ */
getErrors () { getErrors () {
if (this.state.compiledSchema) { if (this.state.compiledSchema) {
const valid = this.state.compiledSchema(dataToJson(this.state.data)) const valid = this.state.compiledSchema(esonToJson(this.state.data))
if (!valid) { if (!valid) {
return this.state.compiledSchema.errors.map(enrichSchemaError) return this.state.compiledSchema.errors.map(enrichSchemaError)
} }
@ -364,10 +364,10 @@ export default class TreeMode extends Component {
/** @private */ /** @private */
handleExpand = (path, expanded, recurse) => { handleExpand = (path, expanded, recurse) => {
if (recurse) { if (recurse) {
const dataPath = toDataPath(this.state.data, path) const esonPath = toEsonPath(this.state.data, path)
this.setState({ this.setState({
data: updateIn(this.state.data, dataPath, function (child) { data: updateIn(this.state.data, esonPath, function (child) {
return expand(child, (path) => true, expanded) return expand(child, (path) => true, expanded)
}) })
}) })
@ -474,8 +474,8 @@ export default class TreeMode extends Component {
} }
/** /**
* Apply a JSONPatch to the current JSON document and emit a change event * Apply a ESONPatch to the current JSON document and emit a change event
* @param {JSONPatch} actions * @param {ESONPatch} actions
* @private * @private
*/ */
handlePatch = (actions) => { handlePatch = (actions) => {
@ -504,13 +504,13 @@ export default class TreeMode extends Component {
* Emit an onChange event when there is a listener for it. * Emit an onChange event when there is a listener for it.
* @private * @private
*/ */
emitOnChange (patch: JSONPatch, revert: JSONPatch, data: JSONData) { emitOnChange (patch: ESONPatch, revert: ESONPatch, data: ESON) {
if (this.props.onPatch) { if (this.props.onPatch) {
this.props.onPatch(patch, revert) this.props.onPatch(patch, revert)
} }
if (this.props.onChange || this.props.onChangeText) { if (this.props.onChange || this.props.onChangeText) {
const json = dataToJson(data) const json = esonToJson(data)
if (this.props.onChange) { if (this.props.onChange) {
this.props.onChange(json) this.props.onChange(json)
@ -539,7 +539,7 @@ export default class TreeMode extends Component {
const historyIndex = this.state.historyIndex const historyIndex = this.state.historyIndex
const historyItem = history[historyIndex] const historyItem = history[historyIndex]
const result = patchData(this.state.data, historyItem.undo) const result = patchEson(this.state.data, historyItem.undo)
this.setState({ this.setState({
data: result.data, data: result.data,
@ -557,7 +557,7 @@ export default class TreeMode extends Component {
const historyIndex = this.state.historyIndex - 1 const historyIndex = this.state.historyIndex - 1
const historyItem = history[historyIndex] const historyItem = history[historyIndex]
const result = patchData(this.state.data, historyItem.redo) const result = patchEson(this.state.data, historyItem.redo)
this.setState({ this.setState({
data: result.data, data: result.data,
@ -570,13 +570,13 @@ export default class TreeMode extends Component {
} }
/** /**
* Apply a JSONPatch to the current JSON document * Apply a ESONPatch to the current JSON document
* @param {JSONPatch} actions JSONPatch actions * @param {ESONPatch} actions ESONPatch actions
* @param {PatchOptions} [options] If no expand function is provided, the * @param {ESONPatchOptions} [options] If no expand function is provided, the
* expanded state will be kept as is for * expanded state will be kept as is for
* existing paths. New paths will be fully * existing paths. New paths will be fully
* expanded. * expanded.
* @return {JSONPatchResult} Returns a JSONPatch result containing the * @return {ESONPatchAction} Returns a ESONPatch result containing the
* patch, a patch to revert the action, and * patch, a patch to revert the action, and
* an error object which is null when successful * an error object which is null when successful
*/ */
@ -586,7 +586,7 @@ export default class TreeMode extends Component {
} }
const expand = options.expand || (path => this.expandKeepOrExpandAll(path)) const expand = options.expand || (path => this.expandKeepOrExpandAll(path))
const result = patchData(this.state.data, actions, expand) const result = patchEson(this.state.data, actions, expand)
const data = result.data const data = result.data
if (this.props.history != false) { if (this.props.history != false) {
@ -629,7 +629,7 @@ export default class TreeMode extends Component {
const expand = this.props.expand || TreeMode.expandRoot const expand = this.props.expand || TreeMode.expandRoot
this.setState({ this.setState({
data: jsonToData(json, expand, []), data: jsonToEson(json, expand, []),
// TODO: do we want to keep history when .set(json) is called? (currently we remove history) // TODO: do we want to keep history when .set(json) is called? (currently we remove history)
history: [], history: [],
@ -642,7 +642,7 @@ export default class TreeMode extends Component {
* @returns {Object | Array | string | number | boolean | null} json * @returns {Object | Array | string | number | boolean | null} json
*/ */
get () { get () {
return dataToJson(this.state.data) return esonToJson(this.state.data)
} }
/** /**
@ -723,7 +723,7 @@ export default class TreeMode extends Component {
* @return {boolean} Returns true when expanded, false otherwise * @return {boolean} Returns true when expanded, false otherwise
*/ */
isExpanded (path) { isExpanded (path) {
return getIn(this.state.data, toDataPath(this.state.data, path)).expanded return getIn(this.state.data, toEsonPath(this.state.data, path)).expanded
} }
/** /**

View File

@ -2,7 +2,7 @@ import {
selectContentEditable, hasClassName, selectContentEditable, hasClassName,
findParentWithAttribute, findParentWithClassName findParentWithAttribute, findParentWithClassName
} from '../../utils/domUtils' } from '../../utils/domUtils'
import { compileJSONPointer, parseJSONPointer } from '../../jsonData' import { compileJSONPointer, parseJSONPointer } from '../../eson'
// singleton // singleton
let lastInputName = null let lastInputName = null

View File

@ -1,8 +1,8 @@
// @flow weak // @flow weak
/** /**
* This file contains functions to act on a JSONData object. * This file contains functions to act on a ESON object.
* All functions are pure and don't mutate the JSONData. * All functions are pure and don't mutate the ESON.
*/ */
import { setIn, getIn } from './utils/immutabilityHelpers' import { setIn, getIn } from './utils/immutabilityHelpers'
@ -10,9 +10,13 @@ import { isObject } from './utils/typeUtils'
import { last, allButLast } from './utils/arrayUtils' import { last, allButLast } from './utils/arrayUtils'
import isEqual from 'lodash/isEqual' import isEqual from 'lodash/isEqual'
import type { JSONData, ObjectData, ItemData, DataPointer, Path } from './types' import type {
ESON, ESONObject, ESONArrayItem, ESONPointer, ESONType, ESONPath,
Path,
JSONPath, JSONType
} from './types'
type RecurseCallback = (value: JSONData, path: Path, root: JSONData) => JSONData type RecurseCallback = (value: ESON, path: Path, root: ESON) => ESON
/** /**
* Expand function which will expand all nodes * Expand function which will expand all nodes
@ -24,14 +28,14 @@ export function expandAll (path) {
} }
/** /**
* Convert a JSON object into the internally used data model * Convert a JSON object into ESON
* @param {Object | Array | string | number | boolean | null} json * @param {Object | Array | string | number | boolean | null} json
* @param {function(path: Path)} [expand] * @param {function(path: JSONPath)} [expand]
* @param {Path} [path=[]] * @param {JSONPath} [path=[]]
* @param {JSONDataType} [type='value'] Optional json data type for the created value * @param {ESONType} [type='value'] Optional eson type for the created value
* @return {JSONData} * @return {ESON}
*/ */
export function jsonToData (json, expand = expandAll, path = [], type = 'value') : JSONData { export function jsonToEson (json, expand = expandAll, path: JSONPath = [], type: ESONType = 'value') : ESON {
if (Array.isArray(json)) { if (Array.isArray(json)) {
return { return {
type: 'Array', type: 'Array',
@ -39,7 +43,7 @@ export function jsonToData (json, expand = expandAll, path = [], type = 'value')
items: json.map((child, index) => { items: json.map((child, index) => {
return { return {
id: getId(), // TODO: use id based on index (only has to be unique within this array) id: getId(), // TODO: use id based on index (only has to be unique within this array)
value: jsonToData(child, expand, path.concat(index)) value: jsonToEson(child, expand, path.concat(index))
} }
}) })
} }
@ -52,75 +56,75 @@ export function jsonToData (json, expand = expandAll, path = [], type = 'value')
return { return {
id: getId(), // TODO: use id based on index (only has to be unique within this array) id: getId(), // TODO: use id based on index (only has to be unique within this array)
name, name,
value: jsonToData(json[name], expand, path.concat(name)) value: jsonToEson(json[name], expand, path.concat(name))
} }
}) })
} }
} }
else { // value else { // value
return { return {
type, type: (type === 'string') ? 'string' : 'value',
value: json value: json
} }
} }
} }
/** /**
* Convert the internal data model to a regular JSON object * Convert an ESON object to a JSON object
* @param {JSONData} data * @param {ESON} eson
* @return {Object | Array | string | number | boolean | null} json * @return {Object | Array | string | number | boolean | null} json
*/ */
export function dataToJson (data: JSONData) { export function esonToJson (eson: ESON) {
switch (data.type) { switch (eson.type) {
case 'Array': case 'Array':
return data.items.map(item => dataToJson(item.value)) return eson.items.map(item => esonToJson(item.value))
case 'Object': case 'Object':
const object = {} const object = {}
data.props.forEach(prop => { eson.props.forEach(prop => {
object[prop.name] = dataToJson(prop.value) object[prop.name] = esonToJson(prop.value)
}) })
return object return object
default: // type 'string' or 'value' default: // type 'string' or 'value'
return data.value return eson.value
} }
} }
/** /**
* Convert a path of a JSON object into a path in the corresponding data model * Convert a path of a JSON object into a path in the corresponding ESON object
* @param {JSONData} data * @param {ESON} eson
* @param {Path} path * @param {JSONPath} path
* @return {Path} dataPath * @return {ESONPath} esonPath
* @private * @private
*/ */
export function toDataPath (data: JSONData, path: Path) : Path { export function toEsonPath (eson: ESON, path: JSONPath) : ESONPath {
if (path.length === 0) { if (path.length === 0) {
return [] return []
} }
if (data.type === 'Array') { if (eson.type === 'Array') {
// index of an array // index of an array
const index = path[0] const index = path[0]
const item = data.items[parseInt(index)] const item = eson.items[parseInt(index)]
if (!item) { if (!item) {
throw new Error('Array item "' + index + '" not found') throw new Error('Array item "' + index + '" not found')
} }
return ['items', index, 'value'].concat(toDataPath(item.value, path.slice(1))) return ['items', index, 'value'].concat(toEsonPath(item.value, path.slice(1)))
} }
else if (data.type === 'Object') { else if (eson.type === 'Object') {
// object property. find the index of this property // object property. find the index of this property
const index = findPropertyIndex(data, path[0]) const index = findPropertyIndex(eson, path[0])
const prop = data.props[index] const prop = eson.props[index]
if (!prop) { if (!prop) {
throw new Error('Object property "' + path[0] + '" not found') throw new Error('Object property "' + path[0] + '" not found')
} }
return ['props', index, 'value'] return ['props', index, 'value']
.concat(toDataPath(prop.value, path.slice(1))) .concat(toEsonPath(prop.value, path.slice(1)))
} }
else { else {
return [] return []
@ -131,19 +135,19 @@ type ExpandCallback = (Path) => boolean
/** /**
* Expand or collapse one or multiple items or properties * Expand or collapse one or multiple items or properties
* @param {JSONData} data * @param {ESON} eson
* @param {function(path: Path) : boolean | Path} callback * @param {function(path: Path) : boolean | Path} callback
* When a path, the object/array at this path will be expanded/collapsed * When a path, the object/array at this path will be expanded/collapsed
* When a function, all objects and arrays for which callback * When a function, all objects and arrays for which callback
* returns true will be expanded/collapsed * returns true will be expanded/collapsed
* @param {boolean} [expanded=true] New expanded state: true to expand, false to collapse * @param {boolean} [expanded=true] New expanded state: true to expand, false to collapse
* @return {JSONData} * @return {ESON}
*/ */
export function expand (data: JSONData, callback: Path | (Path) => boolean, expanded: boolean = true) { export function expand (eson: ESON, callback: Path | (Path) => boolean, expanded: boolean = true) {
// console.log('expand', callback, expand) // console.log('expand', callback, expand)
if (typeof callback === 'function') { if (typeof callback === 'function') {
return transform(data, function (value: JSONData, path: Path, root: JSONData) : JSONData { return transform(eson, function (value: ESON, path: Path, root: ESON) : ESON {
if (value.type === 'Array' || value.type === 'Object') { if (value.type === 'Array' || value.type === 'Object') {
if (callback(path)) { if (callback(path)) {
return setIn(value, ['expanded'], expanded) return setIn(value, ['expanded'], expanded)
@ -154,9 +158,9 @@ export function expand (data: JSONData, callback: Path | (Path) => boolean, expa
}) })
} }
else if (Array.isArray(callback)) { else if (Array.isArray(callback)) {
const dataPath: Path = toDataPath(data, callback) const esonPath: Path = toEsonPath(eson, callback)
return setIn(data, dataPath.concat(['expanded']), expanded) return setIn(eson, esonPath.concat(['expanded']), expanded)
} }
else { else {
throw new Error('Callback function or path expected') throw new Error('Callback function or path expected')
@ -166,50 +170,49 @@ export function expand (data: JSONData, callback: Path | (Path) => boolean, expa
/** /**
* Expand all Objects and Arrays on a path * Expand all Objects and Arrays on a path
*/ */
export function expandPath (data: JSONData, path?: Path) : JSONData { export function expandPath (eson: ESON, path?: JSONPath) : ESON {
let updatedData = data let updatedEson = eson
if (path) { if (path) {
updatedData = expand(updatedData, [], true) // expand root updatedEson = expand(updatedEson, [], true) // expand root
for (let i = 0; i < path.length; i++) { for (let i = 0; i < path.length; i++) {
const pathPart = path.slice(0, i + 1) const pathPart = path.slice(0, i + 1)
updatedData = expand(updatedData, pathPart, true) updatedEson = expand(updatedEson, pathPart, true)
} }
} }
return updatedData return updatedEson
} }
/** /**
* Merge one or multiple errors (for example JSON schema errors) * Merge one or multiple errors (for example JSON schema errors) into the ESON object
* into the data
* *
* @param {JSONData} data * @param {ESON} eson
* @param {JSONSchemaError[]} errors * @param {JSONSchemaError[]} errors
*/ */
export function addErrors (data: JSONData, errors) { export function addErrors (eson: ESON, errors) {
let updatedData = data let updatedEson = eson
if (errors) { if (errors) {
errors.forEach(error => { errors.forEach(error => {
const dataPath = toDataPath(data, parseJSONPointer(error.dataPath)) const esonPath = toEsonPath(eson, parseJSONPointer(error.esonPath))
// TODO: do we want to be able to store multiple errors per item? // TODO: do we want to be able to store multiple errors per item?
updatedData = setIn(updatedData, dataPath.concat('error'), error) updatedEson = setIn(updatedEson, esonPath.concat('error'), error)
}) })
} }
return updatedData return updatedEson
} }
/** /**
* Search some text in all properties and values * Search some text in all properties and values
*/ */
export function search (data: JSONData, text: string): DataPointer[] { export function search (eson: ESON, text: string): ESONPointer[] {
let results: DataPointer[] = [] let results: ESONPointer[] = []
if (text !== '') { if (text !== '') {
traverse(data, function (value, path) { traverse(eson, function (value, path: JSONPath) {
// check property name // check property name
if (path.length > 0) { if (path.length > 0) {
const prop = last(path) const prop = last(path)
@ -217,7 +220,7 @@ export function search (data: JSONData, text: string): DataPointer[] {
// only add search result when this is an object property name, // only add search result when this is an object property name,
// don't add search result for array indices // don't add search result for array indices
const parentPath = allButLast(path) const parentPath = allButLast(path)
const parent = getIn(data, toDataPath(data, parentPath)) const parent = getIn(eson, toEsonPath(eson, parentPath))
if (parent.type === 'Object') { if (parent.type === 'Object') {
results.push({path, type: 'property'}) results.push({path, type: 'property'})
} }
@ -244,7 +247,7 @@ export function search (data: JSONData, text: string): DataPointer[] {
* returned as next * returned as next
* - When `searchResults` is empty, null will be returned * - When `searchResults` is empty, null will be returned
*/ */
export function nextSearchResult (searchResults: DataPointer[], current: DataPointer): DataPointer | null { export function nextSearchResult (searchResults: ESONPointer[], current: ESONPointer): ESONPointer | null {
if (searchResults.length === 0) { if (searchResults.length === 0) {
return null return null
} }
@ -268,7 +271,7 @@ export function nextSearchResult (searchResults: DataPointer[], current: DataPoi
* returned as next * returned as next
* - When `searchResults` is empty, null will be returned * - When `searchResults` is empty, null will be returned
*/ */
export function previousSearchResult (searchResults: DataPointer[], current: DataPointer): DataPointer | null { export function previousSearchResult (searchResults: ESONPointer[], current: ESONPointer): ESONPointer | null {
if (searchResults.length === 0) { if (searchResults.length === 0) {
return null return null
} }
@ -285,27 +288,27 @@ export function previousSearchResult (searchResults: DataPointer[], current: Dat
} }
/** /**
* Merge searchResults into the data * Merge searchResults into the eson object
*/ */
export function addSearchResults (data: JSONData, searchResults: DataPointer[], activeSearchResult: DataPointer) { export function addSearchResults (eson: ESON, searchResults: ESONPointer[], activeSearchResult: ESONPointer) {
let updatedData = data let updatedEson = eson
searchResults.forEach(function (searchResult) { searchResults.forEach(function (searchResult) {
if (searchResult.type === 'value') { if (searchResult.type === 'value') {
const dataPath = toDataPath(data, searchResult.path).concat('searchResult') const esonPath = toEsonPath(updatedEson, searchResult.path).concat('searchResult')
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal' const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
updatedData = setIn(updatedData, dataPath, value) updatedEson = setIn(updatedEson, esonPath, value)
} }
if (searchResult.type === 'property') { if (searchResult.type === 'property') {
const valueDataPath = toDataPath(data, searchResult.path) const esonPath = toEsonPath(updatedEson, searchResult.path)
const propertyDataPath = allButLast(valueDataPath).concat('searchResult') const propertyPath = allButLast(esonPath).concat('searchResult')
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal' const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
updatedData = setIn(updatedData, propertyDataPath, value) updatedEson = setIn(updatedEson, propertyPath, value)
} }
}) })
return updatedData return updatedEson
} }
/** /**
@ -319,25 +322,25 @@ export function containsCaseInsensitive (text: string, search: string): boolean
} }
/** /**
* Recursively transform JSONData: a recursive "map" function * Recursively transform ESON: a recursive "map" function
* @param {JSONData} data * @param {ESON} eson
* @param {function(value: JSONData, path: Path, root: JSONData)} callback * @param {function(value: ESON, path: Path, root: ESON)} callback
* @return {JSONData} Returns the transformed data * @return {ESON} Returns the transformed eson object
*/ */
export function transform (data: JSONData, callback: RecurseCallback) { export function transform (eson: ESON, callback: RecurseCallback) : ESON {
return recurseTransform (data, [], data, callback) return recurseTransform (eson, [], eson, callback)
} }
/** /**
* Recursively transform JSONData * Recursively transform ESON
* @param {JSONData} value * @param {ESON} value
* @param {Path} path * @param {JSONPath} path
* @param {JSONData} root The root object, object at path=[] * @param {ESON} root The root object, object at path=[]
* @param {function(value: JSONData, path: Path, root: JSONData)} callback * @param {function(value: ESON, path: Path, root: ESON)} callback
* @return {JSONData} Returns the transformed data * @return {ESON} Returns the transformed eson object
*/ */
function recurseTransform (value: JSONData, path: Path, root: JSONData, callback: RecurseCallback) : JSONData { function recurseTransform (value: ESON, path: JSONPath, root: ESON, callback: RecurseCallback) : ESON {
let updatedValue = callback(value, path, root) let updatedValue: ESON = callback(value, path, root)
if (value.type === 'Array') { if (value.type === 'Array') {
let updatedItems = updatedValue.items let updatedItems = updatedValue.items
@ -367,27 +370,27 @@ function recurseTransform (value: JSONData, path: Path, root: JSONData, callback
} }
/** /**
* Recursively loop over a JSONData object: a recursive "forEach" function. * Recursively loop over a ESON object: a recursive "forEach" function.
* @param {JSONData} data * @param {ESON} eson
* @param {function(value: JSONData, path: Path, root: JSONData)} callback * @param {function(value: ESON, path: JSONPath, root: ESON)} callback
*/ */
export function traverse (data: JSONData, callback: RecurseCallback) { export function traverse (eson: ESON, callback: RecurseCallback) {
return recurseTraverse (data, [], data, callback) return recurseTraverse (eson, [], eson, callback)
} }
/** /**
* Recursively traverse a JSONData object * Recursively traverse a ESON object
* @param {JSONData} value * @param {ESON} value
* @param {Path} path * @param {JSONPath} path
* @param {JSONData | null} root The root object, object at path=[] * @param {ESON | null} root The root object, object at path=[]
* @param {function(value: JSONData, path: Path, root: JSONData)} callback * @param {function(value: ESON, path: Path, root: ESON)} callback
*/ */
function recurseTraverse (value: JSONData, path: Path, root: JSONData, callback: RecurseCallback) { function recurseTraverse (value: ESON, path: JSONPath, root: ESON, callback: RecurseCallback) {
callback(value, path, root) callback(value, path, root)
switch (value.type) { switch (value.type) {
case 'Array': { case 'Array': {
value.items.forEach((item: ItemData, index) => { value.items.forEach((item: ESONArrayItem, index) => {
recurseTraverse(item.value, path.concat(String(index)), root, callback) recurseTraverse(item.value, path.concat(String(index)), root, callback)
}) })
break break
@ -406,14 +409,14 @@ function recurseTraverse (value: JSONData, path: Path, root: JSONData, callback:
} }
/** /**
* Test whether a path exists in the json data * Test whether a path exists in the eson object
* @param {JSONData} data * @param {ESON} eson
* @param {Path} path * @param {JSONPath} path
* @return {boolean} Returns true if the path exists, else returns false * @return {boolean} Returns true if the path exists, else returns false
* @private * @private
*/ */
export function pathExists (data, path) { export function pathExists (eson, path) {
if (data === undefined) { if (eson === undefined) {
return false return false
} }
@ -421,18 +424,17 @@ export function pathExists (data, path) {
return true return true
} }
let index if (eson.type === 'Array') {
if (data.type === 'Array') {
// index of an array // index of an array
index = path[0] const index = path[0]
const item = data.items[index] const item = eson.items[index]
return pathExists(item && item.value, path.slice(1)) return pathExists(item && item.value, path.slice(1))
} }
else { else {
// object property. find the index of this property // object property. find the index of this property
index = findPropertyIndex(data, path[0]) const index = findPropertyIndex(eson, path[0])
const prop = data.props[index] const prop = eson.props[index]
return pathExists(prop && prop.value, path.slice(1)) return pathExists(prop && prop.value, path.slice(1))
} }
@ -441,14 +443,14 @@ export function pathExists (data, path) {
/** /**
* Resolve the index for `arr/-`, replace it with an index value equal to the * Resolve the index for `arr/-`, replace it with an index value equal to the
* length of the array * length of the array
* @param {JSONData} data * @param {ESON} eson
* @param {Path} path * @param {Path} path
* @return {Path} * @return {Path}
*/ */
export function resolvePathIndex (data, path) { export function resolvePathIndex (eson, path) {
if (path[path.length - 1] === '-') { if (path[path.length - 1] === '-') {
const parentPath = path.slice(0, path.length - 1) const parentPath = path.slice(0, path.length - 1)
const parent = getIn(data, toDataPath(data, parentPath)) const parent = getIn(eson, toEsonPath(eson, parentPath))
if (parent.type === 'Array') { if (parent.type === 'Array') {
const index = parent.items.length const index = parent.items.length
@ -464,12 +466,12 @@ export function resolvePathIndex (data, path) {
/** /**
* Find the property after provided property * Find the property after provided property
* @param {JSONData} parent * @param {ESON} parent
* @param {string} prop * @param {string} prop
* @return {string | null} Returns the name of the next property, * @return {string | null} Returns the name of the next property,
* or null if there is none * or null if there is none
*/ */
export function findNextProp (parent: ObjectData, prop: string) : string | null { export function findNextProp (parent: ESONObject, prop: string) : string | null {
const index = findPropertyIndex(parent, prop) const index = findPropertyIndex(parent, prop)
if (index === -1) { if (index === -1) {
return null return null
@ -481,14 +483,16 @@ export function findNextProp (parent: ObjectData, prop: string) : string | null
/** /**
* Find the index of a property * Find the index of a property
* @param {ObjectData} object * @param {ESONObject} object
* @param {string} prop * @param {string} prop
* @return {number} Returns the index when found, -1 when not found * @return {number} Returns the index when found, -1 when not found
*/ */
export function findPropertyIndex (object: ObjectData, prop: string) { export function findPropertyIndex (object: ESONObject, prop: string) {
return object.props.findIndex(p => p.name === prop) return object.props.findIndex(p => p.name === prop)
} }
// TODO: move parseJSONPointer and compileJSONPointer to a separate file
/** /**
* Parse a JSON Pointer * Parse a JSON Pointer
* WARNING: this is not a complete implementation * WARNING: this is not a complete implementation
@ -514,6 +518,8 @@ export function compileJSONPointer (path: Path) {
.join('') .join('')
} }
// TODO: move getId and createUniqueId to a separate file
/** /**
* Get a new "unique" id. Id's are created from an incremental counter. * Get a new "unique" id. Id's are created from an incremental counter.
* @return {number} * @return {number}

View File

@ -4,7 +4,7 @@ import JSONEditor from './components/JSONEditor'
import CodeMode from './components/CodeMode' import CodeMode from './components/CodeMode'
import TextMode from './components/TextMode' import TextMode from './components/TextMode'
import TreeMode from './components/TreeMode' import TreeMode from './components/TreeMode'
import { compileJSONPointer, parseJSONPointer } from './jsonData' import { compileJSONPointer, parseJSONPointer } from './eson'
import '!style!css!less!./jsoneditor.less' import '!style!css!less!./jsoneditor.less'

View File

@ -1,27 +1,24 @@
import isEqual from 'lodash/isEqual' import isEqual from 'lodash/isEqual'
import type { import type { ESON, Path, JSONPatch, ESONPatchAction, ESONPatchOptions, ESONPatchResult } from './types'
JSONData, Path,
JSONPatch, JSONPatchAction, PatchOptions, JSONPatchResult
} from './types'
import { setIn, updateIn, getIn, deleteIn, insertAt } from './utils/immutabilityHelpers' import { setIn, updateIn, getIn, deleteIn, insertAt } from './utils/immutabilityHelpers'
import { allButLast } from './utils/arrayUtils' import { allButLast } from './utils/arrayUtils'
import { import {
jsonToData, dataToJson, toDataPath, jsonToEson, esonToJson, toEsonPath,
parseJSONPointer, compileJSONPointer, parseJSONPointer, compileJSONPointer,
expandAll, pathExists, resolvePathIndex, findPropertyIndex, findNextProp, getId expandAll, pathExists, resolvePathIndex, findPropertyIndex, findNextProp, getId
} from './jsonData' } from './eson'
/** /**
* Apply a patch to a JSONData object * Apply a patch to a ESON object
* @param {JSONData} data * @param {ESON} eson
* @param {Array} patch A JSON patch * @param {Array} patch A JSON patch
* @param {function(path: Path)} [expand] Optional function to determine * @param {function(path: Path)} [expand] Optional function to determine
* what nodes must be expanded * what nodes must be expanded
* @return {{data: JSONData, revert: Object[], error: Error | null}} * @return {{data: ESON, revert: Object[], error: Error | null}}
*/ */
export function patchData (data: JSONData, patch: JSONPatchAction[], expand = expandAll) { export function patchEson (eson: ESON, patch: ESONPatchAction[], expand = expandAll) {
let updatedData = data let updatedEson = eson
let revert = [] let revert = []
for (let i = 0; i < patch.length; i++) { for (let i = 0; i < patch.length; i++) {
@ -33,17 +30,17 @@ export function patchData (data: JSONData, patch: JSONPatchAction[], expand = ex
switch (action.op) { switch (action.op) {
case 'add': { case 'add': {
const path = parseJSONPointer(action.path) const path = parseJSONPointer(action.path)
const newValue = jsonToData(action.value, expand, path, options && options.type) const newValue = jsonToEson(action.value, expand, path, options && options.type)
const result = add(updatedData, action.path, newValue, options) const result = add(updatedEson, action.path, newValue, options)
updatedData = result.data updatedEson = result.data
revert = result.revert.concat(revert) revert = result.revert.concat(revert)
break break
} }
case 'remove': { case 'remove': {
const result = remove(updatedData, action.path) const result = remove(updatedEson, action.path)
updatedData = result.data updatedEson = result.data
revert = result.revert.concat(revert) revert = result.revert.concat(revert)
break break
@ -51,9 +48,9 @@ export function patchData (data: JSONData, patch: JSONPatchAction[], expand = ex
case 'replace': { case 'replace': {
const path = parseJSONPointer(action.path) const path = parseJSONPointer(action.path)
const newValue = jsonToData(action.value, expand, path, options && options.type) const newValue = jsonToEson(action.value, expand, path, options && options.type)
const result = replace(updatedData, path, newValue) const result = replace(updatedEson, path, newValue)
updatedData = result.data updatedEson = result.data
revert = result.revert.concat(revert) revert = result.revert.concat(revert)
break break
@ -62,14 +59,14 @@ export function patchData (data: JSONData, patch: JSONPatchAction[], expand = ex
case 'copy': { case 'copy': {
if (!action.from) { if (!action.from) {
return { return {
data, data: eson,
revert: [], revert: [],
error: new Error('Property "from" expected in copy action ' + JSON.stringify(action)) error: new Error('Property "from" expected in copy action ' + JSON.stringify(action))
} }
} }
const result = copy(updatedData, action.path, action.from, options) const result = copy(updatedEson, action.path, action.from, options)
updatedData = result.data updatedEson = result.data
revert = result.revert.concat(revert) revert = result.revert.concat(revert)
break break
@ -78,14 +75,14 @@ export function patchData (data: JSONData, patch: JSONPatchAction[], expand = ex
case 'move': { case 'move': {
if (!action.from) { if (!action.from) {
return { return {
data, data: eson,
revert: [], revert: [],
error: new Error('Property "from" expected in move action ' + JSON.stringify(action)) error: new Error('Property "from" expected in move action ' + JSON.stringify(action))
} }
} }
const result = move(updatedData, action.path, action.from, options) const result = move(updatedEson, action.path, action.from, options)
updatedData = result.data updatedEson = result.data
revert = result.revert.concat(revert) revert = result.revert.concat(revert)
break break
@ -93,9 +90,9 @@ export function patchData (data: JSONData, patch: JSONPatchAction[], expand = ex
case 'test': { case 'test': {
// when a test fails, cancel the whole patch and return the error // when a test fails, cancel the whole patch and return the error
const error = test(updatedData, action.path, action.value) const error = test(updatedEson, action.path, action.value)
if (error) { if (error) {
return { data, revert: [], error} return { data: eson, revert: [], error}
} }
break break
@ -104,7 +101,7 @@ export function patchData (data: JSONData, patch: JSONPatchAction[], expand = ex
default: { default: {
// unknown jsonpatch operation. Cancel the whole patch and return an error // unknown jsonpatch operation. Cancel the whole patch and return an error
return { return {
data, data: eson,
revert: [], revert: [],
error: new Error('Unknown jsonpatch op ' + JSON.stringify(action.op)) error: new Error('Unknown jsonpatch op ' + JSON.stringify(action.op))
} }
@ -115,7 +112,7 @@ export function patchData (data: JSONData, patch: JSONPatchAction[], expand = ex
// TODO: Simplify revert when possible: // TODO: Simplify revert when possible:
// when a previous action takes place on the same path, remove the first // when a previous action takes place on the same path, remove the first
return { return {
data: updatedData, data: updatedEson,
revert: simplifyPatch(revert), revert: simplifyPatch(revert),
error: null error: null
} }
@ -123,21 +120,21 @@ export function patchData (data: JSONData, patch: JSONPatchAction[], expand = ex
/** /**
* Replace an existing item * Replace an existing item
* @param {JSONData} data * @param {ESON} data
* @param {Path} path * @param {Path} path
* @param {JSONData} value * @param {ESON} value
* @return {{data: JSONData, revert: JSONPatch}} * @return {{data: ESON, revert: JSONPatch}}
*/ */
export function replace (data: JSONData, path: Path, value: JSONData) { export function replace (data: ESON, path: Path, value: ESON) {
const dataPath = toDataPath(data, path) const esonPath = toEsonPath(data, path)
const oldValue = getIn(data, dataPath) const oldValue = getIn(data, esonPath)
return { return {
data: setIn(data, dataPath, value), data: setIn(data, esonPath, value),
revert: [{ revert: [{
op: 'replace', op: 'replace',
path: compileJSONPointer(path), path: compileJSONPointer(path),
value: dataToJson(oldValue), value: esonToJson(oldValue),
jsoneditor: { jsoneditor: {
type: oldValue.type type: oldValue.type
} }
@ -147,27 +144,27 @@ export function replace (data: JSONData, path: Path, value: JSONData) {
/** /**
* Remove an item or property * Remove an item or property
* @param {JSONData} data * @param {ESON} data
* @param {string} path * @param {string} path
* @return {{data: JSONData, revert: JSONPatch}} * @return {{data: ESON, revert: JSONPatch}}
*/ */
export function remove (data: JSONData, path: string) { export function remove (data: ESON, path: string) {
// console.log('remove', path) // console.log('remove', path)
const pathArray = parseJSONPointer(path) const pathArray = parseJSONPointer(path)
const parentPath = pathArray.slice(0, pathArray.length - 1) const parentPath = pathArray.slice(0, pathArray.length - 1)
const parent = getIn(data, toDataPath(data, parentPath)) const parent = getIn(data, toEsonPath(data, parentPath))
const dataValue = getIn(data, toDataPath(data, pathArray)) const dataValue = getIn(data, toEsonPath(data, pathArray))
const value = dataToJson(dataValue) const value = esonToJson(dataValue)
if (parent.type === 'Array') { if (parent.type === 'Array') {
const dataPath = toDataPath(data, pathArray) const esonPath = toEsonPath(data, pathArray)
// remove the 'value' property, we want to remove the whole item from the items array // remove the 'value' property, we want to remove the whole item from the items array
dataPath.pop() esonPath.pop()
return { return {
data: deleteIn(data, dataPath), data: deleteIn(data, esonPath),
revert: [{ revert: [{
op: 'add', op: 'add',
path, path,
@ -179,14 +176,14 @@ export function remove (data: JSONData, path: string) {
} }
} }
else { // object.type === 'Object' else { // object.type === 'Object'
const dataPath = toDataPath(data, pathArray) const esonPath = toEsonPath(data, pathArray)
const prop = pathArray[pathArray.length - 1] const prop = pathArray[pathArray.length - 1]
// remove the 'value' property, we want to remove the whole object property from props // remove the 'value' property, we want to remove the whole object property from props
dataPath.pop() esonPath.pop()
return { return {
data: deleteIn(data, dataPath), data: deleteIn(data, esonPath),
revert: [{ revert: [{
op: 'add', op: 'add',
path, path,
@ -233,32 +230,32 @@ export function simplifyPatch(patch: JSONPatch) {
/** /**
* @param {JSONData} data * @param {ESON} data
* @param {string} path * @param {string} path
* @param {JSONData} value * @param {ESON} value
* @param {{before?: string}} [options] * @param {{before?: string}} [options]
* @param {number} [id] Optional id for the new item * @param {number} [id] Optional id for the new item
* @return {{data: JSONData, revert: JSONPatch}} * @return {{data: ESON, revert: JSONPatch}}
* @private * @private
*/ */
export function add (data: JSONData, path: string, value: JSONData, options, id = getId()) { export function add (data: ESON, path: string, value: ESON, options, id = getId()) {
const pathArray = parseJSONPointer(path) const pathArray = parseJSONPointer(path)
const parentPath = pathArray.slice(0, pathArray.length - 1) const parentPath = pathArray.slice(0, pathArray.length - 1)
const dataPath = toDataPath(data, parentPath) const esonPath = toEsonPath(data, parentPath)
const parent = getIn(data, dataPath) const parent = getIn(data, esonPath)
const resolvedPath = resolvePathIndex(data, pathArray) const resolvedPath = resolvePathIndex(data, pathArray)
const prop = resolvedPath[resolvedPath.length - 1] const prop = resolvedPath[resolvedPath.length - 1]
let updatedData let updatedEson
if (parent.type === 'Array') { if (parent.type === 'Array') {
const newItem = { const newItem = {
id, // TODO: create a unique id within current id's instead of using a global, ever incrementing id id, // TODO: create a unique id within current id's instead of using a global, ever incrementing id
value value
} }
updatedData = insertAt(data, dataPath.concat('items', prop), newItem) updatedEson = insertAt(data, esonPath.concat('items', prop), newItem)
} }
else { // parent.type === 'Object' else { // parent.type === 'Object'
updatedData = updateIn(data, dataPath, (object) => { updatedEson = updateIn(data, esonPath, (object) => {
const existingIndex = findPropertyIndex(object, prop) const existingIndex = findPropertyIndex(object, prop)
if (existingIndex !== -1) { if (existingIndex !== -1) {
// replace existing item // replace existing item
@ -277,21 +274,21 @@ export function add (data: JSONData, path: string, value: JSONData, options, id
} }
if (parent.type === 'Object' && pathExists(data, resolvedPath)) { if (parent.type === 'Object' && pathExists(data, resolvedPath)) {
const oldValue = getIn(data, toDataPath(data, resolvedPath)) const oldValue = getIn(data, toEsonPath(data, resolvedPath))
return { return {
data: updatedData, data: updatedEson,
revert: [{ revert: [{
op: 'replace', op: 'replace',
path: compileJSONPointer(resolvedPath), path: compileJSONPointer(resolvedPath),
value: dataToJson(oldValue), value: esonToJson(oldValue),
jsoneditor: { type: oldValue.type } jsoneditor: { type: oldValue.type }
}] }]
} }
} }
else { else {
return { return {
data: updatedData, data: updatedEson,
revert: [{ revert: [{
op: 'remove', op: 'remove',
path: compileJSONPointer(resolvedPath) path: compileJSONPointer(resolvedPath)
@ -302,37 +299,37 @@ export function add (data: JSONData, path: string, value: JSONData, options, id
/** /**
* Copy a value * Copy a value
* @param {JSONData} data * @param {ESON} data
* @param {string} path * @param {string} path
* @param {string} from * @param {string} from
* @param {{before?: string}} [options] * @param {{before?: string}} [options]
* @return {{data: JSONData, revert: JSONPatch}} * @return {{data: ESON, revert: JSONPatch}}
* @private * @private
*/ */
export function copy (data: JSONData, path: string, from: string, options) { export function copy (data: ESON, path: string, from: string, options) {
const value = getIn(data, toDataPath(data, parseJSONPointer(from))) const value = getIn(data, toEsonPath(data, parseJSONPointer(from)))
return add(data, path, value, options) return add(data, path, value, options)
} }
/** /**
* Move a value * Move a value
* @param {JSONData} data * @param {ESON} data
* @param {string} path * @param {string} path
* @param {string} from * @param {string} from
* @param {{before?: string}} [options] * @param {{before?: string}} [options]
* @return {{data: JSONData, revert: JSONPatch}} * @return {{data: ESON, revert: JSONPatch}}
* @private * @private
*/ */
export function move (data: JSONData, path: string, from: string, options) { export function move (data: ESON, path: string, from: string, options) {
const fromArray = parseJSONPointer(from) const fromArray = parseJSONPointer(from)
const prop = getIn(data, allButLast(toDataPath(data, fromArray))) const prop = getIn(data, allButLast(toEsonPath(data, fromArray)))
const dataValue = prop.value const dataValue = prop.value
const id = prop.id // we want to use the existing id in case the move is a renaming a property const id = prop.id // we want to use the existing id in case the move is a renaming a property
// FIXME: only reuse the existing id when move is renaming a property in the same object // FIXME: only reuse the existing id when move is renaming a property in the same object
const parentPathFrom = allButLast(fromArray) const parentPathFrom = allButLast(fromArray)
const parent = getIn(data, toDataPath(data, parentPathFrom)) const parent = getIn(data, toEsonPath(data, parentPathFrom))
const result1 = remove(data, from) const result1 = remove(data, from)
const result2 = add(result1.data, path, dataValue, options, id) const result2 = add(result1.data, path, dataValue, options, id)
@ -367,12 +364,12 @@ export function move (data: JSONData, path: string, from: string, options) {
/** /**
* Test whether the data contains the provided value at the specified path. * Test whether the data contains the provided value at the specified path.
* Throws an error when the test fails. * Throws an error when the test fails.
* @param {JSONData} data * @param {ESON} data
* @param {string} path * @param {string} path
* @param {*} value * @param {*} value
* @return {null | Error} Returns an error when the tests, returns null otherwise * @return {null | Error} Returns an error when the tests, returns null otherwise
*/ */
export function test (data: JSONData, path: string, value: any) { export function test (data: ESON, path: string, value: any) {
if (value === undefined) { if (value === undefined) {
return new Error('Test failed, no value provided') return new Error('Test failed, no value provided')
} }
@ -382,8 +379,8 @@ export function test (data: JSONData, path: string, value: any) {
return new Error('Test failed, path not found') return new Error('Test failed, path not found')
} }
const actualValue = getIn(data, toDataPath(data, pathArray)) const actualValue = getIn(data, toEsonPath(data, pathArray))
if (!isEqual(dataToJson(actualValue), value)) { if (!isEqual(esonToJson(actualValue), value)) {
return new Error('Test failed, value differs') return new Error('Test failed, value differs')
} }
} }

View File

@ -25,59 +25,60 @@
/**************************** GENERIC JSON TYPES ******************************/ /**************************** GENERIC JSON TYPES ******************************/
export type JSONType = | string | number | boolean | null | JSONObjectType | JSONArrayType; export type JSONType = | string | number | boolean | null | JSONObjectType | JSONArrayType
export type JSONObjectType = { [key:string]: JSONType }; export type JSONObjectType = { [key:string]: JSONType }
export type JSONArrayType = Array<JSONType>; export type JSONArrayType = JSONType[]
/********************** TYPES FOR THE JSON DATA MODEL *************************/ /********************** TYPES FOR THE ESON OBJECT MODEL *************************/
export type SearchResultStatus = 'normal' | 'active' export type SearchResultStatus = 'normal' | 'active'
export type DataPointerType = 'value' | 'property' export type ESONPointerType = 'value' | 'property'
export type PropertyData = { export type ESONObjectProperty = {
id: number, id: number,
name: string, name: string,
value: JSONData, value: ESON,
searchResult?: SearchResultStatus searchResult?: SearchResultStatus
} }
export type ItemData = { export type ESONArrayItem = {
id: number, id: number,
value: JSONData value: ESON
} }
export type ObjectData = { export type ESONObject = {
type: 'Object', type: 'Object',
expanded?: boolean, expanded?: boolean,
props: PropertyData[] props: ESONObjectProperty[]
} }
export type ArrayData = { export type ESONArray = {
type: 'Array', type: 'Array',
expanded?: boolean, expanded?: boolean,
items: ItemData[] items: ESONArrayItem[]
} }
export type ValueData = { export type ESONValue = {
type: 'value' | 'string', type: 'value' | 'string',
value?: any, value?: any,
searchResult?: SearchResultStatus searchResult?: SearchResultStatus
} }
export type JSONData = ObjectData | ArrayData | ValueData export type ESON = ESONObject | ESONArray | ESONValue
export type JSONDataType = 'Object' | 'Array' | 'value' | 'string' export type ESONType = 'Object' | 'Array' | 'value' | 'string'
export type Path = string[] // TODO: Path must become redundant, replace with JSONPath or ESONPath everywhere
export type JSONPath = string[]
export type ESONPath = string[]
export type ESONPointer = {
export type Path = string[] path: ESONPath,
type: ESONPointerType
export type DataPointer = {
path: Path,
type: DataPointerType
} }
// TODO: DataPointer.dataPath is an array, JSONSchemaError.dataPath is a string -> make this consistent
// TODO: ESONPointer.path is an array, JSONSchemaError.path is a string -> make this consistent
// TODO: remove SetOptions, merge into Options (everywhere in the public API) // TODO: remove SetOptions, merge into Options (everywhere in the public API)
@ -85,27 +86,27 @@ export type SetOptions = {
expand?: (path: Path) => boolean expand?: (path: Path) => boolean
} }
export type JSONPatchAction = { export type ESONPatchAction = {
op: string, // TODO: define allowed ops op: string, // TODO: define allowed ops
path: string, path: string,
from?: string, from?: string,
value?: any, value?: any,
jsoneditor?: PatchOptions jsoneditor?: ESONPatchOptions
} }
export type JSONPatch = JSONPatchAction[] export type ESONPatch = ESONPatchAction[]
export type PatchOptions = { export type ESONPatchOptions = {
type: JSONDataType, type: ESONType,
expand: (Path) => boolean expand: (Path) => boolean
} }
export type JSONPatchResult = { export type ESONPatchResult = {
patch: JSONPatch, patch: ESONPatch,
revert: JSONPatch, revert: ESONPatch,
error: null | Error error: null | Error
} }
export type JSONSchemaError = { export type JSONSchemaError = {
dataPath: string, path: string, // TODO: change type to JSONPath
message: string message: string
} }

View File

@ -1,9 +1,9 @@
import test from 'ava'; import test from 'ava';
import { import {
jsonToData, dataToJson, pathExists, transform, traverse, jsonToEson, esonToJson, pathExists, transform, traverse,
parseJSONPointer, compileJSONPointer, parseJSONPointer, compileJSONPointer,
expand, addErrors, search, addSearchResults, nextSearchResult, previousSearchResult expand, addErrors, search, addSearchResults, nextSearchResult, previousSearchResult
} from '../src/jsonData' } from '../src/eson'
const JSON_EXAMPLE = { const JSON_EXAMPLE = {
@ -105,6 +105,31 @@ const JSON_DATA_EXAMPLE = {
] ]
} }
const JSON_DUPLICATE_PROPERTY_EXAMPLE = {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'name',
value: {
type: 'value',
expanded: true,
value: 'Joe'
}
},
{
id: '[ID]',
name: 'name',
value: {
type: 'value',
expanded: true,
value: 'Joe'
}
}
]
}
// TODO: instead of all slightly different copies of JSON_DATA_EXAMPLE, built them up via setIn, updateIn based on JSON_DATA_EXAMPLE // TODO: instead of all slightly different copies of JSON_DATA_EXAMPLE, built them up via setIn, updateIn based on JSON_DATA_EXAMPLE
const JSON_DATA_EXAMPLE_COLLAPSED_1 = { const JSON_DATA_EXAMPLE_COLLAPSED_1 = {
@ -426,8 +451,8 @@ const JSON_DATA_SMALL = {
const JSON_SCHEMA_ERRORS = [ const JSON_SCHEMA_ERRORS = [
{dataPath: '/obj/arr/2/last', message: 'String expected'}, {esonPath: '/obj/arr/2/last', message: 'String expected'},
{dataPath: '/nill', message: 'Null expected'} {esonPath: '/nill', message: 'Null expected'}
] ]
const JSON_DATA_EXAMPLE_ERRORS = { const JSON_DATA_EXAMPLE_ERRORS = {
@ -522,19 +547,19 @@ const JSON_DATA_EXAMPLE_ERRORS = {
] ]
} }
test('jsonToData', t => { test('jsonToEson', t => {
function expand (path) { function expand (path) {
return true return true
} }
const jsonData = jsonToData(JSON_EXAMPLE, expand, []) const ESON = jsonToEson(JSON_EXAMPLE, expand, [])
replaceIds(jsonData) replaceIds(ESON)
t.deepEqual(jsonData, JSON_DATA_EXAMPLE) t.deepEqual(ESON, JSON_DATA_EXAMPLE)
}) })
test('dataToJson', t => { test('esonToJson', t => {
t.deepEqual(dataToJson(JSON_DATA_EXAMPLE), JSON_EXAMPLE) t.deepEqual(esonToJson(JSON_DATA_EXAMPLE), JSON_EXAMPLE)
}) })
test('expand a single path', t => { test('expand a single path', t => {

View File

@ -1,6 +1,6 @@
import test from 'ava'; import test from 'ava';
import { jsonToData, dataToJson } from '../src/jsonData' import { jsonToEson, esonToJson } from '../src/eson'
import { patchData } from '../src/jsonPatchData' import { patchEson } from '../src/patchEson'
test('jsonpatch add', t => { test('jsonpatch add', t => {
const json = { const json = {
@ -12,11 +12,11 @@ test('jsonpatch add', t => {
{op: 'add', path: '/obj/b', value: {foo: 'bar'}} {op: 'add', path: '/obj/b', value: {foo: 'bar'}}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
arr: [1,2,3], arr: [1,2,3],
@ -37,11 +37,11 @@ test('jsonpatch add: append to matrix', t => {
{op: 'add', path: '/arr/-', value: 4} {op: 'add', path: '/arr/-', value: 4}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
arr: [1,2,3,4], arr: [1,2,3,4],
@ -64,11 +64,11 @@ test('jsonpatch remove', t => {
{op: 'remove', path: '/arr/1'}, {op: 'remove', path: '/arr/1'},
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
arr: [1,3], arr: [1,3],
@ -80,11 +80,11 @@ test('jsonpatch remove', t => {
]) ])
// test revert // test revert
const data2 = jsonToData(patchedJson) const data2 = jsonToEson(patchedJson)
const result2 = patchData(data2, revert) const result2 = patchEson(data2, revert)
const patchedData2 = result2.data const patchedData2 = result2.data
const revert2 = result2.revert const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2) const patchedJson2 = esonToJson(patchedData2)
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, patch) t.deepEqual(revert2, patch)
@ -101,11 +101,11 @@ test('jsonpatch replace', t => {
{op: 'replace', path: '/arr/1', value: 200}, {op: 'replace', path: '/arr/1', value: 200},
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
arr: [1,200,3], arr: [1,200,3],
@ -117,11 +117,11 @@ test('jsonpatch replace', t => {
]) ])
// test revert // test revert
const data2 = jsonToData(patchedJson) const data2 = jsonToEson(patchedJson)
const result2 = patchData(data2, revert) const result2 = patchEson(data2, revert)
const patchedData2 = result2.data const patchedData2 = result2.data
const revert2 = result2.revert const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2) const patchedJson2 = esonToJson(patchedData2)
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, [ t.deepEqual(revert2, [
@ -136,10 +136,10 @@ test('jsonpatch replace (keep ids intact)', t => {
{op: 'replace', path: '/value', value: 100} {op: 'replace', path: '/value', value: 100}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const valueId = data.props[0].id const valueId = data.props[0].id
const patchedData = patchData(data, patch).data const patchedData = patchEson(data, patch).data
const patchedValueId = patchedData.props[0].id const patchedValueId = patchedData.props[0].id
t.is(patchedValueId, valueId) t.is(patchedValueId, valueId)
@ -155,11 +155,11 @@ test('jsonpatch copy', t => {
{op: 'copy', from: '/obj', path: '/arr/2'}, {op: 'copy', from: '/obj', path: '/arr/2'},
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
arr: [1, 2, {a:4}, 3], arr: [1, 2, {a:4}, 3],
@ -170,11 +170,11 @@ test('jsonpatch copy', t => {
]) ])
// test revert // test revert
const data2 = jsonToData(patchedJson) const data2 = jsonToEson(patchedJson)
const result2 = patchData(data2, revert) const result2 = patchEson(data2, revert)
const patchedData2 = result2.data const patchedData2 = result2.data
const revert2 = result2.revert const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2) const patchedJson2 = esonToJson(patchedData2)
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, [ t.deepEqual(revert2, [
@ -188,11 +188,11 @@ test('jsonpatch copy (keeps the same ids)', t => {
{op: 'copy', from: '/foo', path: '/copied'} {op: 'copy', from: '/foo', path: '/copied'}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const fooId = data.props[0].id const fooId = data.props[0].id
const barId = data.props[0].value.props[0].id const barId = data.props[0].value.props[0].id
const patchedData = patchData(data, patch).data const patchedData = patchEson(data, patch).data
const patchedFooId = patchedData.props[0].id const patchedFooId = patchedData.props[0].id
const patchedBarId = patchedData.props[0].value.props[0].id const patchedBarId = patchedData.props[0].value.props[0].id
const copiedId = patchedData.props[1].id const copiedId = patchedData.props[1].id
@ -221,11 +221,11 @@ test('jsonpatch move', t => {
{op: 'move', from: '/obj', path: '/arr/2'}, {op: 'move', from: '/obj', path: '/arr/2'},
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.is(result.error, null) t.is(result.error, null)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
@ -236,11 +236,11 @@ test('jsonpatch move', t => {
]) ])
// test revert // test revert
const data2 = jsonToData(patchedJson) const data2 = jsonToEson(patchedJson)
const result2 = patchData(data2, revert) const result2 = patchEson(data2, revert)
const patchedData2 = result2.data const patchedData2 = result2.data
const revert2 = result2.revert const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2) const patchedJson2 = esonToJson(patchedData2)
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, patch) t.deepEqual(revert2, patch)
@ -257,11 +257,11 @@ test('jsonpatch move before', t => {
{op: 'move', from: '/obj', path: '/arr/2'}, {op: 'move', from: '/obj', path: '/arr/2'},
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.is(result.error, null) t.is(result.error, null)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
@ -273,11 +273,11 @@ test('jsonpatch move before', t => {
]) ])
// test revert // test revert
const data2 = jsonToData(patchedJson) const data2 = jsonToEson(patchedJson)
const result2 = patchData(data2, revert) const result2 = patchEson(data2, revert)
const patchedData2 = result2.data const patchedData2 = result2.data
const revert2 = result2.revert const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2) const patchedJson2 = esonToJson(patchedData2)
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, patch) t.deepEqual(revert2, patch)
@ -290,12 +290,12 @@ test('jsonpatch move and replace', t => {
{op: 'move', from: '/a', path: '/b'}, {op: 'move', from: '/a', path: '/b'},
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
// id of the replaced B must be kept intact // id of the replaced B must be kept intact
t.is(patchedData.props[0].id, data.props[1].id) t.is(patchedData.props[0].id, data.props[1].id)
@ -323,11 +323,11 @@ test('jsonpatch move and replace', t => {
]) ])
// test revert // test revert
const data2 = jsonToData(patchedJson) const data2 = jsonToEson(patchedJson)
const result2 = patchData(data2, revert) const result2 = patchEson(data2, revert)
const patchedData2 = result2.data const patchedData2 = result2.data
const revert2 = result2.revert const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2) const patchedJson2 = esonToJson(patchedData2)
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, [ t.deepEqual(revert2, [
@ -345,11 +345,11 @@ test('jsonpatch move and replace (nested)', t => {
{op: 'move', from: '/obj', path: '/arr'}, {op: 'move', from: '/obj', path: '/arr'},
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
arr: {a:4} arr: {a:4}
@ -360,11 +360,11 @@ test('jsonpatch move and replace (nested)', t => {
]) ])
// test revert // test revert
const data2 = jsonToData(patchedJson) const data2 = jsonToEson(patchedJson)
const result2 = patchData(data2, revert) const result2 = patchEson(data2, revert)
const patchedData2 = result2.data const patchedData2 = result2.data
const revert2 = result2.revert const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2) const patchedJson2 = esonToJson(patchedData2)
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, [ t.deepEqual(revert2, [
@ -378,10 +378,10 @@ test('jsonpatch move (keep id intact)', t => {
{op: 'move', from: '/value', path: '/moved'} {op: 'move', from: '/value', path: '/moved'}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const valueId = data.props[0].id const valueId = data.props[0].id
const patchedData = patchData(data, patch).data const patchedData = patchEson(data, patch).data
const patchedValueId = patchedData.props[0].id const patchedValueId = patchedData.props[0].id
t.is(patchedValueId, valueId) t.is(patchedValueId, valueId)
@ -393,13 +393,13 @@ test('jsonpatch move and replace (keep ids intact)', t => {
{op: 'move', from: '/a', path: '/b'} {op: 'move', from: '/a', path: '/b'}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const bId = data.props[1].id const bId = data.props[1].id
t.is(data.props[0].name, 'a') t.is(data.props[0].name, 'a')
t.is(data.props[1].name, 'b') t.is(data.props[1].name, 'b')
const patchedData = patchData(data, patch).data const patchedData = patchEson(data, patch).data
t.is(patchedData.props[0].name, 'b') t.is(patchedData.props[0].name, 'b')
t.is(patchedData.props[0].id, bId) t.is(patchedData.props[0].id, bId)
@ -416,11 +416,11 @@ test('jsonpatch test (ok)', t => {
{op: 'add', path: '/added', value: 'ok'} {op: 'add', path: '/added', value: 'ok'}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
arr: [1,2,3], arr: [1,2,3],
@ -444,11 +444,11 @@ test('jsonpatch test (fail: path not found)', t => {
{op: 'add', path: '/added', value: 'ok'} {op: 'add', path: '/added', value: 'ok'}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
// patch shouldn't be applied // patch shouldn't be applied
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
@ -470,11 +470,11 @@ test('jsonpatch test (fail: value not equal)', t => {
{op: 'add', path: '/added', value: 'ok'} {op: 'add', path: '/added', value: 'ok'}
] ]
const data = jsonToData(json) const data = jsonToEson(json)
const result = patchData(data, patch) const result = patchEson(data, patch)
const patchedData = result.data const patchedData = result.data
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = esonToJson(patchedData)
// patch shouldn't be applied // patch shouldn't be applied
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {

View File

@ -64,7 +64,7 @@ describe('util', function () {
}); });
describe('jsonPath', function () { describe('path', function () {
it ('should parse a json path', function () { it ('should parse a json path', function () {
assert.deepEqual(util.parsePath(''), []); assert.deepEqual(util.parsePath(''), []);