AngularJSでngBindHtmlを使用すると、ngSanitize(angular-sanitize.js)のencodeEntitiesに行き着く(はず)。そこでは下記のような処理が行われています。
1 | function encodeEntities(value) { |
NON_ALPHANUMERIC_REGEXPは、/([^\#-~| |!])/g;でマッチした値。文字列はこの処理を通る感じになる。charCodeAtの処理はcharCodeAt - MDNを参照。
Note that charCodeAt will always return a value that is less than 65,536. This is because the higher code points are represented by a pair of (lower valued) “surrogate” pseudo-characters which are used to comprise the real character.
charCodeAtはつねに65,536以下の値が返ってくるようになっていて、それ以上のコードポイントの場合は、サロゲートペアの状態になってくる。サロゲートペアについては、サロゲートペア入門の「サロゲートペアとは?」を参照。
なので、ngBindHtmlで絵文字のように65,356以上のコードポイントを持ってそうな文字列を通すと、サロゲートペアをひとつずつ実体参照の状態にしてしまい、うまく表示できない。
ngBindHtmlでそのような文字列を表示するためには、なんとかしないといけない。それでとりあえずeller86/surrogate-pair.jsを使ってsurrogate pairを処理するように対応。
1 | function handleSurrogatePair(content){ |
$sceはStrict Contextual Escaping services to AngularJSを参照。対処療法に過ぎないので、あんまりいい感じではないけど、一応表示できるようになる。
そもそも、ngSanitizeでsurrogate pairを適切に処理するようにpull requestを作るべきなんだろうなあと思いつつ、そこまでいたってない。そして基本的には、ngBindHtmlを使わずにngBindだけでうまく設計する方がいい。ngSanitizeの処理量半端ない。
というメモ。走り書き。
ngSanitize cant escape all unicode characters ? Issue #5088 ? angular/angular.jsに関連issueがあった。
fix(ngSanitize): encode surrogate pair properly by memolog ? Pull Request #6911 ? angular/angular.jsでPull Requestを送って、1.3.xではサロゲートペアに対する処理が追加されました。ので、絵文字表示できない問題は起きない。