fix: import markdown to text note

This commit is contained in:
SiriusXT 2025-10-28 10:17:37 +08:00
parent b2f1b3c910
commit 507910b0ce
7 changed files with 47 additions and 32 deletions

View File

@ -218,7 +218,6 @@ export type CommandMappings = {
/** Works only in the electron context menu. */
replaceMisspelling: CommandData;
importMarkdownInline: CommandData;
showPasswordNotSet: CommandData;
showProtectedSessionPasswordDialog: CommandData;
showUploadAttachmentsDialog: CommandData & { noteId: string };
@ -306,7 +305,7 @@ export type CommandMappings = {
addLinkToText: CommandData;
followLinkUnderCursor: CommandData;
insertDateTimeToText: CommandData;
pasteMarkdownIntoText: CommandData;
showMarkdownIntoTextDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
cutIntoNote: CommandData;
addIncludeNoteToText: CommandData;
editReadOnlyNote: CommandData;

View File

@ -20,9 +20,6 @@ function setupGlobs() {
window.glob.froca = froca;
window.glob.treeCache = froca; // compatibility for CKEditor builds for a while
// for CKEditor integration (button on block toolbar)
window.glob.importMarkdownInline = async () => appContext.triggerCommand("importMarkdownInline");
window.onerror = function (msg, url, lineNo, columnNo, error) {
const string = String(msg).toLowerCase();

View File

@ -26,7 +26,6 @@ interface CustomGlobals {
appContext: AppContext;
froca: Froca;
treeCache: Froca;
importMarkdownInline: () => Promise<unknown>;
SEARCH_HELP_TEXT: string;
activeDialog: JQuery<HTMLElement> | null;
componentId: string;

View File

@ -7,6 +7,7 @@ import utils from "../../services/utils";
import Modal from "../react/Modal";
import Button from "../react/Button";
import { useTriliumEvent } from "../react/hooks";
import EditableTextTypeWidget from "../type_widgets/editable_text";
interface RenderMarkdownResponse {
htmlContent: string;
@ -14,29 +15,27 @@ interface RenderMarkdownResponse {
export default function MarkdownImportDialog() {
const markdownImportTextArea = useRef<HTMLTextAreaElement>(null);
const [textTypeWidget, setTextTypeWidget] = useState<EditableTextTypeWidget>();
const [ text, setText ] = useState("");
const [ shown, setShown ] = useState(false);
const triggerImport = useCallback(() => {
if (appContext.tabManager.getActiveContextNoteType() !== "text") {
return;
}
useTriliumEvent("showMarkdownIntoTextDialog", ({ textTypeWidget }) => {
setTextTypeWidget(textTypeWidget);
if (utils.isElectron()) {
const { clipboard } = utils.dynamicRequire("electron");
const text = clipboard.readText();
convertMarkdownToHtml(text);
convertMarkdownToHtml(text, textTypeWidget);
} else {
setShown(true);
}
}, []);
useTriliumEvent("importMarkdownInline", triggerImport);
useTriliumEvent("pasteMarkdownIntoText", triggerImport);
});
async function sendForm() {
await convertMarkdownToHtml(text);
if (textTypeWidget) {
await convertMarkdownToHtml(text, textTypeWidget);
}
setText("");
setShown(false);
}
@ -44,7 +43,7 @@ export default function MarkdownImportDialog() {
return (
<Modal
className="markdown-import-dialog" title={t("markdown_import.dialog_title")} size="lg"
footer={<Button className="markdown-import-button" text={t("markdown_import.import_button")} onClick={sendForm} keyboardShortcut="Ctrl+Space" />}
footer={<Button className="markdown-import-button" text={t("markdown_import.import_button")} onClick={sendForm} keyboardShortcut="Ctrl+Enter" />}
onShown={() => markdownImportTextArea.current?.focus()}
onHidden={() => setShown(false) }
show={shown}
@ -63,19 +62,10 @@ export default function MarkdownImportDialog() {
)
}
async function convertMarkdownToHtml(markdownContent: string) {
async function convertMarkdownToHtml(markdownContent: string, textTypeWidget: EditableTextTypeWidget) {
const { htmlContent } = await server.post<RenderMarkdownResponse>("other/render-markdown", { markdownContent });
const textEditor = await appContext.tabManager.getActiveContext()?.getTextEditor();
if (!textEditor) {
return;
}
const viewFragment = textEditor.data.processor.toView(htmlContent);
const modelFragment = textEditor.data.toModel(viewFragment);
textEditor.model.insertContent(modelFragment, textEditor.model.document.selection);
textEditor.editing.view.focus();
await textTypeWidget.addHtmlToEditor(htmlContent);
toast.showMessage(t("markdown_import.import_success"));
}

View File

@ -329,6 +329,30 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
});
}
async addHtmlToEditor(html: string) {
await this.initialized;
const editor = this.watchdog.editor;
if (!editor) return;
editor.model.change((writer) => {
const viewFragment = editor.data.processor.toView(html);
const modelFragment = editor.data.toModel(viewFragment);
const insertPosition = editor.model.document.selection.getLastPosition();
if (insertPosition) {
const range = editor.model.insertContent(modelFragment, insertPosition);
if (range) {
writer.setSelection(range.end);
}
}
});
editor.editing.view.focus();
}
addTextToActiveEditorEvent({ text }: EventData<"addTextToActiveEditor">) {
if (!this.isActive()) {
return;
@ -385,6 +409,10 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
this.triggerCommand("showAddLinkDialog", { textTypeWidget: this, text: selectedText });
}
pasteMarkdownIntoTextCommand() {
this.triggerCommand("showMarkdownIntoTextDialog", { textTypeWidget: this });
}
getSelectedText() {
const range = this.watchdog.editor?.model.document.selection.getFirstRange();
let text = "";

View File

@ -19,6 +19,5 @@ declare global {
getHeaders(): Promise<Record<string, string>>;
getReferenceLinkTitle(href: string): Promise<string>;
getReferenceLinkTitleSync(href: string): string;
importMarkdownInline(): void;
}
}

View File

@ -31,7 +31,10 @@ export default class MarkdownImportPlugin extends Plugin {
class ImportMarkdownCommand extends Command {
execute() {
glob.importMarkdownInline();
const editorEl = this.editor.editing.view.getDomRoot();
const component = glob.getComponentByEl(editorEl);
component.triggerCommand('pasteMarkdownIntoText');
}
}