JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://epeli.github.io/underscore.string/lib/underscore.string.js"></script>
<h1>Être ou ne pas être, là est la question.</h1>
CSS
span.red {color:red;}
JavaScript
_.mixin(_.str.exports());
normalizeText = function(s){
var r=s.toLowerCase();
r = r.replace(new RegExp("[àáâãäå]", 'g'),"a");
r = r.replace(new RegExp("æ", 'g'),"ae");
r = r.replace(new RegExp("ç", 'g'),"c");
r = r.replace(new RegExp("[èéêë]", 'g'),"e");
r = r.replace(new RegExp("[ìíîï]", 'g'),"i");
r = r.replace(new RegExp("ñ", 'g'),"n");
r = r.replace(new RegExp("[òóôõö]", 'g'),"o");
r = r.replace(new RegExp("œ", 'g'),"oe");
r = r.replace(new RegExp("[ùúûü]", 'g'),"u");
r = r.replace(new RegExp("[ýÿ]", 'g'),"y");
return r;
};
highlight = function(text, pattern) {
var textNorm = normalizeText(text),
terms = pattern.split(/[\s,]+/),
matches = [],
html = text;
// Find matches
_.each(terms, function(term) {
term = _.trim(term);
var termNorm = normalizeText(term),
index = textNorm.indexOf(termNorm);
while (index >= 0) {
matches.push({
index: index,
term: term,
termNorm: termNorm
});
index = textNorm.indexOf(termNorm, index+termNorm.length);
}
});
// Last matches first
matches = _.sortBy(matches, function(match) {return -match.index;});
// Highlight them
_.each(matches, function(match) {
html = html.substring(0, match.index) +
'<span class="red">' +
html.substring(match.index, match.index + match.term.length) +
'</span>' +
html.substring(match.index + match.term.length);
});
return html;
};
$('h1').html(highlight($('h1').text(), 'etre la'));