mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-11 01:33:58 +02:00
fix delete forward/backward to be unicode aware, closes #87
This commit is contained in:
@@ -2,9 +2,9 @@
|
|||||||
import Key from '../utils/key'
|
import Key from '../utils/key'
|
||||||
import Placeholder from '../components/placeholder'
|
import Placeholder from '../components/placeholder'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import String from '../utils/string'
|
||||||
import keycode from 'keycode'
|
import keycode from 'keycode'
|
||||||
import { IS_WINDOWS, IS_MAC } from '../utils/environment'
|
import { IS_WINDOWS, IS_MAC } from '../utils/environment'
|
||||||
import { getWordOffsetBackward, getWordOffsetForward } from '../utils/string'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default plugin.
|
* The default plugin.
|
||||||
@@ -156,14 +156,16 @@ function Plugin(options = {}) {
|
|||||||
|
|
||||||
case 'backspace': {
|
case 'backspace': {
|
||||||
if (state.isExpanded) return transform.delete().apply()
|
if (state.isExpanded) return transform.delete().apply()
|
||||||
|
const { startOffset, startBlock } = state
|
||||||
|
const text = startBlock.text
|
||||||
let n
|
let n
|
||||||
|
|
||||||
if (Key.isWord(e)) {
|
if (Key.isWord(e)) {
|
||||||
n = getWordOffsetBackward(state.startBlock.text, state.startOffset)
|
n = String.getWordOffsetBackward(text, startOffset)
|
||||||
} else if (Key.isLine(e)) {
|
} else if (Key.isLine(e)) {
|
||||||
n = state.startOffset
|
n = startOffset
|
||||||
} else {
|
} else {
|
||||||
n = 1
|
n = String.getCharOffsetBackward(text, startOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform.deleteBackward(n).apply()
|
return transform.deleteBackward(n).apply()
|
||||||
@@ -171,14 +173,16 @@ function Plugin(options = {}) {
|
|||||||
|
|
||||||
case 'delete': {
|
case 'delete': {
|
||||||
if (state.isExpanded) return transform.delete().apply()
|
if (state.isExpanded) return transform.delete().apply()
|
||||||
|
const { startOffset, startBlock } = state
|
||||||
|
const text = startBlock.text
|
||||||
let n
|
let n
|
||||||
|
|
||||||
if (Key.isWord(e)) {
|
if (Key.isWord(e)) {
|
||||||
n = getWordOffsetForward(state.startBlock.text, state.startOffset)
|
n = String.getWordOffsetForward(text, startOffset)
|
||||||
} else if (Key.isLine(e)) {
|
} else if (Key.isLine(e)) {
|
||||||
n = state.startBlock.text.length - state.startOffset
|
n = text.length - startOffset
|
||||||
} else {
|
} else {
|
||||||
n = 1
|
n = String.getCharOffsetForward(text, startOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform.deleteForward(n).apply()
|
return transform.deleteForward(n).apply()
|
||||||
|
@@ -60,7 +60,7 @@ function isWord(char, remaining) {
|
|||||||
// If it's a chameleon character, recurse to see if the next one is or not.
|
// If it's a chameleon character, recurse to see if the next one is or not.
|
||||||
if (CHAMELEON.test(char)) {
|
if (CHAMELEON.test(char)) {
|
||||||
const next = remaining.charAt(0)
|
const next = remaining.charAt(0)
|
||||||
const length = getCharacterLength(next)
|
const length = getCharLength(next)
|
||||||
const rest = remaining.slice(length)
|
const rest = remaining.slice(length)
|
||||||
if (isWord(next, rest)) return true
|
if (isWord(next, rest)) return true
|
||||||
}
|
}
|
||||||
@@ -76,12 +76,51 @@ function isWord(char, remaining) {
|
|||||||
* @return {Number}
|
* @return {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function getCharacterLength(char) {
|
function getCharLength(char) {
|
||||||
return isSurrogate(char.charCodeAt(0))
|
return isSurrogate(char.charCodeAt(0))
|
||||||
? 2
|
? 2
|
||||||
: 1
|
: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the offset to the end of the first character in `text`.
|
||||||
|
*
|
||||||
|
* @param {String} text
|
||||||
|
* @return {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getCharOffset(text) {
|
||||||
|
const char = text.charAt(0)
|
||||||
|
return getCharLength(char)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the offset to the end of the character before an `offset` in `text`.
|
||||||
|
*
|
||||||
|
* @param {String} text
|
||||||
|
* @param {Number} offset
|
||||||
|
* @return {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getCharOffsetBackward(text, offset) {
|
||||||
|
text = text.slice(0, offset)
|
||||||
|
text = reverse(text)
|
||||||
|
return getCharOffset(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the offset to the end of the character after an `offset` in `text`.
|
||||||
|
*
|
||||||
|
* @param {String} text
|
||||||
|
* @param {Number} offset
|
||||||
|
* @return {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getCharOffsetForward(text, offset) {
|
||||||
|
text = text.slice(offset)
|
||||||
|
return getCharOffset(text)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the length of a `string`.
|
* Get the length of a `string`.
|
||||||
*
|
*
|
||||||
@@ -95,7 +134,7 @@ function getLength(string) {
|
|||||||
for (
|
for (
|
||||||
let i = 0, char = string.charAt(i);
|
let i = 0, char = string.charAt(i);
|
||||||
i < string.length;
|
i < string.length;
|
||||||
i += getCharacterLength(char)
|
i += getCharLength(char)
|
||||||
) {
|
) {
|
||||||
length++
|
length++
|
||||||
}
|
}
|
||||||
@@ -104,34 +143,7 @@ function getLength(string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the offset at the end of the word before an `offset` in `text`.
|
* Get the offset to the end of the first word in `text`.
|
||||||
*
|
|
||||||
* @param {String} text
|
|
||||||
* @param {Number} offset
|
|
||||||
* @return {Number}
|
|
||||||
*/
|
|
||||||
|
|
||||||
function getWordOffsetBackward(text, offset) {
|
|
||||||
text = text.slice(0, offset)
|
|
||||||
text = reverse(text)
|
|
||||||
return getWordOffset(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the offset at the end of the word after an `offset` in `text`.
|
|
||||||
*
|
|
||||||
* @param {String} text
|
|
||||||
* @param {Number} offset
|
|
||||||
* @return {Number}
|
|
||||||
*/
|
|
||||||
|
|
||||||
function getWordOffsetForward(text, offset) {
|
|
||||||
text = text.slice(offset)
|
|
||||||
return getWordOffset(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the offset at the end of the first word in `text`.
|
|
||||||
*
|
*
|
||||||
* @param {String} text
|
* @param {String} text
|
||||||
* @return {Number}
|
* @return {Number}
|
||||||
@@ -144,7 +156,7 @@ function getWordOffset(text) {
|
|||||||
let char
|
let char
|
||||||
|
|
||||||
while (char = text.charAt(i)) {
|
while (char = text.charAt(i)) {
|
||||||
const l = getCharacterLength(char)
|
const l = getCharLength(char)
|
||||||
const rest = text.slice(i + l)
|
const rest = text.slice(i + l)
|
||||||
|
|
||||||
if (isWord(char, rest)) {
|
if (isWord(char, rest)) {
|
||||||
@@ -162,11 +174,40 @@ function getWordOffset(text) {
|
|||||||
return length
|
return length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the offset to the end of the word before an `offset` in `text`.
|
||||||
|
*
|
||||||
|
* @param {String} text
|
||||||
|
* @param {Number} offset
|
||||||
|
* @return {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getWordOffsetBackward(text, offset) {
|
||||||
|
text = text.slice(0, offset)
|
||||||
|
text = reverse(text)
|
||||||
|
return getWordOffset(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the offset to the end of the word after an `offset` in `text`.
|
||||||
|
*
|
||||||
|
* @param {String} text
|
||||||
|
* @param {Number} offset
|
||||||
|
* @return {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getWordOffsetForward(text, offset) {
|
||||||
|
text = text.slice(offset)
|
||||||
|
return getWordOffset(text)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export.
|
* Export.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export {
|
export default {
|
||||||
|
getCharOffsetForward,
|
||||||
|
getCharOffsetBackward,
|
||||||
getWordOffsetBackward,
|
getWordOffsetBackward,
|
||||||
getWordOffsetForward
|
getWordOffsetForward
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user