diff --git a/src/Highlight.js b/src/Highlight.js
new file mode 100644
index 00000000..c306c69d
--- /dev/null
+++ b/src/Highlight.js
@@ -0,0 +1,27 @@
+import React from 'react'
+import { Typography } from '@material-ui/core'
+
+const escapeHtml = unsafe =>
+ unsafe
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''')
+
+const addHighlight = (query, text, className = '') => {
+ if (!text) return ''
+ return escapeHtml(text).replace(
+ new RegExp(query, 'gi'),
+ match => `${match}`,
+ )
+}
+
+export default function Highlight({ query, text, classes = {}, ...props }) {
+ return (
+
+ )
+}
diff --git a/src/search/SearchProvider.js b/src/search/SearchProvider.js
index 689f282e..d121b0d5 100644
--- a/src/search/SearchProvider.js
+++ b/src/search/SearchProvider.js
@@ -46,6 +46,7 @@ export default function SearchProvider({ children, query, initialGroups, active
}, 250)
const context = {
+ query,
state,
setState,
fetchSuggestions,
diff --git a/src/search/SearchSuggestionItem.js b/src/search/SearchSuggestionItem.js
index a0c477ee..ea3ae266 100644
--- a/src/search/SearchSuggestionItem.js
+++ b/src/search/SearchSuggestionItem.js
@@ -1,9 +1,10 @@
-import React from 'react'
+import React, { useContext } from 'react'
import makeStyles from '@material-ui/core/styles/makeStyles'
import Link from '../link/Link'
-import { Typography } from '@material-ui/core'
import PropTypes from 'prop-types'
import Image from '../Image'
+import SearchContext from './SearchContext'
+import Highlight from '../Highlight'
export const styles = theme => ({
root: {
@@ -28,6 +29,12 @@ export const styles = theme => ({
},
},
},
+ text: {},
+ highlight: {
+ backgroundColor: 'rgba(0,0,0,0.05)',
+ borderRadius: '2px',
+ color: theme.palette.secondary.main,
+ },
})
const useStyles = makeStyles(styles, { name: 'RSFSearchSuggestionItem' })
@@ -42,6 +49,8 @@ export default function SearchSuggestionItem({
}) {
classes = useStyles({ classes })
+ const { query } = useContext(SearchContext)
+
return (
@@ -55,7 +64,12 @@ export default function SearchSuggestionItem({
{...thumbnailProps}
{...item.thumbnail}
/>
- {item.text}
+
)}
diff --git a/test/Highlight.test.js b/test/Highlight.test.js
new file mode 100644
index 00000000..0bd89be7
--- /dev/null
+++ b/test/Highlight.test.js
@@ -0,0 +1,25 @@
+import React from 'react'
+import { mount } from 'enzyme'
+import Highlight from 'react-storefront/Highlight'
+
+describe('Highlight', () => {
+ it('should not blow up if empty props', () => {
+ const wrapper = mount()
+ expect(wrapper.text()).toBe('')
+ })
+ it('should not add highlights if no matches', () => {
+ const wrapper = mount()
+ expect(wrapper.text()).toBe('the fox jumps over')
+ })
+ it('should escape text', () => {
+ const wrapper = mount( 'bar' < zat`} />)
+ expect(wrapper.text()).toBe('"foo" > 'bar' < zat')
+ })
+ it('should add highlights to matches', () => {
+ const wrapper = mount(
+ ,
+ )
+ const matches = wrapper.html().match(/ox<\/span>/g)
+ expect(matches.length).toBe(2)
+ })
+})
diff --git a/test/search/SearchSuggestionGroup.test.js b/test/search/SearchSuggestionGroup.test.js
index 2f0c9e47..7a095aea 100644
--- a/test/search/SearchSuggestionGroup.test.js
+++ b/test/search/SearchSuggestionGroup.test.js
@@ -2,6 +2,7 @@ import React from 'react'
import { mount } from 'enzyme'
import SearchSuggestionGroup from 'react-storefront/search/SearchSuggestionGroup'
import SearchSuggestionItem from 'react-storefront/search/SearchSuggestionItem'
+import SearchProvider from 'react-storefront/search/SearchProvider'
import PWAContext from 'react-storefront/PWAContext'
describe('SearchSuggestionGroup', () => {
@@ -13,9 +14,11 @@ describe('SearchSuggestionGroup', () => {
it('should render children when provided', () => {
wrapper = mount(
-
- child
- ,
+
+
+ child
+
+ ,
)
expect(wrapper.find('#child').text()).toBe('child')
@@ -24,7 +27,9 @@ describe('SearchSuggestionGroup', () => {
it('should render suggested items when no children provided', () => {
wrapper = mount(
-
+
+
+
,
)
@@ -32,7 +37,11 @@ describe('SearchSuggestionGroup', () => {
})
it('should render provided caption', () => {
- wrapper = mount()
+ wrapper = mount(
+
+
+ ,
+ )
expect(wrapper.find(SearchSuggestionGroup).text()).toBe('test')
})
diff --git a/test/search/SearchSuggestionItem.test.js b/test/search/SearchSuggestionItem.test.js
index c968bc6d..b38455be 100644
--- a/test/search/SearchSuggestionItem.test.js
+++ b/test/search/SearchSuggestionItem.test.js
@@ -1,5 +1,6 @@
import React from 'react'
import { mount } from 'enzyme'
+import SearchProvider from 'react-storefront/search/SearchProvider'
import SearchSuggestionItem from 'react-storefront/search/SearchSuggestionItem'
import Image from 'react-storefront/Image'
import PWAContext from 'react-storefront/PWAContext'
@@ -14,9 +15,11 @@ describe('SearchSuggestionItem', () => {
it('should render children when provided', () => {
wrapper = mount(
-
- child
-
+
+
+ child
+
+
,
)
@@ -26,7 +29,9 @@ describe('SearchSuggestionItem', () => {
it('should render image with a text when no children provided', () => {
wrapper = mount(
-
+
+
+
,
)
@@ -42,10 +47,12 @@ describe('SearchSuggestionItem', () => {
it('should spread thumbnail props on image', () => {
wrapper = mount(
-
+
+
+
,
)