I am working on a scenario where I want to highlight words or parts of words that people search for. I have a function called addMarks
that wraps the searched word in the <mark>
tag. Of course, this search needs to be case-insensitive, but more than that, it also needs to ignore accents.
Using the function .normalize('NFD').replace(/p{Diacritic}/gu, '')
, I am able to perform searches that ignore accents. However, I am struggling to wrap the searched word in the <mark>
tag correctly.
For example, if someone searches for “éner”, the highlighting works as expected. But when searching for “ener” (without the accent), the highlighting does not work.
My question: How can I modify the code so that the <mark>
tag wraps the search term correctly even when accents are missing ? For instance, if someone searches “ener” instead of “éner”, the highlight should still work.
Thanks in advance for your help!
Here also the MRE
const search = 'éner';
function escapeRegExp(s) {
return s.replace(/[.*+?^${}()|[]\]/g, '\$&');
}
function addMarks(liItem, q) {
if (liItem.textContent.toLowerCase().normalize('NFD').replace(/p{Diacritic}/gu, '').includes(q.toLowerCase().normalize('NFD').replace(/p{Diacritic}/gu, ''))) {
liItem.innerHTML = liItem.innerHTML.replace(
new RegExp(
`(>[^<>]*)(${escapeRegExp(q)})([^<>]*<)`,
'gi',
),
'$1<mark>$2</mark>$3',
);
}
}
for (const liItem of document.querySelectorAll('li')) {
addMarks(liItem, search);
}
<ul>
<li>
<article>
<h2>Mot avec accent : <b>énergie</b></h2>
<p>L'importance de l'<dfn>énergie</dfn> renouvelable ne cesse de croître dans le monde moderne.</p>
</article>
</li>
<li>
<article>
<h2>Expression avec caractères spéciaux : <b>Ça va ?</b></h2>
<p>En français, <dfn>ça va ?</dfn> est une façon courante de demander des nouvelles.</p>
</article>
</li>
<li>
<article>
<h2>Proverbe français : <b>À cœur vaillant rien d'impossible</b></h2>
<p>Ce proverbe met en avant la détermination face aux défis :À cœur vaillant rien d'impossible.</p>
</article>
</li>
</ul>