Unicode文字とエンティティ参照|サロゲートペアと絵文字の扱い
Unicodeのコードポイント空間
Unicodeは U+0000 から U+10FFFF(10進で約110万)の範囲で、世界中の文字を表します。
| 範囲 | 名称 | 主な内容 |
|---|---|---|
| U+0000 - U+007F | ASCII | 英数字・記号 |
| U+0080 - U+00FF | Latin-1 補助 | 欧州言語の記号 |
| U+0100 - U+FFFF | BMP(基本多言語面) | 漢字・かな・ハングル等 |
| U+10000 - U+10FFFF | 補助面 | 絵文字・補助漢字 |
HTMLエンティティ参照では、この全範囲の任意の文字を数値参照で表せます。
1バイトでは足りない
ASCII(U+0000 - U+007F)は7bitで足ります。Latin-1(U+0080 - U+00FF)も8bitで足ります。
しかし:
- BMP(U+0000 - U+FFFF)は16bit
- 全Unicode(U+0000 - U+10FFFF)は21bit
1バイトでは到底足りないため、エンコーディング(UTF-8、UTF-16、UTF-32)が必要です。
UTF-16 とサロゲートペア
JavaScriptの文字列は内部UTF-16で保持されています。BMP内の文字は1コード単位(2バイト)で済みますが、補助面の文字(絵文字など)は サロゲートペア という2つのコード単位の組で表現されます。
サロゲート領域
| 範囲 | 名称 |
|---|---|
| U+D800 - U+DBFF | High surrogate |
| U+DC00 - U+DFFF | Low surrogate |
この領域の単独文字は不正。常にペアで使う前提です。
サロゲートペアの計算
絵文字 😀(U+1F600)をUTF-16で表すと:
codepoint = 0x1F600
high = ((0x1F600 - 0x10000) >> 10) + 0xD800 = 0xD83D
low = ((0x1F600 - 0x10000) & 0x3FF) + 0xDC00 = 0xDE00
→ 😀 という2つのコード単位の組。
HTMLエンティティではサロゲートを使わない
HTMLの数値参照はコードポイントを直接書く形式です:
<!-- 正しい -->
😀
😀
<!-- 不正(サロゲートペアの片割れ) -->
�
�
サロゲートペアの個々の値はHTMLでは書きません。Unicodeコードポイントをそのまま書くのが正解。
HTML特殊文字エスケープツール はサロゲート領域(U+D800 - U+DFFF)の入力をデコード時に検出し、元の文字列をそのまま保持します(不正な文字を出力しないため)。
「文字数」の罠
JavaScriptでは絵文字の長さがおかしく見えます:
"😀".length // 2(サロゲートペアなので2コード単位)
[..."😀"].length // 1(イテレータは正しく1文字と認識)
絵文字を含む文字列を扱うときは:
| 用途 | 推奨 |
|---|---|
| 文字数カウント | [...str].length |
| 1文字ずつ処理 | for (const ch of str) |
str[i] | サロゲートで分裂する可能性、注意 |
本ツールのエスケープ実装は for..of を使っているため、絵文字も1文字単位で正しくエンティティ化します。
絵文字の修飾子・結合文字
絵文字は単独の文字に見えても、複数のコードポイントの結合で表現されることがあります:
国旗(Regional Indicator)
🇯🇵 = 🇯 + 🇵 = U+1F1EF + U+1F1F5
JとPのRegional Indicatorを並べると「日本」の国旗。エンティティ化:
🇯🇵
肌色修飾
👍🏼 = 👍 + 🏼 = U+1F44D + U+1F3FC
親指を立てるサイン + 中等度の肌色トーン。
ZWJシーケンス
👨👩👧 = 👨 + ZWJ + 👩 + ZWJ + 👧
家族絵文字は ZWJ(Zero Width Joiner, U+200D)で結合された複数の絵文字。
結論
これらの複合絵文字は元のコードポイントを保ったままエンティティ化することで安全に扱えます。本ツールは各コードポイントを個別にエンティティ化するため、結合関係はそのまま保持されます。
「制御文字」の扱い
U+0000 (NULL)
U+0001 - U+001F(C0制御文字)
U+007F (DEL)
U+0080 - U+009F(C1制御文字)
これらはHTMLでは表示されませんが、エンティティ化することは可能です:
� ← NULL
	 ← Tab
← LF
← CR
ただし、XML / XHTMLでは大半の制御文字がエラー。HTMLでもセキュリティ上の理由で制御文字を含むことは推奨されません。
BOM(Byte Order Mark)
UTF-16のBOM U+FEFF は、UTF-8でも先頭につくことがあります:

可視化されない文字ですが、ファイルの先頭に紛れ込むと「ゴミ文字が混じる」原因になります。エンティティ化したら気づくきっかけに。
用途別Unicode参照早見表
| 文字 | コードポイント | 10進エンティティ | 16進エンティティ |
|---|---|---|---|
| あ | U+3042 | あ | あ |
| 漢 | U+6F22 | 漢 | 漢 |
| 😀 | U+1F600 | 😀 | 😀 |
| 🇯🇵 | U+1F1EF U+1F1F5 | 🇯🇵 | 🇯🇵 |
| → | U+2192 | → | → |
| ™ | U+2122 | ™ | ™ |
HTML特殊文字エスケープツール で「対象=非ASCII全て」「形式=16進数」にすれば、上記のような変換を自動で行います。
関連記事
Unicodeは「全世界の文字を1つの体系に収める」野心的な規格。HTMLエンティティはその100万文字すべてを扱えます。サロゲートペアの罠だけ気をつければ、絵文字も古典文字も自在に書けます。