Refactored `findSelectionIndices`

This commit is contained in:
jos 2018-09-05 12:14:52 +02:00
parent 9b2b8233af
commit 80f45f39ec
2 changed files with 30 additions and 38 deletions

View File

@ -1,7 +1,8 @@
import last from 'lodash/last'
import initial from 'lodash/initial'
import isEmpty from 'lodash/isEmpty'
import { findRootPath, findSelectionIndices, pathsFromSelection } from './eson'
import first from 'lodash/first'
import { findRootPath, pathsFromSelection } from './eson'
import { getIn } from './utils/immutabilityHelpers'
import { findUniqueName } from './utils/stringUtils'
import { isObject, stringConvert } from './utils/typeUtils'
@ -86,14 +87,16 @@ export function duplicate (json, selection) {
const rootPath = findRootPath(selection)
const root = getIn(json, rootPath)
const { maxIndex } = findSelectionIndices(root, rootPath, selection)
const paths = pathsFromSelection(json, selection)
if (Array.isArray(root)) {
return paths.map((path, offset) => ({
const lastPath = last(paths)
const offset = lastPath ? (parseInt(last(lastPath), 10) + 1) : 0
return paths.map((path, index) => ({
op: 'copy',
from: compileJSONPointer(path),
path: compileJSONPointer(rootPath.concat(maxIndex + offset))
path: compileJSONPointer(rootPath.concat(index + offset))
}))
}
else { // 'object'
@ -221,13 +224,16 @@ export function insertInside (json, parentPath, values) {
export function replace (json, selection, values) { // TODO: find a better name and define datastructure for values
const rootPath = findRootPath(selection)
const root = getIn(json, rootPath)
const { minIndex, maxIndex } = findSelectionIndices(root, rootPath, selection)
if (Array.isArray(root)) {
const removeActions = removeAll(pathsFromSelection(json, selection))
const insertActions = values.map((entry, offset) => ({
const paths = pathsFromSelection(json, selection)
const firstPath = first(paths)
const offset = firstPath ? parseInt(last(firstPath), 10) : 0
const removeActions = removeAll(paths)
const insertActions = values.map((entry, index) => ({
op: 'add',
path: compileJSONPointer(rootPath.concat(minIndex + offset)),
path: compileJSONPointer(rootPath.concat(index + offset)),
value: entry.value
}))

View File

@ -413,33 +413,6 @@ export function applySelection (eson, selection) {
}
}
/**
* Find the min and max index of a start and end child.
* Start and end can be a property name in case of an Object,
* or a matrix index (string with a number) in case of an Array.
*
* @param {ESON} root
* @param {Path} rootPath
* @param {Selection} selection
* @return {{minIndex: number, maxIndex: number}}
*/
export function findSelectionIndices (root, rootPath, selection) {
const start = (selection.after || selection.inside || selection.start)[rootPath.length]
const end = (selection.after || selection.inside || selection.end)[rootPath.length]
// if no object we assume it's an Array
// TODO: create a util function getSortedProps, cache results?
const rootIsObject = getType(root) === 'object'
const props = rootIsObject ? Object.keys(root).sort(naturalSort) : undefined
const startIndex = rootIsObject ? props.indexOf(start) : parseInt(start, 10)
const endIndex = rootIsObject ? props.indexOf(end) : parseInt(end, 10)
const minIndex = Math.min(startIndex, endIndex)
const maxIndex = Math.max(startIndex, endIndex) + ((selection.after || selection.inside) ? 0 : 1) // include max index itself
return { minIndex, maxIndex }
}
/**
* Get the contents of a list with paths
* @param {ESON} eson
@ -518,14 +491,27 @@ export function pathsFromSelection (eson, selection) {
const rootPath = findRootPath(selection)
const root = getIn(eson, rootPath)
const { minIndex, maxIndex } = findSelectionIndices(root, rootPath, selection)
const start = (selection.after || selection.inside || selection.start)[rootPath.length]
const end = (selection.after || selection.inside || selection.end)[rootPath.length]
if (getType(root) === 'object') {
const props = Object.keys(root).sort(naturalSort) // TODO: create a util function getSortedProps
// TODO: create a util function getSortedProps, cache results?
const props = Object.keys(root).sort(naturalSort)
const startIndex = props.indexOf(start)
const endIndex = props.indexOf(end)
const minIndex = Math.min(startIndex, endIndex)
const maxIndex = Math.max(startIndex, endIndex) + ((selection.after || selection.inside) ? 0 : 1) // include max index itself
return times(maxIndex - minIndex, i => rootPath.concat(props[i + minIndex]))
}
else { // root[TYPE] === 'array'
const startIndex = parseInt(start, 10)
const endIndex = parseInt(end, 10)
const minIndex = Math.min(startIndex, endIndex)
const maxIndex = Math.max(startIndex, endIndex) + ((selection.after || selection.inside) ? 0 : 1) // include max index itself
return times(maxIndex - minIndex, i => rootPath.concat(String(i + minIndex)))
}
}
@ -541,7 +527,7 @@ export function pathsFromSelection (eson, selection) {
export function immutableESONPatch (eson, operations) {
return immutableJSONPatch(eson, operations, {
fromJSON: (value, previousEson) => syncEson(value, previousEson),
toJSON: (eson) => eson[VALUE],
toJSON: (eson) => eson.valueOf(),
clone: (value) => setIn(value, [ID], createId())
})
}