diff --git a/apps/web/core/components/comments/card/edit-form.tsx b/apps/web/core/components/comments/card/edit-form.tsx index 6747df1233d..31e7f63da0f 100644 --- a/apps/web/core/components/comments/card/edit-form.tsx +++ b/apps/web/core/components/comments/card/edit-form.tsx @@ -71,7 +71,8 @@ export const CommentCardEditForm = observer(function CommentCardEditForm(props:
{ - if (e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !isEmpty) handleSubmit(onEnter)(e); + if (e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !e.nativeEvent.isComposing && !isEmpty) + handleSubmit(onEnter)(e); }} > ({ // replace text emojis with emoji node on any change appendTransaction: (transactions, oldState, newState) => { + // Skip during IME composition to avoid interfering with Chinese/Japanese/Korean input + if (this.editor.view.composing) { + return; + } + const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc); diff --git a/packages/editor/src/core/extensions/enter-key.ts b/packages/editor/src/core/extensions/enter-key.ts index 854a7081361..09badc5d4f3 100644 --- a/packages/editor/src/core/extensions/enter-key.ts +++ b/packages/editor/src/core/extensions/enter-key.ts @@ -9,6 +9,11 @@ export const EnterKeyExtension = (onEnterKeyPress?: () => void) => addKeyboardShortcuts(this) { return { Enter: () => { + // Don't trigger submission during IME composition (e.g., Chinese/Japanese input) + if (this.editor.view.composing) { + return false; + } + const { activeDropbarExtensions } = this.editor.storage.utility; if (activeDropbarExtensions.length === 0) { diff --git a/packages/editor/src/core/extensions/trailing-node.ts b/packages/editor/src/core/extensions/trailing-node.ts index 5f9624e9698..e578b2abd6f 100644 --- a/packages/editor/src/core/extensions/trailing-node.ts +++ b/packages/editor/src/core/extensions/trailing-node.ts @@ -30,11 +30,17 @@ export const TrailingNode = Extension.create({ const disabledNodes = Object.entries(this.editor.schema.nodes) .map(([, value]) => value) .filter((node) => this.options.notAfter.includes(node.name)); + const editor = this.editor; return [ new Plugin({ key: plugin, appendTransaction: (_, __, state) => { + // Skip during IME composition to avoid interfering with Chinese/Japanese/Korean input + if (editor.view.composing) { + return; + } + const { doc, tr, schema } = state; const shouldInsertNodeAtEnd = plugin.getState(state); const endPosition = doc.content.size; diff --git a/packages/editor/src/core/extensions/unique-id/extension.ts b/packages/editor/src/core/extensions/unique-id/extension.ts index c07ade359e6..a82776bfff4 100644 --- a/packages/editor/src/core/extensions/unique-id/extension.ts +++ b/packages/editor/src/core/extensions/unique-id/extension.ts @@ -131,6 +131,6 @@ export const UniqueID = Extension.create({ return []; } - return [createUniqueIDPlugin(this.options)]; + return [createUniqueIDPlugin(this.options, this.editor)]; }, }); diff --git a/packages/editor/src/core/extensions/unique-id/plugin.ts b/packages/editor/src/core/extensions/unique-id/plugin.ts index c7f09860b56..1e2fc03a826 100644 --- a/packages/editor/src/core/extensions/unique-id/plugin.ts +++ b/packages/editor/src/core/extensions/unique-id/plugin.ts @@ -1,4 +1,4 @@ -import { combineTransactionSteps, findChildrenInRange, findDuplicates, getChangedRanges } from "@tiptap/core"; +import { combineTransactionSteps, Editor, findChildrenInRange, findDuplicates, getChangedRanges } from "@tiptap/core"; import { Fragment, Slice } from "@tiptap/pm/model"; import type { Node as ProseMirrorNode } from "@tiptap/pm/model"; import { Plugin, PluginKey } from "@tiptap/pm/state"; @@ -8,7 +8,7 @@ import type { UniqueIDOptions } from "./extension"; // utils import { createIdsForView } from "./utils"; -export const createUniqueIDPlugin = (options: UniqueIDOptions) => { +export const createUniqueIDPlugin = (options: UniqueIDOptions, editor?: Editor) => { let dragSourceElement: Element | null = null; let transformPasted = false; let syncHandler: (() => void) | null = null; @@ -16,6 +16,11 @@ export const createUniqueIDPlugin = (options: UniqueIDOptions) => { return new Plugin({ key: new PluginKey("uniqueID"), appendTransaction: (transactions, oldState, newState) => { + // Skip during IME composition to avoid interfering with Chinese/Japanese/Korean input + if (editor?.view.composing) { + return; + } + const hasDocChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc); const filterTransactions =