1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-03-07 14:30:04 +01:00

Fix selection replacement and marks ()

* Fix selection replacement and marks

* Create `getInsertMarks` method for text insertion
This commit is contained in:
Blake Embrey 2018-01-25 13:08:17 -08:00 committed by Ian Storm Taylor
parent 7d5a33025b
commit 4e8dd7405a
4 changed files with 63 additions and 39 deletions
packages
slate-react/src/plugins
slate/src

@ -492,7 +492,7 @@ function AfterPlugin() {
if (startBlock.isVoid) return
const defaultBlock = startBlock
const defaultMarks = document.getMarksAtRange(selection.collapseToStart())
const defaultMarks = document.getInsertMarksAtRange(selection)
const frag = Plain.deserialize(text, { defaultBlock, defaultMarks }).document
change.insertFragment(frag)
}

@ -189,7 +189,7 @@ Changes.insertInline = (change, inline) => {
Changes.insertText = (change, text, marks) => {
const { value } = change
const { document, selection } = value
marks = marks || value.marks
marks = marks || selection.marks || document.getInsertMarksAtRange(selection)
change.insertTextAtRange(selection, text, marks)
// If the text was successfully inserted, and the selection had marks on it,

@ -881,8 +881,10 @@ Changes.insertTextAtRange = (change, range, text, marks, options = {}) => {
change.deleteAtRange(range, { normalize: false })
// Update range start after delete
key = change.value.startKey
offset = change.value.startOffset
if (change.value.startKey !== key) {
key = change.value.startKey
offset = change.value.startOffset
}
}
// PERF: Unless specified, don't normalize if only inserting text.

@ -1018,6 +1018,18 @@ class Node {
return new Set(array)
}
/**
* Get a set of the marks in a `range`.
*
* @param {Range} range
* @return {Set<Mark>}
*/
getInsertMarksAtRange(range) {
const array = this.getInsertMarksAtRangeAsArray(range)
return new Set(array)
}
/**
* Get a set of the marks in a `range`.
*
@ -1052,25 +1064,8 @@ class Node {
getMarksAtRangeAsArray(range) {
range = range.normalize(this)
if (range.isUnset) return []
if (range.isCollapsed) return this.getMarksAtCollaspsedRangeAsArray(range)
const { startKey, startOffset } = range
// If the range is collapsed at the start of the node, check the previous.
if (range.isCollapsed && startOffset == 0) {
const previous = this.getPreviousText(startKey)
if (!previous || previous.text.length == 0) return []
const char = previous.characters.get(previous.text.length - 1)
return char.marks.toArray()
}
// If the range is collapsed, check the character before the start.
if (range.isCollapsed) {
const text = this.getDescendant(startKey)
const char = text.characters.get(range.startOffset - 1)
return char.marks.toArray()
}
// Otherwise, get a set of the marks for each character in the range.
return this
.getCharactersAtRange(range)
.reduce((memo, char) => {
@ -1079,6 +1074,47 @@ class Node {
}, [])
}
/**
* Get a set of the marks in a `range` for insertion behavior.
*
* @param {Range} range
* @return {Array}
*/
getInsertMarksAtRangeAsArray(range) {
range = range.normalize(this)
if (range.isUnset) return []
if (range.isCollapsed) return this.getMarksAtCollaspsedRangeAsArray(range)
const text = this.getDescendant(range.startKey)
const char = text.characters.get(range.startOffset)
return char.marks.toArray()
}
/**
* Get a set of marks in a `range`, by treating it as collapsed.
*
* @param {Range} range
* @return {Array}
*/
getMarksAtCollaspsedRangeAsArray(range) {
if (range.isUnset) return []
const { startKey, startOffset } = range
if (startOffset == 0) {
const previous = this.getPreviousText(startKey)
if (!previous || previous.text.length == 0) return []
const char = previous.characters.get(previous.text.length - 1)
return char.marks.toArray()
}
const text = this.getDescendant(startKey)
const char = text.characters.get(startOffset - 1)
return char.marks.toArray()
}
/**
* Get a set of marks in a `range`, by intersecting.
*
@ -1089,23 +1125,7 @@ class Node {
getActiveMarksAtRangeAsArray(range) {
range = range.normalize(this)
if (range.isUnset) return []
const { startKey, startOffset } = range
// If the range is collapsed at the start of the node, check the previous.
if (range.isCollapsed && startOffset == 0) {
const previous = this.getPreviousText(startKey)
if (!previous || previous.text.length == 0) return []
const char = previous.characters.get(previous.text.length - 1)
return char.marks.toArray()
}
// If the range is collapsed, check the character before the start.
if (range.isCollapsed) {
const text = this.getDescendant(startKey)
const char = text.characters.get(range.startOffset - 1)
return char.marks.toArray()
}
if (range.isCollapsed) return this.getMarksAtCollaspsedRangeAsArray(range)
// Otherwise, get a set of the marks for each character in the range.
const chars = this.getCharactersAtRange(range)
@ -1981,8 +2001,10 @@ memoize(Node.prototype, [
'getInlinesByType',
'getInlinesByTypeAsArray',
'getMarksAtRange',
'getInsertMarksAtRange',
'getOrderedMarksAtRange',
'getMarksAtRangeAsArray',
'getInsertMarksAtRangeAsArray',
'getMarksByType',
'getOrderedMarksByType',
'getMarksByTypeAsArray',