Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
}
}
}