diff --git a/src/muya/lib/contentState/inputCtrl.js b/src/muya/lib/contentState/inputCtrl.js index 40b75674..e8a6c865 100644 --- a/src/muya/lib/contentState/inputCtrl.js +++ b/src/muya/lib/contentState/inputCtrl.js @@ -11,7 +11,21 @@ const BRACKET_HASH = { '*': '*', '_': '_', '"': '"', - '\'': '\'' + '\'': '\'', + '$': '$', + '~': '~' +} + +const BACK_HASH = { + '}': '{', + ']': '[', + ')': '(', + '*': '*', + '_': '_', + '"': '"', + '\'': '\'', + '$': '$', + '~': '~' } const inputCtrl = ContentState => { @@ -59,28 +73,44 @@ const inputCtrl = ContentState => { const { autoPairBracket, autoPairMarkdownSyntax, autoPairQuote } = this const inputChar = text.charAt(+offset - 1) const preInputChar = text.charAt(+offset - 2) + const prePreInputChar = text.charAt(+offset - 3) const postInputChar = text.charAt(+offset) - /* eslint-disable no-useless-escape */ - if ( + + if (/^delete/.test(event.inputType)) { + // handle `deleteContentBackward` or `deleteContentForward` + const deletedChar = block.text[offset] + if (event.inputType === 'deleteContentBackward' && postInputChar === BRACKET_HASH[deletedChar]) { + needRender = true + text = text.substring(0, offset) + text.substring(offset + 1) + } + if (event.inputType === 'deleteContentForward' && inputChar === BACK_HASH[deletedChar]) { + needRender = true + start.offset -= 1 + end.offset -= 1 + text = text.substring(0, offset - 1) + text.substring(offset) + } + /* eslint-disable no-useless-escape */ + } else if ( (event.inputType.indexOf('delete') === -1) && (inputChar === postInputChar) && ( (autoPairQuote && /[']{1}/.test(inputChar)) || (autoPairQuote && /["]{1}/.test(inputChar)) || (autoPairBracket && /[\}\]\)]{1}/.test(inputChar)) || - (autoPairMarkdownSyntax && /[*$`~_]{1}/.test(inputChar)) + (autoPairMarkdownSyntax && /[*$`~_]{1}/.test(inputChar)) && /[_*~]{1}/.test(prePreInputChar) ) ) { + needRender = true text = text.substring(0, offset) + text.substring(offset + 1) } else { /* eslint-disable no-useless-escape */ // Not Unicode aware, since things like \p{Alphabetic} or \p{L} are not supported yet - const isInInlineMath = this.checkCursorInInlineMath(text, start.offset) + const isInInlineMath = this.checkCursorInInlineMath(text, offset) if ( (autoPairQuote && /[']{1}/.test(inputChar) && !(/[a-zA-Z\d]{1}/.test(preInputChar))) || (autoPairQuote && /["]{1}/.test(inputChar)) || (autoPairBracket && /[\{\[\(]{1}/.test(inputChar)) || - (block.functionType !== 'codeLine' && !isInInlineMath && autoPairMarkdownSyntax && /[*_]{1}/.test(inputChar)) + (block.functionType !== 'codeLine' && !isInInlineMath && autoPairMarkdownSyntax && /[*$`~_]{1}/.test(inputChar)) ) { needRender = true text = BRACKET_HASH[event.data] @@ -88,8 +118,15 @@ const inputCtrl = ContentState => { : text } /* eslint-enable no-useless-escape */ - if (/\s/.test(event.data) && preInputChar === '*' && postInputChar === '*') { + // Delete the last `*` of `**` when you insert one space between `**` to create a bullet list. + if ( + /\s/.test(event.data) && + /^\* /.test(text) && + preInputChar === '*' && + postInputChar === '*' + ) { text = text.substring(0, offset) + text.substring(offset + 1) + needRender = true } } }