1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-02-24 09:13:24 +01:00

refactor for operations

This commit is contained in:
Ian Storm Taylor 2016-08-16 20:06:02 -07:00
parent 9ae245ddab
commit 6af9466c60
4 changed files with 194 additions and 26 deletions

View File

@ -42,6 +42,20 @@ class Character extends CharacterRecord {
return new List(array.map(Character.create))
}
/**
* Create a characters list from a `string` and optional `marks`.
*
* @param {String} string
* @param {Set} marks (optional)
* @return {List}
*/
static createListFromText(string, marks) {
const chars = string.split('').map(text => { return { text, marks } })
const list = Character.createList(chars)
return list
}
/**
* Get the kind.
*

View File

@ -60,6 +60,23 @@ const Node = {
return descendant
},
/**
* Assert that a node exists at `path` and return it.
*
* @param {Array} path
* @return {Node}
*/
assertPath(path) {
const descendant = this.getDescendantAtPath(path)
if (!descendant) {
throw new Error(`Could not find a descendant at path "${path}".`)
}
return descendant
},
/**
* Concat children `nodes` on to the end of the node.
*
@ -405,6 +422,24 @@ const Node = {
return child
},
/**
* Get a descendant by `path`.
*
* @param {Array} path
* @return {Node || Void}
*/
getDescedantAtPath(path) {
let descendant = this
for (const index of path) {
if (!descendant.nodes) return
descendant = descendant.nodes.get(index)
}
return descendant
},
/**
* Get the depth of a child node by `key`, with optional `startAt`.
*
@ -721,6 +756,27 @@ const Node = {
return node
},
/**
* Get the path of a descendant node by `key`.
*
* @param {String || Node} node
* @return {Array}
*/
getPath(key) {
let child = this.assertDescendant(key)
let path = []
let parent
while (parent = this.getParent(child)) {
const index = parent.nodes.indexOf(child)
path.push(index)
child = parent
}
return path
},
/**
* Get the node before a descendant node by `key`.
*
@ -911,6 +967,19 @@ const Node = {
return this.merge({ nodes })
},
/**
* Insert a `node` at `index`.
*
* @param {Number} index
* @param {Node} node
* @return {Node}
*/
insertNode(index, node) {
const nodes = this.nodes.splice(index, 0, node)
return this.merge({ nodes })
},
/**
* Check if the inline nodes are split at a `range`.
*
@ -1106,6 +1175,18 @@ const Node = {
return node
},
/**
* Remove a node at `index`.
*
* @param {Number} index
* @return {Node}
*/
removeNode(index) {
const nodes = this.nodes.splice(index, 1)
return this.merge({ nodes })
},
/**
* Set a new value for a child node by `key`.
*

View File

@ -98,6 +98,28 @@ class Text extends new Record(DEFAULTS) {
.join('')
}
/**
* Add a `mark` at `index` and `length`.
*
* @param {Number} index
* @param {Number} length
* @param {Mark} mark
* @return {Text}
*/
addMark(index, length, mark) {
const characters = this.characters.map((char, i) => {
if (i < index) return char
if (i > index + length) return char
let { marks } = char
marks = marks.add(mark)
char = char.merge({ marks })
return char
})
return this.merge({ characters })
}
/**
* Derive a set of decorated characters with `decorators`.
*
@ -129,6 +151,21 @@ class Text extends new Record(DEFAULTS) {
return schema.__getDecorators(this)
}
/**
* Get the marks on the text at `index`.
*
* @param {Number} index
* @return {Set}
*/
getMarksAtIndex(index) {
if (index == 0) return Mark.createSet()
const { characters } = this
const char = characters.get(index - 1)
if (!char) return Mark.createSet()
return char.marks
}
/**
* Derive the ranges for a list of `characters`.
*
@ -181,50 +218,86 @@ class Text extends new Record(DEFAULTS) {
}
/**
* Remove characters from the text node from `start` to `end`.
* Insert `text` at `index`.
*
* @param {Number} start
* @param {Number} end
* @param {Numbder} index
* @param {String} text
* @param {String} marks (optional)
* @return {Text} text
*/
removeCharacters(start, end) {
insertText(index, text, marks) {
marks = marks || this.getMarksAtIndex(index)
let { characters } = this
const chars = Character.createListFromText(text, marks)
characters = characters.filterNot((char, i) => {
return start <= i && i < end
characters = characters.slice(0, index)
.concat(chars)
.concat(characters.slice(index))
return this.merge({ characters })
}
/**
* Remove a `mark` at `index` and `length`.
*
* @param {Number} index
* @param {Number} length
* @param {Mark} mark
* @return {Text}
*/
removeMark(index, length, mark) {
const characters = this.characters.map((char, i) => {
if (i < index) return char
if (i > index + length) return char
let { marks } = char
marks = marks.remove(mark)
char = char.merge({ marks })
return char
})
return this.merge({ characters })
}
/**
* Insert text `string` at `index`.
* Remove text from the text node at `index` for `length`.
*
* @param {Numbder} index
* @param {String} string
* @param {String} marks (optional)
* @param {Number} index
* @param {Number} length
* @return {Text} text
*/
insertText(index, string, marks) {
removeText(index, length) {
let { characters } = this
if (!marks) {
const prev = index ? characters.get(index - 1) : null
marks = prev ? prev.marks : Mark.createSet()
let start = index
let end = index + length
characters = characters.filterNot((char, i) => start <= i && i < end)
return this.merge({ characters })
}
const chars = Character.createList(string.split('').map((char) => {
return {
text: char,
marks
}
}))
/**
* Update a `mark` at `index` and `length` with `properties`.
*
* @param {Number} index
* @param {Number} length
* @param {Mark} mark
* @param {Object} properties
* @return {Text}
*/
characters = characters.slice(0, index)
.concat(chars)
.concat(characters.slice(index))
updateMark(index, length, mark, properties) {
const characters = this.characters.map((char, i) => {
if (i < index) return char
if (i > index + length) return char
let { marks } = char
const j = marks.indexOf(mark)
let m = marks.get(j)
m = m.merge(properties)
marks = marks.set(j, m)
char = char.merge({ marks })
return char
})
return this.merge({ characters })
}

View File

@ -77,7 +77,7 @@ export function deleteAtRange(transform, range) {
// If the start and end nodes are the same, just remove characters.
if (startKey == endKey) {
let text = document.getDescendant(startKey)
text = text.removeCharacters(startOffset, endOffset)
text = text.removeText(startOffset, endOffset - startOffset)
document = document.updateDescendant(text)
document = document.normalize()
state = state.merge({ document })