作为自定义所见即所得编辑器的一部分,我们被要求在启用时实现自动表情符号解析。为此,我们使用正则表达式将字符组合替换为其关联的 PNG 文件。
这是处理此代码的相关部分(它由 contenteditable
元素上的 onkeyup
事件触发;我已将其 trim 回相关部分):
// Parse emjoi:
this.parseEmoji = function()
{
if( ! this.settings.parseSmileys )
{
return;
}
var _self = this,
url = 'http://cdn.jsdelivr.net/emojione/assets/png/',
$html = this.$editor.html();
// Loop through:
for( var i in _self.emoji )
{
var re = new RegExp( '\\B' + _self.regexpEscape(i) + '\\B', 'g' ),
em = _self.emoji[i];
if( re.test($html) )
{
var replace = '<img class="lw-emoji" height="16" src="'+(url + em[0] + '.png')+'" alt="'+em[1]+'" />';
this.insertAtCaret( replace );
_self.$editor.html(function() { return $(this).html().replace(re, ''); });
}
}
};
这里是 regexpEscape()
函数:
// Escape a string so that it's RegExp safe!
this.regexpEscape = function( txt )
{
return txt.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};
我们将系统中使用的所有表情符号定义在一个对象中,该对象由字符组合本身引用,如下所示:
this.emoji = {
':)' : [ '1F642', 'Smiling face' ],
':-)' : [ '1F642', 'Smiling face' ],
':D' : [ '1F601', 'Happy face' ],
':-D' : [ '1F601', 'Happy face' ],
':\'(': [ '1F622', 'Crying face' ],
':(' : [ '1F614', 'Sad face' ],
':-(' : [ '1F614', 'Sad face' ],
':P' : [ '1F61B', 'Cheeky' ],
':-P' : [ '1F61B', 'Cheeky' ],
':/' : [ '1F615', 'Unsure face' ],
':-/' : [ '1F615', 'Unsure face' ],
'B)' : [ '1F60E', 'Too cool face' ],
'B-)' : [ '1F60E', 'Too cool face' ]
};
现在,奇怪的是,任何包含字母字符的字符组合都不会被替换,并且无法通过 re.test()
函数。例如::)
、:-)
、:(
和 :'(
都可以毫无问题地被替换。但是,:D
和 B)
没有。
谁能解释为什么字母字符会导致 RegExp 内部出现问题?
最佳答案
问题是 \B
是上下文相关的,如果有一个单词字符开始模式,一个单词字符必须在输入字符串中出现在它之前才能匹配。同样的方式在模式的末尾,\B
在模式的末尾将要求相同类型的符号紧随其后出现。
为避免该问题,通常使用基于环视的解决方案:(?<!\w)YOUR_PATTERN(?!\w)
.但是,在 JS 中,不支持后视。它可以在稍后的替换函数中使用捕获组和反向引用来解决。
因此,要正确替换这些案例,您需要将那部分代码更改为
var re = new RegExp( '(^|\\W)' + _self.regexpEscape(i) + '(?!\\w)' ),
em = _self.emoji[i]; // match the pattern when not preceded and not followed by a word character
if( re.test($html) )
{
var replace = '<img class="lw-emoji" height="16" src="'+(url + em[0] + '.png')+'" alt="'+em[1]+'" />';
this.insertAtCaret( replace );
_self.$editor.html(function() { return $(this).html().replace(re, '$1'); }); // restore the matched symbol (the one \W matched) with $1
}
这是 updated fiddle .
关于javascript - JS RegExp 不适用于字母字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34265871/