mirror of https://github.com/halo-dev/halo
fix: list items require multiple backspace presses to delete (#6408)
#### What type of PR is this? /kind bug /area editor /milestone 2.18.x #### What this PR does / why we need it: 目前当编辑器中列表内容为空时,需要按退格键多次才能删除掉此列表内容。 本 PR 在执行单行删除逻辑之前,会检查列表是否处于活动状态,如果是则不再执行单行删除的逻辑。列表会执行 ListKeyMap 相关快捷键。 #### How to test it? 1. 在默认富文本键入一个列表。 2. 使用退格键删除这个列表。 3. 查看是否可以一次就删除。 #### Which issue(s) this PR fixes: Fixes #6389 #### Does this PR introduce a user-facing change? ```release-note 修复默认编辑器中列表项需要按多次退格键才可以删除的问题 ```pull/6411/head
parent
5707f295f1
commit
fae5bf7ce9
|
@ -7,6 +7,7 @@ import {
|
||||||
type KeyboardShortcutCommand,
|
type KeyboardShortcutCommand,
|
||||||
} from "@/tiptap";
|
} from "@/tiptap";
|
||||||
import { TextSelection, Transaction } from "@/tiptap/pm";
|
import { TextSelection, Transaction } from "@/tiptap/pm";
|
||||||
|
import { isListActive } from "@/utils/isListActive";
|
||||||
|
|
||||||
declare module "@/tiptap" {
|
declare module "@/tiptap" {
|
||||||
interface Commands<ReturnType> {
|
interface Commands<ReturnType> {
|
||||||
|
@ -222,14 +223,6 @@ const isTextIndent = (tr: Transaction, currNodePos: number) => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isListActive = (editor: CoreEditor) => {
|
|
||||||
return (
|
|
||||||
editor.isActive("bulletList") ||
|
|
||||||
editor.isActive("orderedList") ||
|
|
||||||
editor.isActive("taskList")
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const isFilterActive = (editor: CoreEditor) => {
|
const isFilterActive = (editor: CoreEditor) => {
|
||||||
return editor.isActive("table") || editor.isActive("columns");
|
return editor.isActive("table") || editor.isActive("columns");
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@ import ToolbarItem from "@/components/toolbar/ToolbarItem.vue";
|
||||||
import ToolbarSubItem from "@/components/toolbar/ToolbarSubItem.vue";
|
import ToolbarSubItem from "@/components/toolbar/ToolbarSubItem.vue";
|
||||||
import { i18n } from "@/locales";
|
import { i18n } from "@/locales";
|
||||||
import {
|
import {
|
||||||
|
CoreEditor,
|
||||||
EditorState,
|
EditorState,
|
||||||
ResolvedPos,
|
ResolvedPos,
|
||||||
TextSelection,
|
TextSelection,
|
||||||
|
@ -11,6 +12,7 @@ import {
|
||||||
} from "@/tiptap";
|
} from "@/tiptap";
|
||||||
import type { ExtensionOptions, ToolbarItem as TypeToolbarItem } from "@/types";
|
import type { ExtensionOptions, ToolbarItem as TypeToolbarItem } from "@/types";
|
||||||
import { deleteNodeByPos } from "@/utils";
|
import { deleteNodeByPos } from "@/utils";
|
||||||
|
import { isListActive } from "@/utils/isListActive";
|
||||||
import { isEmpty } from "@/utils/isNodeEmpty";
|
import { isEmpty } from "@/utils/isNodeEmpty";
|
||||||
import type { ParagraphOptions } from "@tiptap/extension-paragraph";
|
import type { ParagraphOptions } from "@tiptap/extension-paragraph";
|
||||||
import TiptapParagraph from "@tiptap/extension-paragraph";
|
import TiptapParagraph from "@tiptap/extension-paragraph";
|
||||||
|
@ -97,15 +99,15 @@ const Paragraph = TiptapParagraph.extend<ExtensionOptions & ParagraphOptions>({
|
||||||
|
|
||||||
addKeyboardShortcuts() {
|
addKeyboardShortcuts() {
|
||||||
return {
|
return {
|
||||||
Backspace: ({ editor }) => {
|
Backspace: ({ editor }: { editor: CoreEditor }) => {
|
||||||
const { state, view } = editor;
|
const { state, view } = editor;
|
||||||
const { selection } = state;
|
const { selection } = state;
|
||||||
|
|
||||||
if (
|
if (isListActive(editor) || !isActive(state, Paragraph.name)) {
|
||||||
!isActive(state, Paragraph.name) ||
|
return false;
|
||||||
!(selection instanceof TextSelection) ||
|
}
|
||||||
!selection.empty
|
|
||||||
) {
|
if (!(selection instanceof TextSelection) || !selection.empty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import {
|
||||||
|
callOrReturn,
|
||||||
|
CoreEditor,
|
||||||
|
getExtensionField,
|
||||||
|
isActive,
|
||||||
|
type NodeConfig,
|
||||||
|
} from "@/tiptap";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a list is active
|
||||||
|
*
|
||||||
|
* @param state - The state of the editor
|
||||||
|
* @returns Whether a list is active
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const isActive = isListActive(editor.state);
|
||||||
|
* ```
|
||||||
|
**/
|
||||||
|
export const isListActive = (editor: CoreEditor) => {
|
||||||
|
const extensions = editor.extensionManager.extensions;
|
||||||
|
const listExtensions = extensions.filter((extension) => {
|
||||||
|
const context = {
|
||||||
|
name: extension.name,
|
||||||
|
options: extension.options,
|
||||||
|
storage: extension.storage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const group = callOrReturn(
|
||||||
|
getExtensionField<NodeConfig["group"]>(extension, "group", context)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (typeof group !== "string") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return group.split(" ").includes("list");
|
||||||
|
});
|
||||||
|
|
||||||
|
return listExtensions.some((extension) => {
|
||||||
|
return isActive(editor.state, extension.name);
|
||||||
|
});
|
||||||
|
};
|
Loading…
Reference in New Issue