Skip to content

Commit

Permalink
fix: selection sync error (#260)
Browse files Browse the repository at this point in the history
* style: refactor by new eslint

* fix: selection sync error

* docs: modify dev docs

* docs: modify publish docs

* Create gentle-goats-hang.md

* Update packages/core/src/text-area/event-handlers/composition.ts

254 在windows上搭建webview2或者electron客户端使用wangeditor和搜狗输入法执行特定步骤会出现异常

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* perf: variable naming correction & delete redundant judgment conditions

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • Loading branch information
cycleccc and coderabbitai[bot] committed Oct 17, 2024
1 parent c2abdb2 commit c0cfd9c
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 80 deletions.
14 changes: 14 additions & 0 deletions .changeset/gentle-goats-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'@wangeditor-next/upload-image-module': patch
'@wangeditor-next/code-highlight': patch
'@wangeditor-next/basic-modules': patch
'@wangeditor-next/yjs-for-react': patch
'@wangeditor-next/table-module': patch
'@wangeditor-next/video-module': patch
'@wangeditor-next/list-module': patch
'@wangeditor-next/editor': patch
'@wangeditor-next/core': patch
'@wangeditor-next/yjs': patch
---

254 在windows上搭建webview2或者electron客户端使用wangeditor和搜狗输入法执行特定步骤会出现异常
4 changes: 2 additions & 2 deletions docs/contribution-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
我们非常欢迎Pull Request!

- **克隆仓库**:Fork并克隆项目到本地。
- **创建分支**:基于开发分支`develop`创建一个新的分支。
- **创建分支**:基于开发分支`master`创建一个新的分支。
- **编写代码**:确保您的代码遵循项目中的编码规范。
- **提交更改**:提交您的更改,并确保提交信息清晰明了。
- **Pull Request**:将您的分支推送到远程仓库,并在GitHub上发起Pull Request。
Expand Down Expand Up @@ -62,4 +62,4 @@

## 感谢

我们非常感激您的贡献,无论是大是小。您的努力帮助我们构建了一个更好的`wangEditor-next`
我们非常感激您的贡献,无论是大是小。您的努力帮助我们构建了一个更好的`wangEditor-next`
4 changes: 2 additions & 2 deletions docs/contribution-EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ If you find a bug or have an idea for a new feature, please create a new issue i
We warmly welcome Pull Requests!

- **Fork the Repository**: Fork and clone the project to your local machine.
- **Create a Branch**: Create a new branch based on the `develop` branch.
- **Create a Branch**: Create a new branch based on the `master` branch.
- **Write Code**: Ensure your code follows the project's coding standards.
- **Commit Changes**: Commit your changes, and make sure the commit messages are clear and descriptive.
- **Pull Request**: Push your branch to the remote repository and initiate a Pull Request on GitHub.
Expand Down Expand Up @@ -62,4 +62,4 @@ Help answer questions, participate in discussions, or promote the project on soc

## Thanks

We greatly appreciate your contributions, big or small. Your efforts help us build a better `wangEditor-next`.
We greatly appreciate your contributions, big or small. Your efforts help us build a better `wangEditor-next`.
2 changes: 1 addition & 1 deletion docs/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

- 了解 slate.js
- 了解 vdom 和 snabbdom.js
- 了解 lerna
- 了解 turbo 和 changeset
- 已安装 yarn

## 本地启动
Expand Down
44 changes: 9 additions & 35 deletions docs/publish.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,14 @@
# 发布到 NPM

因为我们的项目是使用 `independent` 的方式组织 `muti-packgae`,所以每个包都有单独的版本号,默认使用 `lerna publish` 发布包,我们需要根据包的修改内容选择合适的版本号。**对于没有变动的 `package`,lerna 发布的时候不会算在本次发布的内容里面**
## 发布一个正式版本

发布的流程分两步:
1. 添加 `changeset``npx changeset`
2. 提交代码合并 master,线上会自动发版到 `npm`

第一步:将所有要发版的代码合并到 `master` 分支后,先在本地执行 `yarn release:version` 生成各个本次变动的 `package` 的版本后,自动生成 `changelog`,接着 lerna 会生成 `git tag``push` 到远程。

第二步:上面步骤完成后, `lerna` push `git tag` 到远程的时候会触发我们配置的 `git action`,走完正常的发版 `action`,具体看 [`action` 配置]('./../.github/workflows/release.yml')

因为目前我们还在开发当中,所以为了更加方便发版到 `npm` 进行测试,目前,项目中集成了以下 `release``script command`

## 正常发布一个版本

```bash
yarn release:publish
```

## 发布指定的 dist-tag 版本

发布一个 `experimental` [dist-tag](https://docs.npmjs.com/cli/v7/commands/npm-dist-tag) 的版本:

```bash
yarn release:publish:experimental
```

发布一个 `next` [dist-tag](https://docs.npmjs.com/cli/v7/commands/npm-dist-tag) 的版本:

```bash
yarn release:next
```

## 发布 canary 版本

发布一个 `canary` 版本:
```bash
# 1.0.0 => 1.0.1-alpha.0+${SHA} of packages changed since the previous commit
lerna publish --canary
```
## 发布一个测试版本

1. 进入预发布模式:`npx changeset pre enter beta`
2. 添加 `changeset``npx changeset`
3. 更新版本号:`npx changeset version`
4. 发布测试包:`npx changeset publish`
5. 退出预发布模式(可选):`npx changeset pre exit`
100 changes: 60 additions & 40 deletions packages/core/src/text-area/event-handlers/composition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,47 @@
* @author wangfupeng
*/

import { Editor, Range, Element, Text } from 'slate'
import { IDomEditor } from '../../editor/interface'
import {
Editor, Element, Range, Text,
} from 'slate'

import { DomEditor } from '../../editor/dom-editor'
import TextArea from '../TextArea'
import { hasEditableTarget } from '../helpers'
import { IS_SAFARI, IS_CHROME, IS_FIREFOX } from '../../utils/ua'
import { IDomEditor } from '../../editor/interface'
import { DOMNode } from '../../utils/dom'
import { IS_CHROME, IS_FIREFOX, IS_SAFARI } from '../../utils/ua'
import { hasEditableTarget } from '../helpers'
import { hidePlaceholder } from '../place-holder'
import { editorSelectionToDOM } from '../syncSelection'
import TextArea from '../TextArea'

const EDITOR_TO_TEXT: WeakMap<IDomEditor, string> = new WeakMap()
const EDITOR_TO_START_CONTAINER: WeakMap<IDomEditor, DOMNode> = new WeakMap()

function areBothTextNodes(editor, selection) {
if (Range.isCollapsed(selection)) {
const { anchor, focus } = selection

if (
anchor.path.length === 2
&& focus.path.length === 2
&& (anchor.offset === 0 || focus.offset === 0)
) {
const nowEntry = Editor.node(editor, anchor.path)
const nowPath = anchor.offset === 0 ? anchor.path : focus.path
const prePath = [nowPath[0], nowPath[1] - 1]

if (nowPath[1] === 0) {
return false
}
const preEntry = Editor.node(editor, prePath)

if (Text.isText(preEntry[0]) && Text.isText(nowEntry[0])) {
return true
}
}
}
}

/**
* composition start 事件
* @param e event
Expand All @@ -25,9 +53,10 @@ const EDITOR_TO_START_CONTAINER: WeakMap<IDomEditor, DOMNode> = new WeakMap()
export function handleCompositionStart(e: Event, textarea: TextArea, editor: IDomEditor) {
const event = e as CompositionEvent

if (!hasEditableTarget(editor, event.target)) return
if (!hasEditableTarget(editor, event.target)) { return }

const { selection } = editor

if (selection && Range.isExpanded(selection)) {
Editor.deleteFragment(editor)

Expand All @@ -40,11 +69,12 @@ export function handleCompositionStart(e: Event, textarea: TextArea, editor: IDo
})
}

if (selection && (Range.isExpanded(selection) || Range.isCollapsed(selection))) {
if (editor.selection) {
// 记录下 dom text ,以便触发 maxLength 时使用
const domRange = DomEditor.toDOMRange(editor, selection)
const domRange = DomEditor.toDOMRange(editor, editor.selection)
const startContainer = domRange.startContainer
const curText = startContainer.textContent || ''

EDITOR_TO_TEXT.set(editor, curText)

// 记录下 dom range startContainer
Expand All @@ -63,7 +93,7 @@ export function handleCompositionStart(e: Event, textarea: TextArea, editor: IDo
* @param editor editor
*/
export function handleCompositionUpdate(event: Event, textarea: TextArea, editor: IDomEditor) {
if (!hasEditableTarget(editor, event.target)) return
if (!hasEditableTarget(editor, event.target)) { return }

textarea.isComposing = true
}
Expand All @@ -77,11 +107,12 @@ export function handleCompositionUpdate(event: Event, textarea: TextArea, editor
export function handleCompositionEnd(e: Event, textarea: TextArea, editor: IDomEditor) {
const event = e as CompositionEvent

if (!hasEditableTarget(editor, event.target)) return
if (!hasEditableTarget(editor, event.target)) { return }
textarea.isComposing = false

const { selection } = editor
if (selection == null) return

if (selection == null) { return }

// 清理可能暴露的 text 节点
// 例如 chrome 在链接后面,输入拼音,就会出现有暴露出来的 text node
Expand All @@ -96,8 +127,9 @@ export function handleCompositionEnd(e: Event, textarea: TextArea, editor: IDomE
const start = Range.isBackward(selection) ? selection.focus : selection.anchor
const [paragraph] = Editor.node(editor, [start.path[0]])

for (let i = 0; i < start.path.length; i++) {
for (let i = 0; i < start.path.length; i += 1) {
const [node] = Editor.node(editor, start.path.slice(0, i + 1))

if (Element.isElement(node)) {
if (((IS_SAFARI || IS_FIREFOX) && node.type === 'link') || node.type === 'code') {
DomEditor.setNewKey(paragraph)
Expand All @@ -107,15 +139,21 @@ export function handleCompositionEnd(e: Event, textarea: TextArea, editor: IDomE
}

const { data } = event
if (!data) return

if (!data) { return }

// 检查 maxLength -【注意】这里只处理拼音输入的 maxLength 限制。其他限制,在插件 with-max-length.ts 中处理
const { maxLength } = editor.getConfig()

if (maxLength) {
const leftLengthOfMaxLength = DomEditor.getLeftLengthOfMaxLength(editor)

if (leftLengthOfMaxLength < data.length) {
const domRange = DomEditor.toDOMRange(editor, selection)
domRange.startContainer.textContent = EDITOR_TO_TEXT.get(editor) || ''

if (domRange.startContainer.nodeType === Node.TEXT_NODE) {
domRange.startContainer.textContent = EDITOR_TO_TEXT.get(editor) || ''
}
if (leftLengthOfMaxLength > 0) {
// 剩余长度 >0 ,但小于 data 长度,截取一部分插入
Editor.insertText(editor, data.slice(0, leftLengthOfMaxLength))
Expand All @@ -128,6 +166,7 @@ export function handleCompositionEnd(e: Event, textarea: TextArea, editor: IDomE
// 拼音输入,当选区的边缘在两个 text node 之间时 需要重置为 domselction 的 选区
const root = DomEditor.findDocumentOrShadowRoot(editor)
const domSelection = root.getSelection()

if (domSelection && areBothTextNodes(editor, selection)) {
editor.selection = DomEditor.toSlateRange(editor, domSelection, {
exactMatch: false,
Expand All @@ -140,11 +179,14 @@ export function handleCompositionEnd(e: Event, textarea: TextArea, editor: IDomE
// 检查拼音输入是否夸 DOM 节点了,解决 wangEditor-v5/issues/47
if (!IS_SAFARI) {
setTimeout(() => {
const { selection } = editor
if (selection == null) return
const { selection: setTimeoutSelection } = editor

if (setTimeoutSelection == null) { return }
const oldStartContainer = EDITOR_TO_START_CONTAINER.get(editor) // 拼音输入开始时的 text node
if (oldStartContainer == null) return
const curStartContainer = DomEditor.toDOMRange(editor, selection).startContainer // 拼音输入结束时的 text node

if (oldStartContainer == null) { return }
const curStartContainer = DomEditor.toDOMRange(editor, setTimeoutSelection).startContainer // 拼音输入结束时的 text node

if (curStartContainer === oldStartContainer) {
// 拼音输入的开始和结束,都在同一个 text node ,则不做处理
return
Expand All @@ -154,25 +196,3 @@ export function handleCompositionEnd(e: Event, textarea: TextArea, editor: IDomE
})
}
}
function areBothTextNodes(editor, selection) {
if (Range.isCollapsed(selection)) {
const { anchor, focus } = selection
if (
anchor.path.length === 2 &&
focus.path.length === 2 &&
(anchor.offset === 0 || focus.path.offset === 0)
) {
const nowEntry = Editor.node(editor, anchor.path)
const nowPath = anchor.offset === 0 ? anchor.path : focus.path
const prePath = [nowPath[0], nowPath[1] - 1]
if (nowPath[1] === 0) {
return false
}
const preEntry = Editor.node(editor, prePath)

if (Text.isText(preEntry[0]) && Text.isText(nowEntry[0])) {
return true
}
}
}
}

0 comments on commit c0cfd9c

Please sign in to comment.