@@ -29,6 +29,7 @@ const {
2929 isEmpty,
3030 selectedSnippetIds,
3131 isAvailableToCodePreview,
32+ searchQuery,
3233} = useSnippets ()
3334const {
3435 isShowMarkdown,
@@ -43,6 +44,7 @@ const { addToUpdateContentQueue } = useSnippetUpdate()
4344
4445const isDark = useDark ()
4546let editor: CodeMirror .Editor | null = null
47+ let currentSearchOverlay: any = null
4648
4749const isProgrammaticChange = ref (false )
4850
@@ -208,6 +210,11 @@ async function init() {
208210 watch (selectedSnippetContent , (v ) => {
209211 nextTick (() => {
210212 setValue (v ?.value || ' ' )
213+ nextTick (() => {
214+ if (searchQuery .value ) {
215+ updateSearchOverlay ()
216+ }
217+ })
211218 })
212219 })
213220
@@ -328,8 +335,72 @@ function onSplitterLayout() {
328335 editor ?.refresh ()
329336}
330337
338+ function createSearchOverlay(query : string ) {
339+ if (! query )
340+ return null
341+
342+ let regexp: RegExp
343+
344+ try {
345+ regexp = new RegExp (query .replace (/ [. *+?^${}()|[\]\\ ] / g , ' \\ $&' ), ' gi' )
346+ }
347+ catch {
348+ return null
349+ }
350+
351+ return {
352+ token : (stream : any ) => {
353+ regexp .lastIndex = stream .pos
354+ const match = regexp .exec (stream .string )
355+ if (match && match .index === stream .pos ) {
356+ stream .pos += match [0 ].length
357+ return ' searching'
358+ }
359+ else if (match ) {
360+ stream .pos = match .index
361+ }
362+ else {
363+ stream .skipToEnd ()
364+ }
365+ },
366+ }
367+ }
368+
369+ function updateSearchOverlay() {
370+ if (! editor )
371+ return
372+
373+ if (currentSearchOverlay ) {
374+ editor .removeOverlay (currentSearchOverlay )
375+ currentSearchOverlay = null
376+ }
377+
378+ if (searchQuery .value ) {
379+ currentSearchOverlay = createSearchOverlay (searchQuery .value )
380+ if (currentSearchOverlay ) {
381+ editor .addOverlay (currentSearchOverlay )
382+
383+ // Scroll to the first match
384+ const cursor = editor .getSearchCursor (
385+ searchQuery .value ,
386+ { line: 0 , ch: 0 },
387+ true ,
388+ )
389+ if (cursor .findNext ()) {
390+ editor .scrollIntoView (cursor .from (), 50 )
391+ }
392+ }
393+ }
394+ }
395+
331396onMounted (() => {
332397 init ()
398+
399+ watch (searchQuery , () => {
400+ nextTick (() => {
401+ updateSearchOverlay ()
402+ })
403+ })
333404})
334405 </script >
335406
@@ -430,4 +501,10 @@ onMounted(() => {
430501.CodeMirror-scrollbar-filler {
431502 background-color : transparent ;
432503}
504+
505+ .CodeMirror .cm-searching {
506+ background-color : var (--color-text-highlight );
507+ color : black !important ;
508+ border-radius : 2px ;
509+ }
433510 </style >
0 commit comments