表情符号和其他unicode字符在Angular中没有正确显示

时间:2014-04-10 16:42:16

标签: angularjs unicode emoji

我有一个使用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>

enter image description here

这显示了破碎的字符

<div class="inner-message" ng-bind-html="unit.text | linky:'_blank'"></div>

enter image description here


更新2

最后到达那里,按照Michael链接的Pull Request中的详细说明进行更改,以阻止角色搞砸。

如果我将Symbola添加到这些消息的字体堆栈中,我还发现它有助于保持一致性。您可以从this page by George Douros下载Symbola。我通过.ttf到.woff转换器运行它以获得稍微更好的浏览器支持,提供两种选择。

2 个答案:

答案 0 :(得分:7)

  

注意:此帖子未在Chrome上显示,因为它不支持表情符号

看起来Angular的$sanitize服务尝试将字符转换为其HTML实体等效字符。但是,对于某些单个表情符号字符,它会将其拆分为2.可以在http://plnkr.co/edit/fDDen3bnnrQUvx3JfKgw?p=preview处看到,

$scope.sanitizedText = $sanitize('');

在模板中输出

{{sanitizedText}}

显示&#55357;&#56904;。为什么?我不知道。

这意味着使用$sanitize的任何内容都会有效地破坏这些字符。这包括

  • 使用{{1>}显示的输出没有经过ng-bind-html
  • 通过$sce.trustAsHtml传递的任何内容,如linky source所示,都会调用linky

因此,只要

就可以避免HTML通过$sanitize
  • 您将字符串传递给$sce.trustAsHtml
  • 你没有通过Angular提供的linky过滤器传递它,但滚动你自己没有$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.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/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>