我有一个使用Twitter消息的网络应用程序,例如。
JSON的提要用于构建消息列表,但字符显示为菱形中的问号。元素如下所示:
<div class="inner-message" ng-bind-html="unit.caption_text | linky:'_blank'"></div>
当我在Firefox和Chrome中查看JSON网址时,这些显示正常。
头部样本:
<!DOCTYPE html>
<html class="wf-opensans-n4-active wf-active" lang="en">
<head>
<meta charset="utf-8">
我在调试时发现了一件事:当消息都在一个对象数组中,但不是$ scope的一部分时,我可以将它们添加到页面中,并且表情符号显示正确。
所以我认为在Angular中会发生这样的事情。我尝试将ng-bind-html更改为ng-bind,但是并没有这样做。我尝试删除ng-bind-html并在元素中使用{{unit.caption_text}},但它仍会破坏unicode字符。
目前,我需要能够使用linky过滤器来正确显示链接,因此必须使用ng-bind-html,但我不相信这是问题。
javascript中是否发生了破坏编码的事情?
有没有办法让它们正确显示?
这会根据需要显示图标,但是&#34; linky&#34;不会为链接添加格式。
<div class="inner-message">{{unit.text}}</div>
这显示了破碎的字符
<div class="inner-message" ng-bind-html="unit.text | linky:'_blank'"></div>
最后到达那里,按照Michael链接的Pull Request中的详细说明进行更改,以阻止角色搞砸。
如果我将Symbola添加到这些消息的字体堆栈中,我还发现它有助于保持一致性。您可以从this page by George Douros下载Symbola。我通过.ttf到.woff转换器运行它以获得稍微更好的浏览器支持,提供两种选择。
答案 0 :(得分:7)
注意:此帖子未在Chrome上显示,因为它不支持表情符号
看起来Angular的$sanitize
服务尝试将字符转换为其HTML实体等效字符。但是,对于某些单个表情符号字符,它会将其拆分为2.可以在http://plnkr.co/edit/fDDen3bnnrQUvx3JfKgw?p=preview处看到,
$scope.sanitizedText = $sanitize('');
在模板中输出
{{sanitizedText}}
显示��
。为什么?我不知道。
这意味着使用$sanitize
的任何内容都会有效地破坏这些字符。这包括
ng-bind-html
$sce.trustAsHtml
传递的任何内容,如linky source所示,都会调用linky
。因此,只要
,就可以避免HTML通过$sanitize
$sanitize
输入。示例过滤器如下:
$sanitize
可以用作
app.filter('unsafeLinky', function($sce) {
// Regex from https://github.com/angular/angular.js/blob/master/src/ngSanitize/filter/linky.js#L5
var urlRegex = /(((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>])/gi;
return function(input, target) {
var targetHTML = target ? ' target="' + target + '"' : '';
return $sce.trustAsHtml(input.replace(urlRegex,'<a href="$1"' + targetHTML + '>$1</a>'));
}
});
您可以在http://plnkr.co/edit/sRJmt4YVO8udJInCd4Cy?p=preview
看到此演示正如名称所示,此unsafeLinky过滤器不安全。请务必相信原始文本的来源。
正如本回答开头所建议的,Chrome doesn't display Emoji characters properly。要获取Chrome中显示的字符,您可能必须使用某种图像替换。无论如何,我怀疑这超出了这个特定问题的范围。
<强>更新强>
Angular有PR可以解决这个问题,一旦合并完成就不需要上述解决办法:https://github.com/angular/angular.js/pull/6911
答案 1 :(得分:1)
我发现上面的正则表达式打破了一些网址,例如bit.yl短链接,所以我改编了另一个我在某处找到的例子:
twitterApp.filter('parseUrl', function($sce) {
var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/gi;
return function(text) {
angular.forEach(text.match(urlPattern), function(url) {
text = text.replace(url, "<a target=\"_blank\" href="+ url + ">" + url +"</a>");
});
return $sce.trustAsHtml(text);
};
});
用法:
<p ng-bind-html="tweet.text | parseUrl"></p>