Reputation: 697
Im trying to highlight some text on my web page as the user types in the search box. My search algo is simply matching each space separated keyword. I thought this function was perfect until I started adding brackets to my search term. That kicks up SyntaxError: Invalid regular expression: ****: Unterminated group" as its getting interpreted by the regex. Ive tried to escape the brackets and other characters but then the highlighting isn't working.
https://codepen.io/anon/pen/YOaYEv
highlight (str) {
// this line works but prevents highlighting multiple keywords that arent connected
// var replacedStr = (this.search || '').replace(/[-[\]{}()*+!<=:?.\\^$|#\s,]/g, '\\$&')
// you can comment this line and uncomment above to see a different but not perfect option
var replacedStr = (this.search || '').replace(/ /g, '|')
return str.replace(new RegExp(replacedStr, 'gi'), match => {
return '<span class="font-weight-bold">' + match + '</span>'
})
}
So i need to escape the brackets. Which ive tried in the commented line but then the function fails to highlight all keywords in the text :/
Any ideas?
Upvotes: 1
Views: 940
Reputation: 627101
You need to escape each non-whitespace chunk you want to search for and highlight. Also, there is no need to use a callback inside replace
to replace with a whole match, you may use a $&
backreference.
See the updated JS:
vm = new Vue({
el: "#app",
data() {
return {
search: null,
message: 'Search this text for matches (check the bracketed area too)'
};
},
computed: {},
methods: {
highlight (str) {
var replacedStr = (this.search || '').trim().split(/\s+/).map(x => x.replace(/[-[\]{}()*+!<=:?.\\^$|#\s,]/g, '\\$&')).join("|");
return str.replace(new RegExp(replacedStr, 'gi'),
'<span class="teal--text text--darken-1 font-weight-bold">$&</span>');
}
}
});
Here:
.trim().split(/\s+/).map(x => x.replace(/[-[\]{}()*+!<=:?.\\^$|#\s,]/g, '\\$&')).join("|")
- trims the input string with trim()
, then splits out all non-whitespace chunks with .split(/\s+/)
, then these chunks are escaped with .map(x => x.replace(/[-[\]{}()*+!<=:?.\\^$|#\s,]/g, '\\$&'))
, and then .join("|")
creates a regex pattern with a list of alternatives.'<span class="teal--text text--darken-1 font-weight-bold">$&</span>'
string replacement pattern, the $&
parts stands for the whole match value.Upvotes: 1