mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 13:01:31 +08:00 
			
		
		
		
	refactor(code/find): remove inner class
This commit is contained in:
		
							parent
							
								
									e5417827f4
								
							
						
					
					
						commit
						8a35e390f2
					
				| @ -1,5 +1,5 @@ | |||||||
| import { EditorView, Decoration, MatchDecorator, ViewPlugin, ViewUpdate } from "@codemirror/view"; | import { EditorView, Decoration, MatchDecorator, ViewPlugin, ViewUpdate } from "@codemirror/view"; | ||||||
| import { StateEffect, Compartment, EditorSelection, RangeSet } from "@codemirror/state"; | import { RangeSet, RangeSetBuilder } from "@codemirror/state"; | ||||||
| 
 | 
 | ||||||
| const searchMatchDecoration = Decoration.mark({ class: "cm-searchMatch" }); | const searchMatchDecoration = Decoration.mark({ class: "cm-searchMatch" }); | ||||||
| 
 | 
 | ||||||
| @ -8,90 +8,99 @@ interface Match { | |||||||
|     to: number; |     to: number; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function createSearchHighlighter(view: EditorView, searchTerm: string, matchCase: boolean, wholeWord: boolean) { | export class SearchHighlighter { | ||||||
|     // Escape the search term for use in RegExp
 |     matches: RangeSet<Decoration>; | ||||||
|     const escapedTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); |     currentFound: number; | ||||||
|     const wordBoundary = wholeWord ? "\\b" : ""; |     totalFound: number; | ||||||
|     const flags = matchCase ? "g" : "gi"; |     matcher?: MatchDecorator; | ||||||
|     const regex = new RegExp(`${wordBoundary}${escapedTerm}${wordBoundary}`, flags); |     private parsedMatches: Match[]; | ||||||
| 
 | 
 | ||||||
|     const matcher = new MatchDecorator({ |     constructor(public view: EditorView) { | ||||||
|         regexp: regex, |         this.parsedMatches = []; | ||||||
|         decoration: searchMatchDecoration, |         this.currentFound = 0; | ||||||
|     }); |         this.totalFound = 0; | ||||||
|  |         this.matches = (new RangeSetBuilder<Decoration>()).finish(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return ViewPlugin.fromClass(class SearchHighlighter { |     searchFor(searchTerm: string, matchCase: boolean, wholeWord: boolean) { | ||||||
|         matches!: RangeSet<Decoration>; |         // Escape the search term for use in RegExp
 | ||||||
|         currentFound: number; |         const escapedTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | ||||||
|         totalFound: number; |         const wordBoundary = wholeWord ? "\\b" : ""; | ||||||
|         private parsedMatches: Match[]; |         const flags = matchCase ? "g" : "gi"; | ||||||
|  |         const regex = new RegExp(`${wordBoundary}${escapedTerm}${wordBoundary}`, flags); | ||||||
| 
 | 
 | ||||||
|         constructor(public view: EditorView) { |         this.matcher = new MatchDecorator({ | ||||||
|             this.parsedMatches = []; |             regexp: regex, | ||||||
|             this.currentFound = 0; |             decoration: searchMatchDecoration, | ||||||
|             this.totalFound = 0; |         }); | ||||||
|             this.updateSearchData(view); |         this.updateSearchData(this.view); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     updateSearchData(view: EditorView) { | ||||||
|  |         if (!this.matcher) { | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         updateSearchData(view: EditorView) { |         const matches = this.matcher.createDeco(view); | ||||||
|             const matches = matcher.createDeco(view); |         const cursor = matches.iter(); | ||||||
|             const cursor = matches.iter(); |         while (cursor.value) { | ||||||
|             while (cursor.value) { |             this.parsedMatches.push({ | ||||||
|                 this.parsedMatches.push({ |                 from: cursor.from, | ||||||
|                     from: cursor.from, |                 to: cursor.to | ||||||
|                     to: cursor.to |             }); | ||||||
|                 }); |             cursor.next(); | ||||||
|                 cursor.next(); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             this.matches = matches; |  | ||||||
|             this.totalFound = this.parsedMatches.length; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         update(update: ViewUpdate) { |         this.matches = matches; | ||||||
|             if (update.docChanged || update.viewportChanged) { |         this.totalFound = this.parsedMatches.length; | ||||||
|                 this.updateSearchData(update.view); |     } | ||||||
|             } | 
 | ||||||
|  |     update(update: ViewUpdate) { | ||||||
|  |         if (update.docChanged || update.viewportChanged) { | ||||||
|  |             this.updateSearchData(update.view); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     scrollToMatch(matchIndex: number) { | ||||||
|  |         if (this.parsedMatches.length <= matchIndex) { | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         scrollToMatch(matchIndex: number) { |         const match = this.parsedMatches[matchIndex]; | ||||||
|             if (this.parsedMatches.length <= matchIndex) { |         this.currentFound = matchIndex + 1; | ||||||
|  |         this.view.dispatch({ | ||||||
|  |             effects: EditorView.scrollIntoView(match.from, { y: "center" }), | ||||||
|  |             scrollIntoView: true | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     scrollToMatchNearestSelection() { | ||||||
|  |         const cursorPos = this.view.state.selection.main.head; | ||||||
|  |         let index = 0; | ||||||
|  |         for (const match of this.parsedMatches) { | ||||||
|  |             if (match.from >= cursorPos) { | ||||||
|  |                 this.scrollToMatch(index); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const match = this.parsedMatches[matchIndex]; |             index++; | ||||||
|             this.currentFound = matchIndex + 1; |  | ||||||
|             this.view.dispatch({ |  | ||||||
|                 effects: EditorView.scrollIntoView(match.from, { y: "center" }), |  | ||||||
|                 scrollIntoView: true |  | ||||||
|             }); |  | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         scrollToMatchNearestSelection() { |     destroy() { | ||||||
|             const cursorPos = this.view.state.selection.main.head; |         // Do nothing.
 | ||||||
|             let index = 0; |     } | ||||||
|             for (const match of this.parsedMatches) { |  | ||||||
|                 if (match.from >= cursorPos) { |  | ||||||
|                     this.scrollToMatch(index); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
| 
 | 
 | ||||||
|                 index++; |     static deco = (v: SearchHighlighter) => v.matches; | ||||||
|             } | } | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         destroy() { | export function createSearchHighlighter() { | ||||||
|             // Do nothing.
 |     return ViewPlugin.fromClass(SearchHighlighter, { | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         static deco = (v: SearchHighlighter) => v.matches; |  | ||||||
|     }, { |  | ||||||
|         decorations: v => v.matches, |         decorations: v => v.matches, | ||||||
|         provide: (plugin) => plugin |         provide: (plugin) => plugin | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| export const searchMatchHighlightTheme = EditorView.baseTheme({ | export const searchMatchHighlightTheme = EditorView.baseTheme({ | ||||||
|     ".cm-searchMatch": { |     ".cm-searchMatch": { | ||||||
|         backgroundColor: "rgba(255, 255, 0, 0.4)", |         backgroundColor: "rgba(255, 255, 0, 0.4)", | ||||||
|  | |||||||
| @ -172,7 +172,7 @@ export default class CodeMirror extends EditorView { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async performFind(searchTerm: string, matchCase: boolean, wholeWord: boolean) { |     async performFind(searchTerm: string, matchCase: boolean, wholeWord: boolean) { | ||||||
|         const plugin = createSearchHighlighter(this, searchTerm, matchCase, wholeWord); |         const plugin = createSearchHighlighter(); | ||||||
|         this.dispatch({ |         this.dispatch({ | ||||||
|             effects: this.searchHighlightCompartment.reconfigure(plugin) |             effects: this.searchHighlightCompartment.reconfigure(plugin) | ||||||
|         }); |         }); | ||||||
| @ -180,6 +180,7 @@ export default class CodeMirror extends EditorView { | |||||||
|         // Wait for the plugin to activate in the next render cycle
 |         // Wait for the plugin to activate in the next render cycle
 | ||||||
|         await new Promise(requestAnimationFrame); |         await new Promise(requestAnimationFrame); | ||||||
|         const instance = this.plugin(plugin); |         const instance = this.plugin(plugin); | ||||||
|  |         instance?.searchFor(searchTerm, matchCase, wholeWord); | ||||||
|         if (instance) { |         if (instance) { | ||||||
|             instance.scrollToMatchNearestSelection(); |             instance.scrollToMatchNearestSelection(); | ||||||
|         } |         } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran