feat: editor enhancement for order list (#763)

pull/767/head
Zeng1998 2 years ago committed by GitHub
parent 1eec474007
commit a41745c9ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,4 @@
import { forwardRef, ReactNode, useCallback, useEffect, useImperativeHandle, useRef } from "react";
import useRefresh from "../../hooks/useRefresh";
import "../../less/editor.less";
export interface EditorRefActions {
@ -10,6 +9,7 @@ export interface EditorRefActions {
getContent: () => string;
getSelectedContent: () => string;
getCursorPosition: () => number;
setCursorPosition: (pos: number) => void;
}
interface Props {
@ -25,7 +25,6 @@ interface Props {
const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<EditorRefActions>) {
const { className, initialContent, placeholder, fullscreen, onPaste, onContentChange: handleContentChangeCallback } = props;
const editorRef = useRef<HTMLTextAreaElement>(null);
const refresh = useRefresh();
useEffect(() => {
if (editorRef.current && initialContent) {
@ -36,10 +35,16 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
useEffect(() => {
if (editorRef.current && !fullscreen) {
updateEditorHeight();
}
}, [editorRef.current?.value, fullscreen]);
const updateEditorHeight = () => {
if (editorRef.current) {
editorRef.current.style.height = "auto";
editorRef.current.style.height = (editorRef.current.scrollHeight ?? 0) + "px";
}
}, [editorRef.current?.value, fullscreen]);
};
useImperativeHandle(
ref,
@ -66,7 +71,7 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
editorRef.current.focus();
editorRef.current.selectionEnd = endPosition + prefix.length + content.length;
handleContentChangeCallback(editorRef.current.value);
refresh();
updateEditorHeight();
},
removeText: (start: number, length: number) => {
if (!editorRef.current) {
@ -79,14 +84,14 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
editorRef.current.focus();
editorRef.current.selectionEnd = start;
handleContentChangeCallback(editorRef.current.value);
refresh();
updateEditorHeight();
},
setContent: (text: string) => {
if (editorRef.current) {
editorRef.current.value = text;
editorRef.current.focus();
handleContentChangeCallback(editorRef.current.value);
refresh();
updateEditorHeight();
}
},
getContent: (): string => {
@ -100,13 +105,16 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
const end = editorRef.current?.selectionEnd;
return editorRef.current?.value.slice(start, end) ?? "";
},
setCursorPosition: (pos: number) => {
editorRef.current?.setSelectionRange(pos, pos);
},
}),
[]
);
const handleEditorInput = useCallback(() => {
handleContentChangeCallback(editorRef.current?.value ?? "");
refresh();
updateEditorHeight();
}, []);
return (

@ -15,6 +15,7 @@ import showResourcesSelectorDialog from "./ResourcesSelectorDialog";
import "../less/memo-editor.less";
const listItemSymbolList = ["- [ ] ", "- [x] ", "- [X] ", "* ", "- "];
const emptyOlReg = /^([1-9][0-9]*)\. $/;
const getEditorContentCache = (): string => {
return storage.get(["editorContentCache"]).editorContentCache ?? "";
@ -124,17 +125,52 @@ const MemoEditor = () => {
const contentBeforeCursor = editorRef.current.getContent().slice(0, cursorPosition);
const rowValue = last(contentBeforeCursor.split("\n"));
if (rowValue) {
if (listItemSymbolList.includes(rowValue)) {
if (listItemSymbolList.includes(rowValue) || emptyOlReg.test(rowValue)) {
event.preventDefault();
editorRef.current.removeText(cursorPosition - rowValue.length, rowValue.length);
} else {
// unordered list / checked list
let matched = false;
for (const listItemSymbol of listItemSymbolList) {
if (rowValue.startsWith(listItemSymbol)) {
event.preventDefault();
editorRef.current.insertText("", `\n${listItemSymbol}`);
matched = true;
break;
}
}
if (!matched) {
// ordered list
const olReg = /^([1-9][0-9]*)\. /;
const olRes = olReg.exec(rowValue);
if (olRes) {
let order = parseInt(olRes[1]) + 1;
event.preventDefault();
const contentAfterCursor = editorRef.current.getContent().slice(cursorPosition);
editorRef.current.insertText("", `\n${order}. `);
if (contentAfterCursor) {
// correct the order
order++;
const nextRows = contentAfterCursor.split("\n").slice(1);
const rowStart = contentBeforeCursor.split("\n").length + 1;
const content = editorRef.current.getContent().split("\n");
let updated = false;
for (let i = 0; i < nextRows.length; i++) {
const rowRes = olReg.exec(nextRows[i]);
if (rowRes) {
content[rowStart + i] = nextRows[i].replace(rowRes[1], (order + i).toString());
updated = true;
} else {
break;
}
}
if (updated) {
editorRef.current.setContent(content.join("\n"));
editorRef.current.setCursorPosition(cursorPosition + 4);
}
}
}
}
}
}
return;

@ -1,15 +0,0 @@
import { useCallback, useState } from "react";
const useRefresh = () => {
const [, setBoolean] = useState<boolean>(false);
const refresh = useCallback(() => {
setBoolean((ps) => {
return !ps;
});
}, []);
return refresh;
};
export default useRefresh;
Loading…
Cancel
Save