1
0
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:
Ian Storm Taylor
2016-07-14 13:42:10 -07:00
parent 54fe325c80
commit bf1ea4f975
2 changed files with 87 additions and 42 deletions

View File

@@ -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()

View File

@@ -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
} }