diff --git a/.changeset/twelve-elephants-burn.md b/.changeset/twelve-elephants-burn.md new file mode 100644 index 000000000..91b0e4c4b --- /dev/null +++ b/.changeset/twelve-elephants-burn.md @@ -0,0 +1,6 @@ +--- +'slate': patch +--- + +Fix deleteBackward behavior for Thai script where deleting N character(s) backward should delete +N code point(s) instead of an entire grapheme cluster diff --git a/packages/slate/src/transforms/text.ts b/packages/slate/src/transforms/text.ts index c93589b08..1fa4197ef 100644 --- a/packages/slate/src/transforms/text.ts +++ b/packages/slate/src/transforms/text.ts @@ -65,7 +65,9 @@ export const TextTransforms: TextTransforms = { return } + let isCollapsed = false if (Range.isRange(at) && Range.isCollapsed(at)) { + isCollapsed = true at = at.anchor } @@ -170,14 +172,18 @@ export const TextTransforms: TextTransforms = { const startRef = Editor.pointRef(editor, start) const endRef = Editor.pointRef(editor, end) + let removedText = '' + if (!isSingleText && !startVoid) { const point = startRef.current! const [node] = Editor.leaf(editor, point) const { path } = point const { offset } = start const text = node.text.slice(offset) - if (text.length > 0) + if (text.length > 0) { editor.apply({ type: 'remove_text', path, offset, text }) + removedText = text + } } for (const pathRef of pathRefs) { @@ -191,8 +197,10 @@ export const TextTransforms: TextTransforms = { const { path } = point const offset = isSingleText ? start.offset : 0 const text = node.text.slice(offset, end.offset) - if (text.length > 0) + if (text.length > 0) { editor.apply({ type: 'remove_text', path, offset, text }) + removedText = text + } } if ( @@ -208,6 +216,22 @@ export const TextTransforms: TextTransforms = { }) } + // For Thai script, deleting N character(s) backward should delete + // N code point(s) instead of an entire grapheme cluster. + // Therefore, the remaining code points should be inserted back. + if ( + isCollapsed && + reverse && + unit === 'character' && + removedText.length > 1 && + removedText.match(/[\u0E00-\u0E7F]+/) + ) { + Transforms.insertText( + editor, + removedText.slice(0, removedText.length - distance) + ) + } + const startUnref = startRef.unref() const endUnref = endRef.unref() const point = reverse ? startUnref || endUnref : endUnref || startUnref diff --git a/packages/slate/test/transforms/delete/unit-character/thai-multiple-reverse.tsx b/packages/slate/test/transforms/delete/unit-character/thai-multiple-reverse.tsx new file mode 100644 index 000000000..ef9abf591 --- /dev/null +++ b/packages/slate/test/transforms/delete/unit-character/thai-multiple-reverse.tsx @@ -0,0 +1,23 @@ +/** @jsx jsx */ +import { Transforms } from 'slate' +import { jsx } from '../../..' + +export const run = editor => { + Transforms.delete(editor, { unit: 'character', distance: 2, reverse: true }) +} +export const input = ( + + + พี่ + + + +) +export const output = ( + + + พ + + + +) diff --git a/packages/slate/test/transforms/delete/unit-character/thai-reverse.tsx b/packages/slate/test/transforms/delete/unit-character/thai-reverse.tsx new file mode 100644 index 000000000..ad8fc2650 --- /dev/null +++ b/packages/slate/test/transforms/delete/unit-character/thai-reverse.tsx @@ -0,0 +1,23 @@ +/** @jsx jsx */ +import { Transforms } from 'slate' +import { jsx } from '../../..' + +export const run = editor => { + Transforms.delete(editor, { unit: 'character', reverse: true }) +} +export const input = ( + + + พี่ + + + +) +export const output = ( + + + พี + + + +)