diff --git a/src/components/NotePage/NotePage.tsx b/src/components/NotePage/NotePage.tsx index ba7a4feef7..4671061487 100644 --- a/src/components/NotePage/NotePage.tsx +++ b/src/components/NotePage/NotePage.tsx @@ -18,6 +18,7 @@ import { useGeneralStatus } from '../../lib/generalStatus' import { useDialog, DialogIconTypes } from '../../lib/dialog' import FileDropZone from '../atoms/FileDropZone' import { convertCSONFileToNote } from '../../lib/legacy-import' +import { escapeRegExp } from '../../lib/regex' export const StyledNoteDetailNoNote = styled.div` text-align: center; @@ -81,7 +82,7 @@ export default () => { const filteredNotes = useMemo(() => { if (search.trim() === '') return notes - const regex = new RegExp(search, 'i') + const regex = new RegExp(escapeRegExp(search), 'i') return notes.filter( note => note.tags.join().match(regex) || diff --git a/src/components/atoms/HighlightText.tsx b/src/components/atoms/HighlightText.tsx index ca891b9e99..a79d4ae208 100644 --- a/src/components/atoms/HighlightText.tsx +++ b/src/components/atoms/HighlightText.tsx @@ -1,5 +1,6 @@ import React, { useMemo } from 'react' import styled from '../../lib/styled' +import { escapeRegExp } from '../../lib/regex' const HighlightContainer = styled.span` .highlighted { @@ -16,7 +17,7 @@ function HighlightText(props: HighlightTextProps) { const { text, search } = props return useMemo(() => { if (search.trim() === '') return <>{text} - const searchRegex = new RegExp(`(${search})`, 'gi') + const searchRegex = new RegExp(`(${escapeRegExp(search)})`, 'gi') const parts = text.split(searchRegex) return ( diff --git a/src/lib/regex.ts b/src/lib/regex.ts new file mode 100644 index 0000000000..f26ae014b7 --- /dev/null +++ b/src/lib/regex.ts @@ -0,0 +1,3 @@ +export function escapeRegExp(str: string) { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') +}