Fix a bug in `append` and a bit of refactoring

This commit is contained in:
Jos de Jong 2020-07-22 11:09:33 +02:00
parent ce8cf93170
commit 401a6e19fd
4 changed files with 41 additions and 34 deletions

View File

@ -17,7 +17,7 @@
import Icon from 'svelte-awesome' import Icon from 'svelte-awesome'
import { faCut, faCopy, faPaste, faSearch, faUndo, faRedo } from '@fortawesome/free-solid-svg-icons' import { faCut, faCopy, faPaste, faSearch, faUndo, faRedo } from '@fortawesome/free-solid-svg-icons'
import { createHistory } from './history.js' import { createHistory } from './history.js'
import Node from './JSONNode.svelte' import JSONNode from './JSONNode.svelte'
import { expandSelection } from './selection.js' import { expandSelection } from './selection.js'
import { isContentEditableDiv } from './utils/domUtils.js' import { isContentEditableDiv } from './utils/domUtils.js'
import { import {
@ -342,24 +342,17 @@
} }
/** /**
* @param {Selection} newSelection * @param {SelectionSchema} selectionSchema
*/ */
function handleSelect (newSelection) { function handleSelect (selectionSchema) {
// TODO: refactor handleSelect: should be redundant except for the functionality to expand the selection and generate pathsMap if (selectionSchema) {
const { anchorPath, focusPath, beforePath, appendPath } = selectionSchema
if (newSelection) {
const { paths, anchorPath, focusPath, beforePath, appendPath } = newSelection
if (beforePath) { if (beforePath) {
selection = { selection = { beforePath }
beforePath
}
} else if (appendPath) { } else if (appendPath) {
selection = { selection = { appendPath }
appendPath
}
} else if (anchorPath && focusPath) { } else if (anchorPath && focusPath) {
// TODO: move expandSelection to JSONNode? (must change expandSelection to support relative path)
const paths = expandSelection(doc, state, anchorPath, focusPath) const paths = expandSelection(doc, state, anchorPath, focusPath)
selection = { selection = {
@ -367,7 +360,7 @@
pathsMap: createPathsMap(paths) pathsMap: createPathsMap(paths)
} }
} else { } else {
console.error('Unknown type of selection', newSelection) console.error('Unknown type of selection', selectionSchema)
} }
// set focus to the hidden input, so we can capture quick keys like Ctrl+X, Ctrl+C, Ctrl+V // set focus to the hidden input, so we can capture quick keys like Ctrl+X, Ctrl+C, Ctrl+V
@ -552,7 +545,7 @@
/> />
</label> </label>
<div class="contents" bind:this={divContents}> <div class="contents" bind:this={divContents}>
<Node <JSONNode
value={doc} value={doc}
path={[]} path={[]}
state={state} state={state}

View File

@ -23,10 +23,10 @@ export function insertBefore (json, path, values, nextKeys) { // TODO: find a b
const parent = getIn(json, parentPath) const parent = getIn(json, parentPath)
if (Array.isArray(parent)) { if (Array.isArray(parent)) {
const startIndex = parseInt(last(path), 10) const offset = parseInt(last(path), 10)
return values.map((entry, offset) => ({ return values.map((entry, index) => ({
op: 'add', op: 'add',
path: compileJSONPointer(parentPath.concat(startIndex + offset)), path: compileJSONPointer(parentPath.concat(offset + index)),
value: entry.value value: entry.value
})) }))
} }
@ -65,10 +65,10 @@ export function append (json, path, values) { // TODO: find a better name and d
const parent = getIn(json, path) const parent = getIn(json, path)
if (Array.isArray(parent)) { if (Array.isArray(parent)) {
const index = parent.length const offset = parent.length
return values.map((entry, offset) => ({ return values.map((entry, index) => ({
op: 'add', op: 'add',
path: compileJSONPointer(path.concat(index)), path: compileJSONPointer(path.concat(offset + index)),
value: entry.value value: entry.value
})) }))
} }

View File

@ -1,4 +1,4 @@
import { isEqual } from 'lodash-es' import { first, initial, isEmpty, isEqual, last } from 'lodash-es'
import { STATE_PROPS } from './constants.js' import { STATE_PROPS } from './constants.js'
import { getIn } from './utils/immutabilityHelpers.js' import { getIn } from './utils/immutabilityHelpers.js'
import { isObject } from './utils/typeUtils.js' import { isObject } from './utils/typeUtils.js'
@ -11,7 +11,7 @@ import { isObject } from './utils/typeUtils.js'
* @param {JSON} state * @param {JSON} state
* @param {Path} anchorPath * @param {Path} anchorPath
* @param {Path} focusPath * @param {Path} focusPath
* @return {Path[]} selection * @return {Path[]} paths
*/ */
export function expandSelection (doc, state, anchorPath, focusPath) { export function expandSelection (doc, state, anchorPath, focusPath) {
if (isEqual(anchorPath, focusPath)) { if (isEqual(anchorPath, focusPath)) {
@ -26,14 +26,14 @@ export function expandSelection (doc, state, anchorPath, focusPath) {
return [ sharedPath ] return [ sharedPath ]
} }
const anchorProp = anchorPath[sharedPath.length] const anchorKey = anchorPath[sharedPath.length]
const focusProp = focusPath[sharedPath.length] const focusKey = focusPath[sharedPath.length]
const value = getIn(doc, sharedPath) const value = getIn(doc, sharedPath)
if (isObject(value)) { if (isObject(value)) {
const props = getIn(state, sharedPath.concat(STATE_PROPS)) const props = getIn(state, sharedPath.concat(STATE_PROPS))
const anchorIndex = props.findIndex(prop => prop.key === anchorProp) const anchorIndex = props.findIndex(prop => prop.key === anchorKey)
const focusIndex = props.findIndex(prop => prop.key === focusProp) const focusIndex = props.findIndex(prop => prop.key === focusKey)
if (anchorIndex !== -1 && focusIndex !== -1) { if (anchorIndex !== -1 && focusIndex !== -1) {
const startIndex = Math.min(anchorIndex, focusIndex) const startIndex = Math.min(anchorIndex, focusIndex)
@ -49,8 +49,8 @@ export function expandSelection (doc, state, anchorPath, focusPath) {
} }
if (Array.isArray(value)) { if (Array.isArray(value)) {
const startIndex = Math.min(anchorProp, focusProp) const startIndex = Math.min(anchorKey, focusKey)
const endIndex = Math.max(anchorProp, focusProp) const endIndex = Math.max(anchorKey, focusKey)
const paths = [] const paths = []
for (let i = startIndex; i <= endIndex; i++) { for (let i = startIndex; i <= endIndex; i++) {
@ -61,8 +61,7 @@ export function expandSelection (doc, state, anchorPath, focusPath) {
} }
} }
// should never happen throw new Error('Failed to create selection')
return []
} }
/** /**

View File

@ -25,7 +25,7 @@
*/ */
/** /**
* @typedef {<string | number>[]} Path * @typedef {Array<string | number>} Path
*/ */
/** /**
@ -50,5 +50,20 @@
*/ */
/** /**
* @typedef {{paths: Path[], pathsMap: Object<string, boolean>}} | {beforePath: Path} | {appendPath: Path}} Selection * @typedef {{
* paths: Path[],
* pathsMap: Object<string, boolean>
* }} MultiSelection
*
* @typedef {{beforePath: Path}} BeforeSelection
*
* @typedef {{appendPath: Path}} AppendSelection
* @typedef {MultiSelection | BeforeSelection | AppendSelection} Selection
*/
/**
* @typedef {{anchorPath: Path, focusPath: Path}} MultiSelectionSchema
*
* @typedef {MultiSelectionSchema | BeforeSelection | AppendSelection} SelectionSchema
*/ */