diff --git a/src/models/transform.js b/src/models/transform.js index a5b25c3b0..c82b20ead 100644 --- a/src/models/transform.js +++ b/src/models/transform.js @@ -23,11 +23,10 @@ class Transform { * * @param {Object} properties * @property {State} properties.state - * @property {Boolean} properties.normalized */ constructor(properties) { - const { state, normalized = true } = properties + const { state } = properties this.state = state this.operations = [] } diff --git a/src/plugins/core.js b/src/plugins/core.js index 269765b59..50cd08abc 100644 --- a/src/plugins/core.js +++ b/src/plugins/core.js @@ -353,9 +353,11 @@ function Plugin(options = {}) { case 'delete': return onKeyDownDelete(e, data, state) case 'left': return onKeyDownLeft(e, data, state) case 'right': return onKeyDownRight(e, data, state) + case 'd': return onKeyDownD(e, data, state) + case 'h': return onKeyDownH(e, data, state) + case 'k': return onKeyDownK(e, data, state) case 'y': return onKeyDownY(e, data, state) case 'z': return onKeyDownZ(e, data, state) - case 'k': return onKeyDownK(e, data, state) } } @@ -369,8 +371,6 @@ function Plugin(options = {}) { */ function onKeyDownEnter(e, data, state) { - debug('onKeyDownEnter', { data }) - const { document, startKey } = state const hasVoidParent = document.hasVoidParent(startKey) @@ -401,36 +401,13 @@ function Plugin(options = {}) { */ function onKeyDownBackspace(e, data, state) { - debug('onKeyDownBackspace', { data }) - - // If expanded, delete regularly. - if (state.isExpanded) { - return state - .transform() - .delete() - .apply() - } - - const { startOffset, startBlock } = state - const text = startBlock.text - let n - - // Determine how far backwards to delete. - if (data.isWord) { - n = String.getWordOffsetBackward(text, startOffset) - } - - else if (data.isLine) { - n = startOffset - } - - else { - n = String.getCharOffsetBackward(text, startOffset) - } + let boundary = 'Char' + if (data.isWord) boundary = 'Word' + if (data.isLine) boundary = 'Line' return state .transform() - .deleteBackward(n) + [`delete${boundary}Backward`]() .apply() } @@ -444,36 +421,13 @@ function Plugin(options = {}) { */ function onKeyDownDelete(e, data, state) { - debug('onKeyDownDelete', { data }) - - // If expanded, delete regularly. - if (state.isExpanded) { - return state - .transform() - .delete() - .apply() - } - - const { startOffset, startBlock } = state - const text = startBlock.text - let n - - // Determine how far forwards to delete. - if (data.isWord) { - n = String.getWordOffsetForward(text, startOffset) - } - - else if (data.isLine) { - n = text.length - startOffset - } - - else { - n = String.getCharOffsetForward(text, startOffset) - } + let boundary = 'Char' + if (data.isWord) boundary = 'Word' + if (data.isLine) boundary = 'Line' return state .transform() - .deleteForward(n) + [`delete${boundary}Forward`]() .apply() } @@ -505,8 +459,6 @@ function Plugin(options = {}) { const previousText = document.getPreviousText(startKey) if (!previousText) return - debug('onKeyDownLeft', { data }) - e.preventDefault() return state .transform() @@ -543,8 +495,6 @@ function Plugin(options = {}) { const nextText = document.getNextText(startKey) if (!nextText) return state - debug('onKeyDownRight', { data }) - // COMPAT: In Chrome & Safari, selections that are at the zero offset of // an inline node will be automatically replaced to be at the last offset // of a previous inline node, which screws us up, so we always want to set @@ -560,6 +510,60 @@ function Plugin(options = {}) { } } + /** + * On `d` key down, for Macs, delete one character forward. + * + * @param {Event} e + * @param {Object} data + * @param {State} state + * @return {State} + */ + + function onKeyDownD(e, data, state) { + if (!IS_MAC || !data.isCtrl) return + e.preventDefault() + return state + .transform() + .deleteCharForward() + .apply() + } + + /** + * On `h` key down, for Macs, delete until the end of the line. + * + * @param {Event} e + * @param {Object} data + * @param {State} state + * @return {State} + */ + + function onKeyDownH(e, data, state) { + if (!IS_MAC || !data.isCtrl) return + e.preventDefault() + return state + .transform() + .deleteCharBackward() + .apply() + } + + /** + * On `k` key down, for Macs, delete until the end of the line. + * + * @param {Event} e + * @param {Object} data + * @param {State} state + * @return {State} + */ + + function onKeyDownK(e, data, state) { + if (!IS_MAC || !data.isCtrl) return + e.preventDefault() + return state + .transform() + .deleteLineForward() + .apply() + } + /** * On `y` key down, redo. * @@ -572,8 +576,6 @@ function Plugin(options = {}) { function onKeyDownY(e, data, state) { if (!data.isMod) return - debug('onKeyDownY', { data }) - return state .transform() .redo() @@ -592,36 +594,12 @@ function Plugin(options = {}) { function onKeyDownZ(e, data, state) { if (!data.isMod) return - debug('onKeyDownZ', { data }) - return state .transform() [data.isShift ? 'redo' : 'undo']() .apply({ save: false }) } - /** - * On `k` key down, delete untill the end of the line (mac only) - * - * @param {Event} e - * @param {Object} data - * @param {State} state - * @return {State} - */ - - function onKeyDownK(e, data, state) { - if (!IS_MAC || !data.isCtrl) return - - debug('onKeyDownK', { data }) - - const { startOffset, startBlock } = state - - return state - .transform() - .deleteForward(startBlock.text.length - startOffset) - .apply() - } - /** * On paste. * @@ -695,15 +673,11 @@ function Plugin(options = {}) { */ function onSelect(e, data, state) { - const { selection } = data - - debug('onSelect', { data, selection: selection.toJS() }) + debug('onSelect', { data }) return state .transform() - .moveTo(selection) - // Since the document has not changed, we only need to normalize the - // selection and this is done automatically in `transform.apply()`. + .moveTo(data.selection) .apply() } diff --git a/src/transforms/at-current-range.js b/src/transforms/at-current-range.js index 5c1e6813a..de5623779 100644 --- a/src/transforms/at-current-range.js +++ b/src/transforms/at-current-range.js @@ -63,6 +63,42 @@ export function deleteBackward(transform, n = 1) { transform.deleteBackwardAtRange(selection, n) } +/** + * Delete backward until the character boundary at the current selection. + * + * @param {Transform} transform + */ + +export function deleteCharBackward(transform) { + const { state } = transform + const { selection } = state + transform.deleteCharBackwardAtRange(selection) +} + +/** + * Delete backward until the line boundary at the current selection. + * + * @param {Transform} transform + */ + +export function deleteLineBackward(transform) { + const { state } = transform + const { selection } = state + transform.deleteLineBackwardAtRange(selection) +} + +/** + * Delete backward until the word boundary at the current selection. + * + * @param {Transform} transform + */ + +export function deleteWordBackward(transform) { + const { state } = transform + const { selection } = state + transform.deleteWordBackwardAtRange(selection) +} + /** * Delete forward `n` characters at the current selection. * @@ -76,6 +112,42 @@ export function deleteForward(transform, n = 1) { transform.deleteForwardAtRange(selection, n) } +/** + * Delete forward until the character boundary at the current selection. + * + * @param {Transform} transform + */ + +export function deleteCharForward(transform) { + const { state } = transform + const { selection } = state + transform.deleteCharForwardAtRange(selection) +} + +/** + * Delete forward until the line boundary at the current selection. + * + * @param {Transform} transform + */ + +export function deleteLineForward(transform) { + const { state } = transform + const { selection } = state + transform.deleteLineForwardAtRange(selection) +} + +/** + * Delete forward until the word boundary at the current selection. + * + * @param {Transform} transform + */ + +export function deleteWordForward(transform) { + const { state } = transform + const { selection } = state + transform.deleteWordForwardAtRange(selection) +} + /** * Insert a `block` at the current selection. * diff --git a/src/transforms/at-range.js b/src/transforms/at-range.js index 004994a76..001834a10 100644 --- a/src/transforms/at-range.js +++ b/src/transforms/at-range.js @@ -1,6 +1,7 @@ /* eslint no-console: 0 */ import Normalize from '../utils/normalize' +import String from '../utils/string' import SCHEMA from '../schemas/core' import { List } from 'immutable' @@ -119,6 +120,55 @@ export function deleteAtRange(transform, range, options = {}) { } } +/** + * Delete backward until the character boundary at a `range`. + * + * @param {Transform} transform + * @param {Selection} range + * @param {Object} options + * @property {Boolean} normalize + */ + +export function deleteCharBackwardAtRange(transform, range, options) { + const { state } = transform + const { startOffset, startBlock } = state + const { text } = startBlock + const n = String.getCharOffsetBackward(text, startOffset) + transform.deleteBackwardAtRange(range, n, options) +} + +/** + * Delete backward until the line boundary at a `range`. + * + * @param {Transform} transform + * @param {Selection} range + * @param {Object} options + * @property {Boolean} normalize + */ + +export function deleteLineBackwardAtRange(transform, range, options) { + const { state } = transform + const { startOffset } = state + transform.deleteBackwardAtRange(range, startOffset, options) +} + +/** + * Delete backward until the word boundary at a `range`. + * + * @param {Transform} transform + * @param {Selection} range + * @param {Object} options + * @property {Boolean} normalize + */ + +export function deleteWordBackwardAtRange(transform, range, options) { + const { state } = transform + const { startOffset, startBlock } = state + const { text } = startBlock + const n = String.getWordOffsetBackward(text, startOffset) + transform.deleteBackwardAtRange(range, n, options) +} + /** * Delete backward `n` characters at a `range`. * @@ -189,6 +239,55 @@ export function deleteBackwardAtRange(transform, range, n = 1, options = {}) { transform.deleteAtRange(range, { normalize }) } +/** + * Delete forward until the character boundary at a `range`. + * + * @param {Transform} transform + * @param {Selection} range + * @param {Object} options + * @property {Boolean} normalize + */ + +export function deleteCharForwardAtRange(transform, range, options) { + const { state } = transform + const { startOffset, startBlock } = state + const { text } = startBlock + const n = String.getCharOffsetForward(text, startOffset) + transform.deleteForwardAtRange(range, n, options) +} + +/** + * Delete forward until the line boundary at a `range`. + * + * @param {Transform} transform + * @param {Selection} range + * @param {Object} options + * @property {Boolean} normalize + */ + +export function deleteLineForwardAtRange(transform, range, options) { + const { state } = transform + const { startOffset, startBlock } = state + transform.deleteForwardAtRange(range, startBlock.length - startOffset, options) +} + +/** + * Delete forward until the word boundary at a `range`. + * + * @param {Transform} transform + * @param {Selection} range + * @param {Object} options + * @property {Boolean} normalize + */ + +export function deleteWordForwardAtRange(transform, range, options) { + const { state } = transform + const { startOffset, startBlock } = state + const { text } = startBlock + const n = String.getWordOffsetForward(text, startOffset) + transform.deleteForwardAtRange(range, n, options) +} + /** * Delete forward `n` characters at a `range`. * diff --git a/src/transforms/index.js b/src/transforms/index.js index 8ee1eac6f..0f02063ea 100644 --- a/src/transforms/index.js +++ b/src/transforms/index.js @@ -33,7 +33,13 @@ import { import { deleteAtRange, deleteBackwardAtRange, + deleteCharBackwardAtRange, + deleteCharForwardAtRange, deleteForwardAtRange, + deleteLineBackwardAtRange, + deleteLineForwardAtRange, + deleteWordBackwardAtRange, + deleteWordForwardAtRange, insertBlockAtRange, insertFragmentAtRange, insertInlineAtRange, @@ -59,7 +65,13 @@ import { import { _delete, deleteBackward, + deleteCharBackward, + deleteCharForward, deleteForward, + deleteLineBackward, + deleteLineForward, + deleteWordBackward, + deleteWordForward, insertBlock, insertFragment, insertInline, @@ -194,7 +206,13 @@ export default { deleteAtRange, deleteBackwardAtRange, + deleteCharBackwardAtRange, + deleteCharForwardAtRange, deleteForwardAtRange, + deleteLineBackwardAtRange, + deleteLineForwardAtRange, + deleteWordBackwardAtRange, + deleteWordForwardAtRange, insertBlockAtRange, insertFragmentAtRange, insertInlineAtRange, @@ -218,7 +236,13 @@ export default { delete: _delete, deleteBackward, + deleteCharBackward, + deleteCharForward, deleteForward, + deleteLineBackward, + deleteLineForward, + deleteWordBackward, + deleteWordForward, insertBlock, insertFragment, insertInline,