mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 19:49:01 +01:00 
			
		
		
		
	fix: import markdown to text note (#7538)
This commit is contained in:
		
						commit
						7f22532a0a
					
				| @ -218,12 +218,12 @@ export type CommandMappings = { | |||||||
|     /** Works only in the electron context menu. */ |     /** Works only in the electron context menu. */ | ||||||
|     replaceMisspelling: CommandData; |     replaceMisspelling: CommandData; | ||||||
| 
 | 
 | ||||||
|     importMarkdownInline: CommandData; |  | ||||||
|     showPasswordNotSet: CommandData; |     showPasswordNotSet: CommandData; | ||||||
|     showProtectedSessionPasswordDialog: CommandData; |     showProtectedSessionPasswordDialog: CommandData; | ||||||
|     showUploadAttachmentsDialog: CommandData & { noteId: string }; |     showUploadAttachmentsDialog: CommandData & { noteId: string }; | ||||||
|     showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget }; |     showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget }; | ||||||
|     showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string }; |     showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string }; | ||||||
|  |     showPasteMarkdownDialog: CommandData & { textTypeWidget: EditableTextTypeWidget }; | ||||||
|     closeProtectedSessionPasswordDialog: CommandData; |     closeProtectedSessionPasswordDialog: CommandData; | ||||||
|     copyImageReferenceToClipboard: CommandData; |     copyImageReferenceToClipboard: CommandData; | ||||||
|     copyImageToClipboard: CommandData; |     copyImageToClipboard: CommandData; | ||||||
|  | |||||||
| @ -20,9 +20,6 @@ function setupGlobs() { | |||||||
|     window.glob.froca = froca; |     window.glob.froca = froca; | ||||||
|     window.glob.treeCache = froca; // compatibility for CKEditor builds for a while
 |     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) { |     window.onerror = function (msg, url, lineNo, columnNo, error) { | ||||||
|         const string = String(msg).toLowerCase(); |         const string = String(msg).toLowerCase(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								apps/client/src/types.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								apps/client/src/types.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -26,7 +26,6 @@ interface CustomGlobals { | |||||||
|     appContext: AppContext; |     appContext: AppContext; | ||||||
|     froca: Froca; |     froca: Froca; | ||||||
|     treeCache: Froca; |     treeCache: Froca; | ||||||
|     importMarkdownInline: () => Promise<unknown>; |  | ||||||
|     SEARCH_HELP_TEXT: string; |     SEARCH_HELP_TEXT: string; | ||||||
|     activeDialog: JQuery<HTMLElement> | null; |     activeDialog: JQuery<HTMLElement> | null; | ||||||
|     componentId: string; |     componentId: string; | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ import utils from "../../services/utils"; | |||||||
| import Modal from "../react/Modal"; | import Modal from "../react/Modal"; | ||||||
| import Button from "../react/Button"; | import Button from "../react/Button"; | ||||||
| import { useTriliumEvent } from "../react/hooks"; | import { useTriliumEvent } from "../react/hooks"; | ||||||
|  | import EditableTextTypeWidget from "../type_widgets/editable_text"; | ||||||
| 
 | 
 | ||||||
| interface RenderMarkdownResponse { | interface RenderMarkdownResponse { | ||||||
|     htmlContent: string; |     htmlContent: string; | ||||||
| @ -14,39 +15,34 @@ interface RenderMarkdownResponse { | |||||||
| 
 | 
 | ||||||
| export default function MarkdownImportDialog() { | export default function MarkdownImportDialog() { | ||||||
|     const markdownImportTextArea = useRef<HTMLTextAreaElement>(null); |     const markdownImportTextArea = useRef<HTMLTextAreaElement>(null); | ||||||
|  |     const [textTypeWidget, setTextTypeWidget] = useState<EditableTextTypeWidget>(); | ||||||
|     const [ text, setText ] = useState(""); |     const [ text, setText ] = useState(""); | ||||||
|     const [ shown, setShown ] = useState(false); |     const [ shown, setShown ] = useState(false); | ||||||
| 
 | 
 | ||||||
|     const triggerImport = useCallback(() => { |     useTriliumEvent("showPasteMarkdownDialog", ({ textTypeWidget }) => { | ||||||
|         if (appContext.tabManager.getActiveContextNoteType() !== "text") { |         setTextTypeWidget(textTypeWidget); | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         if (utils.isElectron()) { |         if (utils.isElectron()) { | ||||||
|             const { clipboard } = utils.dynamicRequire("electron"); |             const { clipboard } = utils.dynamicRequire("electron"); | ||||||
|             const text = clipboard.readText(); |             const text = clipboard.readText(); | ||||||
|      |      | ||||||
|             convertMarkdownToHtml(text); |             convertMarkdownToHtml(text, textTypeWidget); | ||||||
|         } else { |         } else { | ||||||
|             setShown(true); |             setShown(true); | ||||||
|         } |         } | ||||||
|     }, []); |     }); | ||||||
| 
 |  | ||||||
|     useTriliumEvent("importMarkdownInline", triggerImport); |  | ||||||
|     useTriliumEvent("pasteMarkdownIntoText", triggerImport); |  | ||||||
| 
 |  | ||||||
|     async function sendForm() { |  | ||||||
|         await convertMarkdownToHtml(text); |  | ||||||
|         setText(""); |  | ||||||
|         setShown(false); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|         <Modal |         <Modal | ||||||
|             className="markdown-import-dialog" title={t("markdown_import.dialog_title")} size="lg" |             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={() => setShown(false)} keyboardShortcut="Ctrl+Enter" />} | ||||||
|             onShown={() => markdownImportTextArea.current?.focus()} |             onShown={() => markdownImportTextArea.current?.focus()} | ||||||
|             onHidden={() => setShown(false) } |             onHidden={async () => { | ||||||
|  |                 if (textTypeWidget) { | ||||||
|  |                     await convertMarkdownToHtml(text, textTypeWidget); | ||||||
|  |                 } | ||||||
|  |                 setShown(false); | ||||||
|  |                 setText(""); | ||||||
|  |             }} | ||||||
|             show={shown} |             show={shown} | ||||||
|         > |         > | ||||||
|             <p>{t("markdown_import.modal_body_text")}</p> |             <p>{t("markdown_import.modal_body_text")}</p> | ||||||
| @ -56,26 +52,17 @@ export default function MarkdownImportDialog() { | |||||||
|                 onKeyDown={(e) => { |                 onKeyDown={(e) => { | ||||||
|                     if (e.key === "Enter" && e.ctrlKey) { |                     if (e.key === "Enter" && e.ctrlKey) { | ||||||
|                         e.preventDefault(); |                         e.preventDefault(); | ||||||
|                         sendForm(); |                         setShown(false); | ||||||
|                     } |                     } | ||||||
|                 }}></textarea> |                 }}></textarea> | ||||||
|         </Modal> |         </Modal> | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function convertMarkdownToHtml(markdownContent: string) { | async function convertMarkdownToHtml(markdownContent: string, textTypeWidget: EditableTextTypeWidget) { | ||||||
|     const { htmlContent } = await server.post<RenderMarkdownResponse>("other/render-markdown", { markdownContent }); |     const { htmlContent } = await server.post<RenderMarkdownResponse>("other/render-markdown", { markdownContent }); | ||||||
| 
 | 
 | ||||||
|     const textEditor = await appContext.tabManager.getActiveContext()?.getTextEditor(); |     await textTypeWidget.addHtmlToEditor(htmlContent); | ||||||
|     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(); |  | ||||||
|      |      | ||||||
|     toast.showMessage(t("markdown_import.import_success")); |     toast.showMessage(t("markdown_import.import_success")); | ||||||
| } | } | ||||||
| @ -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">) { |     addTextToActiveEditorEvent({ text }: EventData<"addTextToActiveEditor">) { | ||||||
|         if (!this.isActive()) { |         if (!this.isActive()) { | ||||||
|             return; |             return; | ||||||
| @ -385,6 +409,10 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | |||||||
|         this.triggerCommand("showAddLinkDialog", { textTypeWidget: this, text: selectedText }); |         this.triggerCommand("showAddLinkDialog", { textTypeWidget: this, text: selectedText }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pasteMarkdownIntoTextCommand() { | ||||||
|  |         this.triggerCommand("showPasteMarkdownDialog", { textTypeWidget: this }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     getSelectedText() { |     getSelectedText() { | ||||||
|         const range = this.watchdog.editor?.model.document.selection.getFirstRange(); |         const range = this.watchdog.editor?.model.document.selection.getFirstRange(); | ||||||
|         let text = ""; |         let text = ""; | ||||||
|  | |||||||
| @ -19,6 +19,5 @@ declare global { | |||||||
|         getHeaders(): Promise<Record<string, string>>; |         getHeaders(): Promise<Record<string, string>>; | ||||||
|         getReferenceLinkTitle(href: string): Promise<string>; |         getReferenceLinkTitle(href: string): Promise<string>; | ||||||
|         getReferenceLinkTitleSync(href: string): string; |         getReferenceLinkTitleSync(href: string): string; | ||||||
|         importMarkdownInline(): void; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -31,7 +31,10 @@ export default class MarkdownImportPlugin extends Plugin { | |||||||
| class ImportMarkdownCommand extends Command { | class ImportMarkdownCommand extends Command { | ||||||
| 
 | 
 | ||||||
|     execute() { |     execute() { | ||||||
|         glob.importMarkdownInline(); | 		const editorEl = this.editor.editing.view.getDomRoot(); | ||||||
|  | 		const component = glob.getComponentByEl(editorEl); | ||||||
|  | 
 | ||||||
|  | 		component.triggerCommand('pasteMarkdownIntoText'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran