1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-29 18:09:49 +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) {
const characters = this.characters.map((char, i) => {
if (i < index) return char
if (i > index + length) return char
if (i >= index + length) return char
let { marks } = char
marks = marks.add(mark)
char = char.merge({ marks })

View File

@@ -13,44 +13,30 @@ import { Set } from 'immutable'
*
* @param {Transform} transform
* @param {Selection} range
* @param {Mark || String || Object} mark
* @param {Mixed} mark
* @return {Transform}
*/
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
// Otherwise, find each of the text nodes within the range.
const { state } = transform
const { document } = state
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) => {
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
}
@@ -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 {Selection} range
* @param {String} string
* @param {String} text
* @param {Set} marks (optional)
* @return {Transform}
*/
export function insertTextAtRange(transform, range, string, marks) {
let { state } = transform
let { document } = state
export function insertTextAtRange(transform, range, text, marks) {
const { state } = transform
const { document } = state
const { startKey, startOffset } = range
const isVoid = document.hasVoidParent(startKey)
// If inside a void node, do nothing.
if (isVoid) 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()
if (isVoid) {
return transform
}
// Insert text at the range's offset.
let text = document.getDescendant(startKey)
text = text.insertText(startOffset, string, marks)
document = document.updateDescendant(text)
if (range.isExpanded) {
transform.deleteAtRange(range)
}
// Return the updated selection.
state = state.merge({ document })
transform.state = state
transform.insertTextByKey(startKey, startOffset, text, marks)
return transform
}
@@ -608,11 +584,11 @@ export function removeMarkAtRange(transform, range, mark) {
*
* @param {Transform} transform
* @param {Selection} range
* @param {Object or String} properties
* @param {Object || String} properties
* @return {Transform}
*/
export function setBlockAtRange(transform, range, properties = {}) {
export function setBlockAtRange(transform, range, properties) {
const { state } = transform
const { document } = state
const blocks = document.getBlocksAtRange(range)
@@ -629,24 +605,19 @@ export function setBlockAtRange(transform, range, properties = {}) {
*
* @param {Transform} transform
* @param {Selection} range
* @param {Object or String} properties
* @param {Object || String} properties
* @return {Transform}
*/
export function setInlineAtRange(transform, range, properties = {}) {
let { state } = transform
properties = Normalize.nodeProperties(properties)
let { document } = state
export function setInlineAtRange(transform, range, properties) {
const { state } = transform
const { document } = state
const inlines = document.getInlinesAtRange(range)
inlines.forEach((inline) => {
inline = inline.merge(properties)
document = document.updateDescendant(inline)
transform.setNodeByKey(inline.key, properties)
})
document = document.normalize()
state = state.merge({ document })
transform.state = state
return transform
}

View File

@@ -1,6 +1,73 @@
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`.
*
@@ -34,234 +101,6 @@ export function insertTextByKey(transform, key, index, text, marks) {
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`.
*
@@ -303,3 +142,165 @@ export function moveNodeByKey(transform, key, newKey, newIndex) {
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 {
insertTextByKey,
removeTextByKey,
addMarkByKey,
removeMarkByKey,
setMarkByKey,
insertNodeAfterNodeByKey,
removeNodeByKey,
setNodeByKey,
moveNodeByKey,
} from './by-key'
/**
@@ -152,8 +159,15 @@ export default {
* By key.
*/
insertTextByKey,
removeTextByKey,
addMarkByKey,
removeMarkByKey,
setMarkByKey,
insertNodeAfterNodeByKey,
removeNodeByKey,
setNodeByKey,
moveNodeByKey,
/**
* On selection.