如何解决highlight-text-inside-a-textarea匹配带重音关键词时的半高亮正则问题
textarea关键词高亮插件重音字符匹配异常问题
使用highlight-text-inside-a-textarea插件时,基础高亮功能可正常运行,但处理带重音字符的外语单词时存在匹配偏差。
- 预设待高亮关键词数组为:
$kw = array("excel","Réseau","R","electrom"); - 实际测试中,完整外文单词
electromécanique仅前缀electrom被高亮,出现不符合预期的半高亮效果 - 初步推断异常根源为JS正则表达式的逻辑缺陷
异常效果示意:
完整测试代码如下:
<!DOCTYPE html> <html> <head> <title>Page Title</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="/jquery/highlight-within-textarea.js"></script> <link rel="stylesheet" type="text/css" href="/jquery/highlight-within-textarea.css"/> </style> </head> <body> <h1>Highlighted Keywords Test</h1> <div id="job"> <textarea cols="50" rows="5">excel Réseau Robert electromécanique R electromecanique</textarea></div> <?php $kw = array("excel","Réseau","R","electrom"); foreach($kw as $kws) { $keywords_highlight[] = $kws; } ?> <script> var arrHighlight = <?php echo json_encode($keywords_highlight); ?>; function escapeRegExp(arrHighlight) { return arrHighlight.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& 表示完整匹配的字符串 } var pattern = new RegExp("(?<![\\w-])(?:" + arrHighlight.map(escapeRegExp).join("|") + ")(?![\\w-])", "gi"); $('textarea').highlightWithinTextarea({ highlight: pattern }); </script> </body> </html>
问题根源
当前正则逻辑使用\w实现单词边界判定,而JS原生的\w仅能匹配ASCII范围内的字符(即[a-zA-Z0-9_]),无法识别带重音的拉丁字母(如é、è、à等)。
当正则匹配到关键词electrom时,后续紧跟的é不属于\w的匹配范围,导致负向环视判定为“关键词后没有连接单词字符”,提前触发匹配,最终出现半高亮的错误效果。
解决方案
不再依赖原生\w做单词边界判定,改用Unicode属性匹配显式定义单词组成字符范围,覆盖所有带重音的拉丁字母:
- 将原本用于判定单词边界的
\w,替换为可匹配所有Unicode字母、数字的类\\p{L}\\p{N}_- - 为正则增加
u(Unicode)修饰符,启用非ASCII字符的匹配规则
调整后的核心JS代码:
var arrHighlight = <?php echo json_encode($keywords_highlight); ?>; function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& 表示完整匹配的字符串 } // 定义可匹配所有Unicode单词字符的类,覆盖重音字符 const wordBoundaryChar = "\\p{L}\\p{N}_-"; const pattern = new RegExp( `(?<![${wordBoundaryChar}])(?:${arrHighlight.map(escapeRegExp).join("|")})(?![${wordBoundaryChar}])`, "giu" // 新增u修饰符启用Unicode匹配能力 ); $('textarea').highlightWithinTextarea({ highlight: pattern });
调整后可实现的匹配效果:
- 内嵌在长外文单词中的
electrom(如electromécanique)不会触发误匹配,彻底解决半高亮问题 - 独立存在的关键词(如和其他字符用空格、符号分隔的
electrom)可正常触发高亮 - 带重音的关键词(如
Réseau)可正确匹配对应完整单词,不会出现边界判定偏差
内容的提问来源于stack exchange,提问作者Seb
相关产品推荐
相关产品推荐

