huashui-ai / public-discussion

划水AI 公共讨论区域
1 stars 0 forks source link

插入代码块后,在输入的过程中按tab键会无法继续输入 #34

Open mikesimth opened 3 weeks ago

mikesimth commented 3 weeks ago

请一定按照该模板提交 issue ,谢谢~

问题现象

插入代码块后,在输入的过程中按tab键会无法继续输入,并且光标消失

截图或录屏(可选)

088b3736d8445f5f25df703ba4e317b

你期望的样子

按tab键还能继续输入

复现步骤

weiwang-1992 commented 2 days ago

技术方案

  1. 缩进单位 => 4个连续空格
  2. 处理 tab 键,增加缩进
  3. 处理 shift + tab 键, 减少缩进

关键点

  1. useEffect Hook: 使用 useEffect 监听editor实例,在组件卸载时移除监听。
  2. editor?.commands.insertContent(' '): 使用 Tiptap 提供的 commands 方法来处理 tab 键,增加缩进
  3. 正则表达式匹配全局4个空格,在当前光标位置删除4个连续空格,这样来处理shift + tab 键 减少缩进 @wangfupeng1988

    实现代码

    
    useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (!editor) return
    
      if (event.key === 'Tab') {
        event.preventDefault()
        if (event.shiftKey) {
          // Shift + Tab: 减少缩进(删除当前光标位置的4个连续空格)
          const { state } = editor.view
          const { selection, schema, tr } = state
          const { from, to, $from } = selection
          const range = { from, to }
    
          let spacesToRemove = 4
    
          tr.doc.nodesBetween(range.from, range.to, (node, pos) => {
            if (node.isTextblock && node.content.size) {
              const text = node.textContent
              const cursorPos = $from.pos - pos // 光标在当前文本块中的位置
              if (cursorPos >= 4) {
                const prefix = text.slice(0, cursorPos) // 光标前的文本
                const spaceRegex = /( {4})/g
                const match = prefix.match(spaceRegex) // 匹配连续的4个空格
                if (match) {
                  const spacesCount = match[0].length
                  spacesToRemove = Math.min(spacesCount, spacesToRemove) // 取最小值,确保在减少缩进时,只删除当前位置前的连续4个空格
                  tr.delete(pos + cursorPos - spacesToRemove, pos + cursorPos) // 使用 delete 方法删除空格
                }
              }
            }
          })
          editor.view.dispatch(tr)
        } else {
          // Tab: 增加缩进(4个连续空格)
          editor.commands.insertContent('    ')
        }
      }
    }
    document.addEventListener('keydown', handleKeyDown)
    return () => {
      document.removeEventListener('keydown', handleKeyDown)
    }
    }, [editor])

return (

...

)

wangfupeng1988 commented 2 days ago
weiwang-1992 commented 14 hours ago

插件版本技术方案

  1. 使用ProseMirror的handleKeyDown方法处理键盘事件
  2. view.state.tr.insertText(' ')方法增加缩进
  3. 缩进单位: 4个空格

@wangfupeng1988

实现代码


import { Extension } from '@tiptap/core'
import { Plugin, PluginKey } from '@tiptap/pm/state'

export const extensionName = 'tabIndent'

export const TabIndent = Extension.create({
  name: extensionName,

  //自定义插件,用于tab 键处理缩进
  addProseMirrorPlugins() {
    return [
      new Plugin({
        key: new PluginKey(extensionName),
        props: {
          // handleKeyDown是ProseMirror 插件 API 的一部分,用于在插件中捕获和处理键盘事件。
          handleKeyDown(view, event) {
            if (event.key === 'Tab') {
              event.preventDefault()
              const { state, dispatch } = view
              const { $from } = state.selection

              // 创建一个事务,在当前光标位置插入 缩进(4个空格)
              const tr = state.tr.insertText('    ', $from.pos)
              // 派发该事务,从而更新文档内容并通知编辑器视图进行更新。
              dispatch(tr)
              // true,表示事件已经处理,不需要再传递给其他插件或默认行为
              return true
            }
            // false,表示事件未处理,可以继续传递给其他插件或默认行为
            return false
          },
        },
      }),
    ]
  },
})
weiwang-1992 commented 13 hours ago

测试内容

测试内容 测试结果 备注
在编辑器文字或代码块中,按下tab键后,可向后插入4个空格

@zer0fire 大佬测试下

zer0fire commented 13 hours ago

测试结果

测试内容 测试结果 备注
在编辑器文字或代码块中,按下tab键后,可向后插入4个空格 正确 可以在任意块中输入 tab 插入空格

测试截图

20240717112009_rec_

备注

是否需要根据配置,确定 tab 插入的是空格还是制表符?

weiwang-1992 commented 12 hours ago

@wangfupeng1988 看下测试结果,是否需要根据配置,确定 tab 插入的是空格还是制表符?

wangfupeng1988 commented 12 hours ago

是否需要根据配置,确定 tab 插入的是空格还是制表符?

不用配置。直接输入四个空格即可。