mirror of https://github.com/usememos/memos.git
refactor(web): extract list auto-completion logic into custom hook
- Create useListAutoCompletion hook to encapsulate list continuation logic - Simplify handleEditorKeyDown in Editor component - Improve code organization and testability - Add comprehensive documentation for the hook - Maintain all existing functionality for markdown lists The handleEditorKeyDown function is now much cleaner, delegating list auto-completion concerns to a dedicated, reusable hook.
This commit is contained in:
parent
f11c355446
commit
7f8f0c753d
|
|
@ -1,10 +1,10 @@
|
||||||
import { forwardRef, ReactNode, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
import { forwardRef, ReactNode, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { detectLastListItem, generateListContinuation } from "@/utils/markdown-list-detection";
|
|
||||||
import { Command } from "../types/command";
|
import { Command } from "../types/command";
|
||||||
import CommandSuggestions from "./CommandSuggestions";
|
import CommandSuggestions from "./CommandSuggestions";
|
||||||
import TagSuggestions from "./TagSuggestions";
|
import TagSuggestions from "./TagSuggestions";
|
||||||
import { editorCommands } from "./commands";
|
import { editorCommands } from "./commands";
|
||||||
|
import { useListAutoCompletion } from "./useListAutoCompletion";
|
||||||
|
|
||||||
export interface EditorRefActions {
|
export interface EditorRefActions {
|
||||||
getEditor: () => HTMLTextAreaElement | null;
|
getEditor: () => HTMLTextAreaElement | null;
|
||||||
|
|
@ -152,22 +152,14 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
|
||||||
updateEditorHeight();
|
updateEditorHeight();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleEditorKeyDown = async (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const { handleEnterKey } = useListAutoCompletion({
|
||||||
if (event.key === "Enter" && !isInIME) {
|
editorActions,
|
||||||
if (event.shiftKey || event.ctrlKey || event.metaKey || event.altKey) {
|
isInIME,
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const cursorPosition = editorActions.getCursorPosition();
|
const handleEditorKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
const prevContent = editorActions.getContent().substring(0, cursorPosition);
|
if (event.key === "Enter") {
|
||||||
|
handleEnterKey(event);
|
||||||
// Detect list item using regex-based detection
|
|
||||||
const listInfo = detectLastListItem(prevContent);
|
|
||||||
if (listInfo.type) {
|
|
||||||
event.preventDefault();
|
|
||||||
const insertText = "\n" + generateListContinuation(listInfo);
|
|
||||||
editorActions.insertText(insertText);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { useCallback } from "react";
|
||||||
|
import { detectLastListItem, generateListContinuation } from "@/utils/markdown-list-detection";
|
||||||
|
import { EditorRefActions } from ".";
|
||||||
|
|
||||||
|
interface UseListAutoCompletionOptions {
|
||||||
|
editorActions: EditorRefActions;
|
||||||
|
isInIME: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom hook for handling markdown list auto-completion.
|
||||||
|
* When the user presses Enter on a list item, this hook automatically
|
||||||
|
* continues the list with the appropriate formatting.
|
||||||
|
*
|
||||||
|
* Supports:
|
||||||
|
* - Ordered lists (1. item, 2. item, etc.)
|
||||||
|
* - Unordered lists (- item, * item, + item)
|
||||||
|
* - Task lists (- [ ] task, - [x] task)
|
||||||
|
* - Nested lists with proper indentation
|
||||||
|
*/
|
||||||
|
export function useListAutoCompletion({ editorActions, isInIME }: UseListAutoCompletionOptions) {
|
||||||
|
/**
|
||||||
|
* Handles the Enter key press to auto-complete list items.
|
||||||
|
* Returns true if the event was handled, false otherwise.
|
||||||
|
*/
|
||||||
|
const handleEnterKey = useCallback(
|
||||||
|
(event: React.KeyboardEvent<HTMLTextAreaElement>): boolean => {
|
||||||
|
// Don't handle if in IME composition (for Asian languages)
|
||||||
|
if (isInIME) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't handle if modifier keys are pressed (user wants manual control)
|
||||||
|
if (event.shiftKey || event.ctrlKey || event.metaKey || event.altKey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cursorPosition = editorActions.getCursorPosition();
|
||||||
|
const contentBeforeCursor = editorActions.getContent().substring(0, cursorPosition);
|
||||||
|
|
||||||
|
// Detect if we're on a list item
|
||||||
|
const listInfo = detectLastListItem(contentBeforeCursor);
|
||||||
|
|
||||||
|
if (listInfo.type) {
|
||||||
|
event.preventDefault();
|
||||||
|
const continuation = generateListContinuation(listInfo);
|
||||||
|
editorActions.insertText("\n" + continuation);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
[editorActions, isInIME],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { handleEnterKey };
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue