33import { EditorView , Decoration , DecorationSet , ViewUpdate , ViewPlugin } from '@codemirror/view' ;
44import { RangeSetBuilder } from '@codemirror/state' ;
55import type OccuraPlugin from 'main' ;
6+ import { MarkdownView , Notice } from "obsidian" ;
67
78// Create a decoration for highlighting
89export const highlightDecoration = Decoration . mark ( { class : 'found-occurrence' } ) ;
@@ -82,3 +83,116 @@ export function highlightOccurrenceExtension(plugin: OccuraPlugin) {
8283 ) ;
8384
8485}
86+
87+ //region set/remove permanent highlighting
88+ export function setHighlightOccurrences ( context :any ) {
89+ const activeView = context . app . workspace . getActiveViewOfType ( MarkdownView ) ;
90+ if ( ! activeView ) {
91+ new Notice ( 'No active editor' ) ;
92+ return ;
93+ }
94+
95+ const editor = activeView . editor ;
96+ const selectedText = editor . getSelection ( ) . trim ( ) ;
97+
98+ if ( ! selectedText || / \s / . test ( selectedText ) ) {
99+ new Notice ( 'Please select some text to highlight.' ) ;
100+ return ;
101+ }
102+
103+ // Escape regex special characters
104+ const escapedText = selectedText . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ;
105+ const regex = new RegExp ( escapedText , 'g' ) ;
106+
107+ const docText = editor . getValue ( ) ;
108+ const matches : { from : number ; to : number } [ ] = [ ] ;
109+
110+ let match ;
111+ while ( ( match = regex . exec ( docText ) ) !== null ) {
112+ matches . push ( { from : match . index , to : match . index + match [ 0 ] . length } ) ;
113+ }
114+
115+ if ( matches . length === 0 ) {
116+ new Notice ( 'No occurrences found.' ) ;
117+ return ;
118+ }
119+
120+ // Access the underlying EditorView
121+ const editorView = ( editor as any ) . cm as EditorView ;
122+ if ( ! editorView ) {
123+ new Notice ( 'Cannot access the editor view.' ) ;
124+ return ;
125+ }
126+
127+ // Prepare changes
128+ const changes = matches . reverse ( ) . map ( range => ( {
129+ from : range . from ,
130+ to : range . to ,
131+ insert : `==${ docText . slice ( range . from , range . to ) } ==` ,
132+ } ) ) ;
133+
134+ // Apply all changes in a single transaction
135+ editorView . dispatch ( {
136+ changes,
137+ } ) ;
138+
139+ new Notice ( `Permanently highlighted ${ matches . length } for ${ selectedText } occurrences.` ) ;
140+ }
141+ export function removeHighlightOccurrences ( context :any ) {
142+ const activeView = context . app . workspace . getActiveViewOfType ( MarkdownView ) ;
143+ if ( ! activeView ) {
144+ new Notice ( 'No active editor' ) ;
145+ return ;
146+ }
147+
148+ const editor = activeView . editor ;
149+ const selectedText = editor . getSelection ( ) . trim ( ) ;
150+
151+ if ( ! selectedText || / \s / . test ( selectedText ) ) {
152+ new Notice ( 'Please select some text to remove highlighting from.' ) ;
153+ return ;
154+ }
155+
156+ // Construct the search pattern to find ==selectedText==
157+ const escapedText = selectedText . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ;
158+ const pattern = `==${ escapedText } ==` ;
159+ const regex = new RegExp ( pattern , 'g' ) ;
160+
161+ const docText = editor . getValue ( ) ;
162+ const matches : { from : number ; to : number } [ ] = [ ] ;
163+
164+ let match ;
165+ while ( ( match = regex . exec ( docText ) ) !== null ) {
166+ matches . push ( { from : match . index , to : match . index + match [ 0 ] . length } ) ;
167+ }
168+
169+ if ( matches . length === 0 ) {
170+ new Notice ( 'No highlighted occurrences found.' ) ;
171+ return ;
172+ }
173+
174+ // Access the underlying EditorView
175+ const editorView = ( editor as any ) . cm as EditorView ;
176+ if ( ! editorView ) {
177+ new Notice ( 'Cannot access the editor view.' ) ;
178+ return ;
179+ }
180+
181+ // Prepare changes
182+ const changes = matches . reverse ( ) . map ( range => {
183+ const originalText = docText . slice ( range . from + 2 , range . to - 2 ) ; // Remove the '==' from both ends
184+ return {
185+ from : range . from ,
186+ to : range . to ,
187+ insert : originalText ,
188+ } ;
189+ } ) ;
190+
191+ // Apply all changes in a single transaction
192+ editorView . dispatch ( {
193+ changes,
194+ } ) ;
195+
196+ new Notice ( `Removed highlighting from ${ matches . length } occurrences of ${ selectedText } .` ) ;
197+ }
198+ //endregion
0 commit comments