1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-30 10:29:48 +02:00

refactor more transforms

This commit is contained in:
Ian Storm Taylor
2016-08-16 23:26:25 -07:00
parent 650f467126
commit 54a46484e3
4 changed files with 275 additions and 289 deletions

View File

@@ -110,7 +110,7 @@ class Text extends new Record(DEFAULTS) {
addMark(index, length, mark) { addMark(index, length, mark) {
const characters = this.characters.map((char, i) => { const characters = this.characters.map((char, i) => {
if (i < index) return char if (i < index) return char
if (i > index + length) return char if (i >= index + length) return char
let { marks } = char let { marks } = char
marks = marks.add(mark) marks = marks.add(mark)
char = char.merge({ marks }) char = char.merge({ marks })

View File

@@ -13,44 +13,30 @@ import { Set } from 'immutable'
* *
* @param {Transform} transform * @param {Transform} transform
* @param {Selection} range * @param {Selection} range
* @param {Mark || String || Object} mark * @param {Mixed} mark
* @return {Transform} * @return {Transform}
*/ */
export function addMarkAtRange(transform, range, mark) { export function addMarkAtRange(transform, range, mark) {
let { state } = transform
let { document } = state
// Normalize the mark.
mark = Normalize.mark(mark)
// When the range is collapsed, do nothing.
if (range.isCollapsed) return transform if (range.isCollapsed) return transform
// Otherwise, find each of the text nodes within the range. const { state } = transform
const { document } = state
const { startKey, startOffset, endKey, endOffset } = range const { startKey, startOffset, endKey, endOffset } = range
let texts = document.getTextsAtRange(range) const texts = document.getTextsAtRange(range)
// Apply the mark to each of the text nodes's matching characters.
texts = texts.map((text) => {
let characters = text.characters.map((char, i) => {
if (!isInRange(i, text, range)) return char
let { marks } = char
marks = marks.add(mark)
return char.merge({ marks })
})
return text.merge({ characters })
})
// Update each of the text nodes.
texts.forEach((text) => { texts.forEach((text) => {
document = document.updateDescendant(text) const { key } = text
let index = 0
let length = text.length
if (key == startKey) index = startOffset
if (key == endKey) length = endOffset
if (key == startKey && key == endKey) length = endOffset - startOffset
transform.addMarkByKey(key, index, length, mark)
}) })
// Update the state.
state = state.merge({ document })
transform.state = state
return transform return transform
} }
@@ -522,40 +508,30 @@ export function insertInlineAtRange(transform, range, inline) {
} }
/** /**
* Insert text `string` at a `range`, with optional `marks`. * Insert `text` at a `range`, with optional `marks`.
* *
* @param {Transform} transform * @param {Transform} transform
* @param {Selection} range * @param {Selection} range
* @param {String} string * @param {String} text
* @param {Set} marks (optional) * @param {Set} marks (optional)
* @return {Transform} * @return {Transform}
*/ */
export function insertTextAtRange(transform, range, string, marks) { export function insertTextAtRange(transform, range, text, marks) {
let { state } = transform const { state } = transform
let { document } = state const { document } = state
const { startKey, startOffset } = range const { startKey, startOffset } = range
const isVoid = document.hasVoidParent(startKey) const isVoid = document.hasVoidParent(startKey)
// If inside a void node, do nothing. if (isVoid) {
if (isVoid) return transform return transform
// Is the range is expanded, delete it first.
if (range.isExpanded) {
transform = deleteAtRange(transform, range)
state = transform.state
document = state.document
range = range.collapseToStart()
} }
// Insert text at the range's offset. if (range.isExpanded) {
let text = document.getDescendant(startKey) transform.deleteAtRange(range)
text = text.insertText(startOffset, string, marks) }
document = document.updateDescendant(text)
// Return the updated selection. transform.insertTextByKey(startKey, startOffset, text, marks)
state = state.merge({ document })
transform.state = state
return transform return transform
} }
@@ -608,11 +584,11 @@ export function removeMarkAtRange(transform, range, mark) {
* *
* @param {Transform} transform * @param {Transform} transform
* @param {Selection} range * @param {Selection} range
* @param {Object or String} properties * @param {Object || String} properties
* @return {Transform} * @return {Transform}
*/ */
export function setBlockAtRange(transform, range, properties = {}) { export function setBlockAtRange(transform, range, properties) {
const { state } = transform const { state } = transform
const { document } = state const { document } = state
const blocks = document.getBlocksAtRange(range) const blocks = document.getBlocksAtRange(range)
@@ -629,24 +605,19 @@ export function setBlockAtRange(transform, range, properties = {}) {
* *
* @param {Transform} transform * @param {Transform} transform
* @param {Selection} range * @param {Selection} range
* @param {Object or String} properties * @param {Object || String} properties
* @return {Transform} * @return {Transform}
*/ */
export function setInlineAtRange(transform, range, properties = {}) { export function setInlineAtRange(transform, range, properties) {
let { state } = transform const { state } = transform
properties = Normalize.nodeProperties(properties) const { document } = state
let { document } = state
const inlines = document.getInlinesAtRange(range) const inlines = document.getInlinesAtRange(range)
inlines.forEach((inline) => { inlines.forEach((inline) => {
inline = inline.merge(properties) transform.setNodeByKey(inline.key, properties)
document = document.updateDescendant(inline)
}) })
document = document.normalize()
state = state.merge({ document })
transform.state = state
return transform return transform
} }

View File

@@ -1,6 +1,73 @@
import Normalize from '../utils/normalize' import Normalize from '../utils/normalize'
/**
* Add mark to text at `index` and `length` in node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Number} length
* @param {Mixed} mark
* @return {Transform}
*/
export function addMarkByKey(transform, key, index, length, mark) {
mark = Normalize.mark(mark)
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.addMark(index, length, mark)
document = document.updateDescendant(node)
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'add-mark',
index,
length,
mark,
path,
})
return transform
}
/**
* Insert a `node` at `index` in a node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Node} node
* @return {Transform}
*/
export function insertNodeByKey(transform, key, index, node) {
let { state } = transform
let { document } = state
let parent = document.assertDescendant(key)
const path = document.getPath(parent)
const nodes = parent.nodes.splice(index + 1, 0, node)
parent = parent.merge({ nodes })
document = document.updateDescendant(parent)
document = document.normalize()
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'insert-node',
index,
node,
path,
})
return transform
}
/** /**
* Insert `text` at `index` in node by `key`. * Insert `text` at `index` in node by `key`.
* *
@@ -34,234 +101,6 @@ export function insertTextByKey(transform, key, index, text, marks) {
return transform return transform
} }
/**
* Remove text at `index` and `length` in node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Number} length
* @return {Transform}
*/
export function removeTextByKey(transform, key, index, length) {
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.removeText(index, length)
document = document.updateDescendant(node)
document = document.normalize()
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'remove-text',
index,
length,
path,
})
return transform
}
/**
* Add mark to text at `index` and `length` in node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Number} length
* @param {Mark} mark
* @return {Transform}
*/
export function addMarkByKey(transform, key, index, length, mark) {
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.addMark(index, length, mark)
document = document.updateDescendant(node)
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'add-mark',
index,
length,
mark,
path,
})
return transform
}
/**
* Remove mark from text at `index` and `length` in node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Number} length
* @param {Mark} mark
* @return {Transform}
*/
export function removeMarkByKey(transform, key, index, length, mark) {
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.removeMark(index, length, mark)
document = document.updateDescendant(node)
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'remove-mark',
index,
length,
mark,
path,
})
return transform
}
/**
* Set `properties` on mark on text at `index` and `length` in node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Number} length
* @param {Mark} mark
* @return {Transform}
*/
export function setMarkByKey(transform, key, index, length, mark, properties) {
properties = Normalize.markProperties(properties)
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.updateMark(index, length, mark, properties)
document = document.updateDescendant(node)
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'set-mark',
index,
length,
mark,
path,
properties,
})
return transform
}
/**
* Insert a `node` at `index` in a node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Node} node
* @return {Transform}
*/
export function insertNodeAfterNodeByKey(transform, key, index, node) {
let { state } = transform
let { document } = state
let parent = document.assertDescendant(key)
const path = document.getPath(parent)
const nodes = parent.nodes.splice(index + 1, 0, node)
parent = parent.merge({ nodes })
document = document.updateDescendant(parent)
document = document.normalize()
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'insert-node',
index,
node,
path,
})
return transform
}
/**
* Remove a node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @return {Transform}
*/
export function removeNodeByKey(transform, key) {
let { state } = transform
let { document } = state
const node = document.assertDescendant(key)
const path = document.getPath(node)
let parent = document.getParent(node)
const index = parent.nodes.indexOf(node)
const isParent = document == parent
parent = parent.removeNode(index)
document = isParent ? parent : document.updateDescendant(parent)
document = document.normalize()
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'remove-node',
path,
})
return transform
}
/**
* Set `properties` on a node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Object || String} properties
* @return {Transform}
*/
export function setNodeByKey(transform, key, properties) {
properties = Normalize.nodeProperties(properties)
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.merge(properties)
document = document.updateDescendant(node)
document = document.normalize()
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'set-node',
path,
properties,
})
return transform
}
/** /**
* Move a node by `key` to a new parent by `key` and `index`. * Move a node by `key` to a new parent by `key` and `index`.
* *
@@ -303,3 +142,165 @@ export function moveNodeByKey(transform, key, newKey, newIndex) {
return transform return transform
} }
/**
* Remove mark from text at `index` and `length` in node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Number} length
* @param {Mark} mark
* @return {Transform}
*/
export function removeMarkByKey(transform, key, index, length, mark) {
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.removeMark(index, length, mark)
document = document.updateDescendant(node)
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'remove-mark',
index,
length,
mark,
path,
})
return transform
}
/**
* Remove a node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @return {Transform}
*/
export function removeNodeByKey(transform, key) {
let { state } = transform
let { document } = state
const node = document.assertDescendant(key)
const path = document.getPath(node)
let parent = document.getParent(node)
const index = parent.nodes.indexOf(node)
const isParent = document == parent
parent = parent.removeNode(index)
document = isParent ? parent : document.updateDescendant(parent)
document = document.normalize()
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'remove-node',
path,
})
return transform
}
/**
* Remove text at `index` and `length` in node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Number} length
* @return {Transform}
*/
export function removeTextByKey(transform, key, index, length) {
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.removeText(index, length)
document = document.updateDescendant(node)
document = document.normalize()
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'remove-text',
index,
length,
path,
})
return transform
}
/**
* Set `properties` on mark on text at `index` and `length` in node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Number} index
* @param {Number} length
* @param {Mark} mark
* @return {Transform}
*/
export function setMarkByKey(transform, key, index, length, mark, properties) {
properties = Normalize.markProperties(properties)
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.updateMark(index, length, mark, properties)
document = document.updateDescendant(node)
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'set-mark',
index,
length,
mark,
path,
properties,
})
return transform
}
/**
* Set `properties` on a node by `key`.
*
* @param {Transform} transform
* @param {String} key
* @param {Object || String} properties
* @return {Transform}
*/
export function setNodeByKey(transform, key, properties) {
properties = Normalize.nodeProperties(properties)
let { state } = transform
let { document } = state
let node = document.assertDescendant(key)
const path = document.getPath(node)
node = node.merge(properties)
document = document.updateDescendant(node)
document = document.normalize()
state = state.merge({ document })
transform.state = state
transform.operations.push({
type: 'set-node',
path,
properties,
})
return transform
}

View File

@@ -56,8 +56,15 @@ import {
*/ */
import { import {
insertTextByKey,
removeTextByKey,
addMarkByKey,
removeMarkByKey,
setMarkByKey,
insertNodeAfterNodeByKey,
removeNodeByKey, removeNodeByKey,
setNodeByKey, setNodeByKey,
moveNodeByKey,
} from './by-key' } from './by-key'
/** /**
@@ -152,8 +159,15 @@ export default {
* By key. * By key.
*/ */
insertTextByKey,
removeTextByKey,
addMarkByKey,
removeMarkByKey,
setMarkByKey,
insertNodeAfterNodeByKey,
removeNodeByKey, removeNodeByKey,
setNodeByKey, setNodeByKey,
moveNodeByKey,
/** /**
* On selection. * On selection.