我有一堆推文以普通文本形式返回,我希望根据RegEx匹配分配正确的链接标记。
这里有一条推文,我希望@Bundlehunt
成为<a href="http://twitter.com/bundlehunt">@Bundlehunt</a>
,http://bundlehunt.com
成为<a href="http://bundlehunt.com">http://bundlehunt.com</a>
。
示例推文:
joined @BundleHunt for a chance to win the 2010 Mega Bundle!
http://bundlehunt.com * Only 10 Days Left!
听起来很简单我以为我使用了优秀的http://www.gskinner.com/RegExr/工具来查找以下2个与我的推文中的内容匹配的RegEx模式:
@twittername = /@(\w.+?)(?=\s)/gi
@links = /http:\/\/(.*)\.([a-zA-Z\.]){2,3}/gi
现在回到我的jQuery文档中,我正在尝试浏览文本并匹配RegEx,但这就是我迷失的地方......
我如何实际匹配纯文本,绕着锚标签并将匹配的文本插入正确的锚标签?
感谢阅读,
Jannis
答案 0 :(得分:1)
如果您在不受信任的输入上使用jQuery的.html()方法,那么您的Web应用程序将容易受到跨站点脚本(XSS)攻击,这种攻击可以通过发布恶意推文来利用。避免此安全问题的最佳方法是使用正确的jQuery函数单独附加推文的每个部分,这些函数使用Web浏览器的DOM函数转换为HTML转义字符串。
首先,使用正则表达式替换(|
符号)将两个正则表达式合并为一个。出于我的示例代码的目的,Twitter用户名正则表达式为/@\w+/gi
,URL正则表达式为/(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi
这些正则表达式与原始问题中的正则表达式不同;原始URL正则表达式似乎无法正常工作,我们不需要使用捕获组。因此,合并的正则表达式为/@\w+|(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi
。
每次正则表达式匹配时,请将匹配前的文本安全地添加到容器中。要在jQuery中执行此操作,请创建一个空的“span”元素,并使用.text()方法在其中插入文本。使用$('text here')会使XSS孔敞开。如果推文内容为<script>alert(document.cookie)</script>
?
检查匹配的第一个字符以确定如何格式化。 Twitter用户名以“@”开头,但URL不能。
格式化匹配并将其添加到容器中。同样,不要将不受信任的输入传递给$或jQuery函数;使用.attr()方法添加href和.text()方法等属性来添加链接文本。
处理完所有匹配后,添加推文的最后一个纯文本部分,该部分尚未在步骤3或4中添加。
示例代码(也在http://jsfiddle.net/6X6xD/3/):
var tweet = 'joined @BundleHunt for a chance to win the 2010 Mega Bundle! http://bundlehunt.com * Only 10 Days Left! URL containing an at sign: http://www.last.fm/event/1196311+Live+@+Public+Assembly. This should not work: <scr'+'ipt>alert(document.cookie)</scr'+'ipt>';
var combinedRegex = /@\w+|(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi,
container = $('#tweet-container');
var result, prevLastIndex = 0;
combinedRegex.lastIndex = 0;
while((result = combinedRegex.exec(tweet))) {
// Append the text coming before the matched entity
container.append($('<span/>').text(tweet.slice(prevLastIndex, result.index)));
if(result[0].slice(0, 1) == "@") {
// Twitter username was matched
container.append($('<a/>')
// .slice(1) cuts off the first character (i.e. "@")
.attr('href', 'http://twitter.com/' + encodeURIComponent(result[0].slice(1)))
.text(result[0])
);
} else {
// URL was matched
container.append($('<a/>')
.attr('href', result[0])
.text(result[0])
);
}
// prevLastIndex will point to the next plain text character to be added
prevLastIndex = combinedRegex.lastIndex;
}
// Append last plain text part of tweet
container.append($('<span/>').text(tweet.slice(prevLastIndex)));
注意:此答案的旧版本确实建议使用.html()方法。因为这是一个严重的安全问题,如上所述,我使用编辑按钮发布我的新答案,从视图中删除旧答案。
答案 1 :(得分:1)
最简单的方法是使用replace
String
的{{1}}方法:
Object
请参阅此处了解文档:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace。
另一方面,如果你的字符串包含多个与正则表达式匹配的子字符串,则必须在循环中运行它,因为处理捕获组,即parens中的部分在JavaScript中很糟糕。