1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-22 06:53:25 +02:00

Fix selection replacement and marks (#1473)

* 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

View File

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

View File

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

View File

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

View File

@@ -1018,6 +1018,18 @@ class Node {
return new Set(array) 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`. * Get a set of the marks in a `range`.
* *
@@ -1052,25 +1064,8 @@ class Node {
getMarksAtRangeAsArray(range) { getMarksAtRangeAsArray(range) {
range = range.normalize(this) range = range.normalize(this)
if (range.isUnset) return [] 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 return this
.getCharactersAtRange(range) .getCharactersAtRange(range)
.reduce((memo, char) => { .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. * Get a set of marks in a `range`, by intersecting.
* *
@@ -1089,23 +1125,7 @@ class Node {
getActiveMarksAtRangeAsArray(range) { getActiveMarksAtRangeAsArray(range) {
range = range.normalize(this) range = range.normalize(this)
if (range.isUnset) return [] 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. // Otherwise, get a set of the marks for each character in the range.
const chars = this.getCharactersAtRange(range) const chars = this.getCharactersAtRange(range)
@@ -1981,8 +2001,10 @@ memoize(Node.prototype, [
'getInlinesByType', 'getInlinesByType',
'getInlinesByTypeAsArray', 'getInlinesByTypeAsArray',
'getMarksAtRange', 'getMarksAtRange',
'getInsertMarksAtRange',
'getOrderedMarksAtRange', 'getOrderedMarksAtRange',
'getMarksAtRangeAsArray', 'getMarksAtRangeAsArray',
'getInsertMarksAtRangeAsArray',
'getMarksByType', 'getMarksByType',
'getOrderedMarksByType', 'getOrderedMarksByType',
'getMarksByTypeAsArray', 'getMarksByTypeAsArray',