mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-29 17:26:38 +01:00 
			
		
		
		
	findwidget in read only notes WIP
This commit is contained in:
		
							
								
								
									
										7
									
								
								libraries/jquery.mark.es6.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								libraries/jquery.mark.es6.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -16,7 +16,7 @@ async function convertMarkdownToHtml(text) { | |||||||
|  |  | ||||||
|     const result = writer.render(parsed); |     const result = writer.render(parsed); | ||||||
|  |  | ||||||
|     appContext.triggerCommand('executeInTextEditor', { |     appContext.triggerCommand('executeWithTextEditor', { | ||||||
|         callback: textEditor => { |         callback: textEditor => { | ||||||
|             const viewFragment = textEditor.data.processor.toView(result); |             const viewFragment = textEditor.data.processor.toView(result); | ||||||
|             const modelFragment = textEditor.data.toModel(viewFragment); |             const modelFragment = textEditor.data.toModel(viewFragment); | ||||||
|   | |||||||
| @@ -61,10 +61,13 @@ const EXCALIDRAW = { | |||||||
|         "node_modules/react/umd/react.production.min.js", |         "node_modules/react/umd/react.production.min.js", | ||||||
|         "node_modules/react-dom/umd/react-dom.production.min.js", |         "node_modules/react-dom/umd/react-dom.production.min.js", | ||||||
|         "node_modules/@excalidraw/excalidraw/dist/excalidraw.production.min.js", |         "node_modules/@excalidraw/excalidraw/dist/excalidraw.production.min.js", | ||||||
|     ], |     ] | ||||||
|     // css: [ | }; | ||||||
|     //     "stylesheets/somestyle.css" |  | ||||||
|     // ] | const MARKJS = { | ||||||
|  |     js: [ | ||||||
|  |         "libraries/jquery.mark.es6.min.js" | ||||||
|  |     ] | ||||||
| }; | }; | ||||||
|  |  | ||||||
| async function requireLibrary(library) { | async function requireLibrary(library) { | ||||||
| @@ -118,5 +121,6 @@ export default { | |||||||
|     WHEEL_ZOOM, |     WHEEL_ZOOM, | ||||||
|     FORCE_GRAPH, |     FORCE_GRAPH, | ||||||
|     MERMAID, |     MERMAID, | ||||||
|     EXCALIDRAW |     EXCALIDRAW, | ||||||
|  |     MARKJS | ||||||
| } | } | ||||||
|   | |||||||
| @@ -228,7 +228,7 @@ class NoteContext extends Component { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async getTextEditor(callback) { |     async getTextEditor(callback) { | ||||||
|         return new Promise(resolve => appContext.triggerCommand('executeInTextEditor', { |         return new Promise(resolve => appContext.triggerCommand('executeWithTextEditor', { | ||||||
|             callback, |             callback, | ||||||
|             resolve, |             resolve, | ||||||
|             ntxId: this.ntxId |             ntxId: this.ntxId | ||||||
| @@ -236,7 +236,14 @@ class NoteContext extends Component { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async getCodeEditor() { |     async getCodeEditor() { | ||||||
|         return new Promise(resolve => appContext.triggerCommand('executeInCodeEditor', { |         return new Promise(resolve => appContext.triggerCommand('executeWithCodeEditor', { | ||||||
|  |             resolve, | ||||||
|  |             ntxId: this.ntxId | ||||||
|  |         })); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async getContentElement() { | ||||||
|  |         return new Promise(resolve => appContext.triggerCommand('executeWithContentElement', { | ||||||
|             resolve, |             resolve, | ||||||
|             ntxId: this.ntxId |             ntxId: this.ntxId | ||||||
|         })); |         })); | ||||||
|   | |||||||
| @@ -365,6 +365,10 @@ function sleep(time_ms) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function escapeRegExp(str) { | ||||||
|  |     return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); | ||||||
|  | } | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     reloadFrontendApp, |     reloadFrontendApp, | ||||||
|     parseDate, |     parseDate, | ||||||
| @@ -410,4 +414,5 @@ export default { | |||||||
|     filterAttributeName, |     filterAttributeName, | ||||||
|     isValidAttributeName, |     isValidAttributeName, | ||||||
|     sleep, |     sleep, | ||||||
|  |     escapeRegExp | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ | |||||||
| import NoteContextAwareWidget from "./note_context_aware_widget.js"; | import NoteContextAwareWidget from "./note_context_aware_widget.js"; | ||||||
| import FindInText from "./find_in_text.js"; | import FindInText from "./find_in_text.js"; | ||||||
| import FindInCode from "./find_in_code.js"; | import FindInCode from "./find_in_code.js"; | ||||||
|  | import FindInHtml from "./find_in_html.js"; | ||||||
|  |  | ||||||
| const findWidgetDelayMillis = 200; | const findWidgetDelayMillis = 200; | ||||||
| const waitForEnter = (findWidgetDelayMillis < 0); | const waitForEnter = (findWidgetDelayMillis < 0); | ||||||
| @@ -86,6 +87,13 @@ export default class FindWidget extends NoteContextAwareWidget { | |||||||
|  |  | ||||||
|         this.textHandler = new FindInText(this); |         this.textHandler = new FindInText(this); | ||||||
|         this.codeHandler = new FindInCode(this); |         this.codeHandler = new FindInCode(this); | ||||||
|  |         this.htmlHandler = new FindInHtml(this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async noteSwitched() { | ||||||
|  |         await super.noteSwitched(); | ||||||
|  |  | ||||||
|  |         await this.closeSearch(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     doRender() { |     doRender() { | ||||||
| @@ -125,6 +133,42 @@ export default class FindWidget extends NoteContextAwareWidget { | |||||||
|         return this.$widget; |         return this.$widget; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async findInTextEvent() { | ||||||
|  |         if (!this.isActiveNoteContext()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!['text', 'code'].includes(this.note.type) || !this.$findBox.is(":hidden")) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const readOnly = await this.noteContext.isReadOnly(); | ||||||
|  |  | ||||||
|  |         if (readOnly) { | ||||||
|  |             this.handler = this.htmlHandler; | ||||||
|  |         } else { | ||||||
|  |             this.handler = this.note.type === "code" | ||||||
|  |                 ? this.codeHandler | ||||||
|  |                 : this.textHandler; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.$findBox.show(); | ||||||
|  |         this.$input.focus(); | ||||||
|  |         this.$totalFound.text(0); | ||||||
|  |         this.$currentFound.text(0); | ||||||
|  |  | ||||||
|  |         const searchTerm = await this.handler.getInitialSearchTerm(); | ||||||
|  |  | ||||||
|  |         this.$input.val(searchTerm || ""); | ||||||
|  |  | ||||||
|  |         // Directly perform the search if there's some text to | ||||||
|  |         // find, without delaying or waiting for enter | ||||||
|  |         if (searchTerm !== "") { | ||||||
|  |             this.$input.select(); | ||||||
|  |             await this.performFind(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     startSearch() { |     startSearch() { | ||||||
|         // XXX This should clear the previous search immediately in all cases |         // XXX This should clear the previous search immediately in all cases | ||||||
|         //     (the search is stale when waitforenter but also while the |         //     (the search is stale when waitforenter but also while the | ||||||
| @@ -172,35 +216,6 @@ export default class FindWidget extends NoteContextAwareWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async findInTextEvent() { |  | ||||||
|         if (!this.isActiveNoteContext()) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // Only writeable text and code supported |  | ||||||
|         const readOnly = await this.noteContext.isReadOnly(); |  | ||||||
|  |  | ||||||
|         if (readOnly || !['text', 'code'].includes(this.note.type) || !this.$findBox.is(":hidden")) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         this.$findBox.show(); |  | ||||||
|         this.$input.focus(); |  | ||||||
|         this.$totalFound.text(0); |  | ||||||
|         this.$currentFound.text(0); |  | ||||||
|  |  | ||||||
|         const searchTerm = await this.handler.getInitialSearchTerm(); |  | ||||||
|  |  | ||||||
|         this.$input.val(searchTerm || ""); |  | ||||||
|  |  | ||||||
|         // Directly perform the search if there's some text to |  | ||||||
|         // find, without delaying or waiting for enter |  | ||||||
|         if (searchTerm !== "") { |  | ||||||
|             this.$input.select(); |  | ||||||
|             await this.performFind(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** Perform the find and highlight the find results. */ |     /** Perform the find and highlight the find results. */ | ||||||
|     async performFind() { |     async performFind() { | ||||||
|         const searchTerm = this.$input.val(); |         const searchTerm = this.$input.val(); | ||||||
| @@ -216,6 +231,7 @@ export default class FindWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async closeSearch() { |     async closeSearch() { | ||||||
|  |         if (this.$findBox.is(":visible")) { | ||||||
|             this.$findBox.hide(); |             this.$findBox.hide(); | ||||||
|  |  | ||||||
|             // Restore any state, if there's a current occurrence clear markers |             // Restore any state, if there's a current occurrence clear markers | ||||||
| @@ -229,20 +245,9 @@ export default class FindWidget extends NoteContextAwareWidget { | |||||||
|  |  | ||||||
|             this.searchTerm = null; |             this.searchTerm = null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     async entitiesReloadedEvent({loadResults}) { |  | ||||||
|         if (loadResults.isNoteContentReloaded(this.noteId)) { |  | ||||||
|             this.refresh(); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     isEnabled() { |     isEnabled() { | ||||||
|         return super.isEnabled() && ['text', 'code'].includes(this.note.type); |         return super.isEnabled() && ['text', 'code'].includes(this.note.type); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     get handler() { |  | ||||||
|         return this.note.type === "code" |  | ||||||
|             ? this.codeHandler |  | ||||||
|             : this.textHandler; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,13 +1,14 @@ | |||||||
| // ck-find-result and ck-find-result_selected are the styles ck-editor | // ck-find-result and ck-find-result_selected are the styles ck-editor | ||||||
| // uses for highlighting matches, use the same one on CodeMirror | // uses for highlighting matches, use the same one on CodeMirror | ||||||
| // for consistency | // for consistency | ||||||
|  | import utils from "../services/utils.js"; | ||||||
|  |  | ||||||
| const FIND_RESULT_SELECTED_CSS_CLASSNAME = "ck-find-result_selected"; | const FIND_RESULT_SELECTED_CSS_CLASSNAME = "ck-find-result_selected"; | ||||||
| const FIND_RESULT_CSS_CLASSNAME = "ck-find-result"; | const FIND_RESULT_CSS_CLASSNAME = "ck-find-result"; | ||||||
|  |  | ||||||
| const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); |  | ||||||
|  |  | ||||||
| export default class FindInCode { | export default class FindInCode { | ||||||
|     constructor(parent) { |     constructor(parent) { | ||||||
|  |         /** @property {FindWidget} */ | ||||||
|         this.parent = parent; |         this.parent = parent; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -53,7 +54,7 @@ export default class FindInCode { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (searchTerm !== "") { |         if (searchTerm !== "") { | ||||||
|             searchTerm = escapeRegExp(searchTerm); |             searchTerm = utils.escapeRegExp(searchTerm); | ||||||
|  |  | ||||||
|             // Find and highlight matches |             // Find and highlight matches | ||||||
|             // Find and highlight matches |             // Find and highlight matches | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								src/public/app/widgets/find_in_html.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/public/app/widgets/find_in_html.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | // ck-find-result and ck-find-result_selected are the styles ck-editor | ||||||
|  | // uses for highlighting matches, use the same one on CodeMirror | ||||||
|  | // for consistency | ||||||
|  | import libraryLoader from "../services/library_loader.js"; | ||||||
|  | import utils from "../services/utils.js"; | ||||||
|  |  | ||||||
|  | const FIND_RESULT_SELECTED_CSS_CLASSNAME = "ck-find-result_selected"; | ||||||
|  | const FIND_RESULT_CSS_CLASSNAME = "ck-find-result"; | ||||||
|  |  | ||||||
|  | export default class FindInHtml { | ||||||
|  |     constructor(parent) { | ||||||
|  |         /** @property {FindWidget} */ | ||||||
|  |         this.parent = parent; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async getInitialSearchTerm() { | ||||||
|  |         return ""; // FIXME | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async performFind(searchTerm, matchCase, wholeWord) { | ||||||
|  |         await libraryLoader.requireLibrary(libraryLoader.MARKJS); | ||||||
|  |  | ||||||
|  |         const $content = await this.parent.noteContext.getContentElement(); | ||||||
|  |  | ||||||
|  |         $content.markRegExp(new RegExp(utils.escapeRegExp(searchTerm), "gi")); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async findNext(direction, currentFound, nextFound) { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async cleanup(totalFound, currentFound) { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async close() { | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,5 +1,6 @@ | |||||||
| export default class FindInText { | export default class FindInText { | ||||||
|     constructor(parent) { |     constructor(parent) { | ||||||
|  |         /** @property {FindWidget} */ | ||||||
|         this.parent = parent; |         this.parent = parent; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -171,7 +171,7 @@ export default class EditableCodeTypeWidget extends TypeWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async executeInCodeEditorEvent({resolve, ntxId}) { |     async executeWithCodeEditorEvent({resolve, ntxId}) { | ||||||
|         if (!this.isNoteContext(ntxId)) { |         if (!this.isNoteContext(ntxId)) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -229,7 +229,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | |||||||
|         return !selection.isCollapsed; |         return !selection.isCollapsed; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async executeInTextEditorEvent({callback, resolve, ntxId}) { |     async executeWithTextEditorEvent({callback, resolve, ntxId}) { | ||||||
|         if (!this.isNoteContext(ntxId)) { |         if (!this.isNoteContext(ntxId)) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -30,4 +30,14 @@ export default class ReadOnlyCodeTypeWidget extends TypeWidget { | |||||||
|  |  | ||||||
|         this.$content.text(noteComplement.content); |         this.$content.text(noteComplement.content); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async executeWithContentElementEvent({resolve, ntxId}) { | ||||||
|  |         if (!this.isNoteContext(ntxId)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         await this.initialized; | ||||||
|  |  | ||||||
|  |         resolve(this.$content); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -114,4 +114,14 @@ export default class ReadOnlyTextTypeWidget extends AbstractTextTypeWidget { | |||||||
|     async refreshIncludedNoteEvent({noteId}) { |     async refreshIncludedNoteEvent({noteId}) { | ||||||
|         this.refreshIncludedNote(this.$content, noteId); |         this.refreshIncludedNote(this.$content, noteId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async executeWithContentElementEvent({resolve, ntxId}) { | ||||||
|  |         if (!this.isNoteContext(ntxId)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         await this.initialized; | ||||||
|  |  | ||||||
|  |         resolve(this.$content); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user