Skip to content

Commit

Permalink
feat: jump cursor to the end to format (#976)
Browse files Browse the repository at this point in the history
* feat: jump cursor to the end to format

* update changelog
  • Loading branch information
Jocs authored and fxha committed Apr 27, 2019
1 parent 379290e commit f3b5342
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .github/CHANGELOG.md
Expand Up @@ -4,6 +4,8 @@

**:cactus:Feature**

- The cursor jump to the end of format or to the next brackets when press `tab`(#976)

**:butterfly:Optimization**

- Rewrite `select all` when press `CtrlOrCmd + A` (#937)
Expand Down
120 changes: 118 additions & 2 deletions src/muya/lib/contentState/tabCtrl.js
@@ -1,5 +1,6 @@
import selection from '../selection'
import { HTML_TAGS, VOID_HTML_TAGS } from '../config'
import { HTML_TAGS, VOID_HTML_TAGS, HAS_TEXT_BLOCK_REG } from '../config'
import { tokenizer } from '../parser'

/**
* parseSelector
Expand Down Expand Up @@ -35,9 +36,13 @@ const parseSelector = (str = '') => {
return { tag, id, className, isVoid }
}

const BOTH_SIDES_FORMATS = ['strong', 'em', 'inline_code', 'image', 'link', 'reference_image', 'reference_link', 'emoji', 'del', 'html_tag', 'inline_math']

const tabCtrl = ContentState => {
ContentState.prototype.findNextCell = function (block) {
if (!(/td|th/.test(block.type))) throw new Error('only th and td can have next cell')
if (!(/td|th/.test(block.type))) {
throw new Error('only th and td can have next cell')
}
const nextSibling = this.getBlock(block.nextSibling)
const parent = this.getBlock(block.parent)
const tbOrTh = this.getBlock(parent.parent)
Expand Down Expand Up @@ -175,6 +180,95 @@ const tabCtrl = ContentState => {
}
}

ContentState.prototype.checkCursorAtEndFormat = function (text, offset) {
const { labels } = this.stateRender
const tokens = tokenizer(text, [], false, labels)
let result = null
const walkTokens = tkns => {

for (const token of tkns) {
const { marker, type, range, children, srcAndTitle, hrefAndTitle, backlash, closeTag, isFullLink, label } = token
const { start, end } = range
if (BOTH_SIDES_FORMATS.includes(type) && offset > start && offset < end) {
switch (type) {
case 'strong':
case 'em':
case 'inline_code':
case 'emoji':
case 'del':
case 'inline_math': {
if (marker && offset === end - marker.length) {
result = {
offset: marker.length
}
return
}
break
}
case 'image':
case 'link': {
const linkTitleLen = (srcAndTitle || hrefAndTitle).length
const secondLashLen = backlash && backlash.second ? backlash.second.length : 0
if (offset === end - 3 - (linkTitleLen + secondLashLen)) {
result = {
offset: 2
}
return
} else if (offset === end - 1) {
result = {
offset: 1
}
return
}
break
}
case 'reference_image':
case 'reference_link': {
const labelLen = label ? label.length : 0
const secondLashLen = backlash && backlash.second ? backlash.second.length : 0
if (isFullLink) {
if (offset === end - 3 - labelLen - secondLashLen) {
result = {
offset: 2
}
return
} else if (offset === end - 1) {
result = {
offset: 1
}
return
}
} else if (offset === end - 1) {
result = {
offset: 1
}
return
}
break
}
case 'html_tag': {
if (closeTag && offset === end - closeTag.length) {
result = {
offset: closeTag.length
}
return
}
break
}
default:
break
}
}
if (children && children.length) {
walkTokens(children)
}
}
}
walkTokens(tokens)

return result
}

ContentState.prototype.tabHandler = function (event) {
// disable tab focus
event.preventDefault()
Expand All @@ -194,6 +288,27 @@ const tabCtrl = ContentState => {
return
}

// Handle `tab` to jump to the end of format when the cursor is at the end of format content.
if (
start.key === end.key &&
start.offset === end.offset &&
HAS_TEXT_BLOCK_REG.test(startBlock.type) &&
startBlock.functionType !== 'codeLine' && // code line has no inline syntax
startBlock.functionType !== 'languageInput' // language input textarea has no inline syntax
) {
const { text, key } = startBlock
const { offset } = start
const atEnd = this.checkCursorAtEndFormat(text, offset)
if (atEnd) {
this.cursor = {
start: { key, offset: offset + atEnd.offset },
end: { key, offset: offset + atEnd.offset }
}
return this.partialRender()
}
}

// Auto-complete of inline html tag and html block and `html` code block.
if (
start.key === end.key &&
start.offset === end.offset &&
Expand Down Expand Up @@ -253,6 +368,7 @@ const tabCtrl = ContentState => {
}
}

// Handle `tab` key in table cell.
let nextCell
if (start.key === end.key && /th|td/.test(startBlock.type)) {
nextCell = this.findNextCell(startBlock)
Expand Down

0 comments on commit f3b5342

Please sign in to comment.