絵文字と異体字と Markdown

no extension

絵文字ってある意味で漢字より難解なので,なるべく使わないようにしてきたのだが,文章に混ぜたり emoticon 代わりに使ったりするだけでなく Zenn みたいにページのアテンションに使ってる例もあるわけで「もう少し積極的に使ってもいいかなぁ」という気になってきた。

とはいえ input method から延々と探したりその辺のページから絵文字をコピペするのも馬鹿らしいし,折角 markdown で書いてるんだから意味のあるコードで書きたい。

Hugo なら config.toml 等の設定ファイルで

enableEmoji = true

とすれば markdown テキスト内の :heart: 等を ❤️ 等に変換してくれる。 あるいはテンプレートや shortcodes で

{{ emojify ":heart:" }}

などとしてもよい。

変換可能な絵文字の一覧は以下を参照のこと。

ただしリンク先にある全部の文字が Hugo で使えるわけではないらしい。 私がよく使いそうな絵文字を挙げておくか。

字形 Markdown コード CLDR Short Name
😄 :smile: grinning face with smiling eyes
😴 :sleeping: sleeping face
😔 :pensive: pensive face
🙇 :bow: person bowing ???
💤 :zzz: zzz
💢 :anger: anger symbol
💦 :sweat_drops: sweat droplets1
:star: star
💡 :bulb: light bulb
🎵 :musical_note: musical note
🔑 :key: key
🔒 :lock: locked
🔓 :unlock: unlocked
🔐 :closed_lock_with_key: locked with key

さて,皆さんの環境ではどう見えているでしょうか。 人によって見え方が異なると思います(絵文字のフォント指定については後述)。

ところで,上に挙げた :bow: ってどう見えてます? 実は 🙇♂ ってな感じの2文字に見えてません? うちでは :bow: から変換した絵文字をターミナル・エミュレータとかにコピペすると,こうなるんですよ。

というわけでコードを見てみると

$ echo 🙇‍♂️ | gnkf dump --unicode
0x0001f647, 0x200d, 0x2642, 0xfe0f, 0x000a

おいおい。 本来のコードの後ろに何か付いとるやないかいっ 💢 (← 早速)

実はこれ,絵文字の異体字なんだよ。 内訳はこんな感じ。

Unicode Point 字形 Unicode 名称
U+1F647 🙇 PERSON BOWING DEEPLY
U+200D ZERO WIDTH JOINER
U+2642 MALE SIGN
U+FE0F VARIATION SELECTOR-16

ZERO WIDTH JOINER (ゼロ幅接合子; ZWJ) はアラビア文字なんかで複数の文字を結合してひとつの文字にするための制御文字。 さらに VARIATION SELECTOR-16 は “Emoji Variation Selector” とも呼ばれ,絵文字の異体字であることを示す異体字セレクタである2

つまり :bow: で表示されるのは「土下座する男性」を意味する絵文字(の異体字)なわけだ。 処理系によって異体字を上手く表示できない場合は 🙇♂ のように2つの文字が並んでいるように見えたりするようだ。

…なんで男性なんだろうね。 GitHub の既定ブランチ名を弄るとかするくらいなら,こういうのを真っ先に改善すべきなんじゃないの?

というわけで Hugo 環境全体の設定は変えずに,絵文字表示用の shortcode を作って対応することにした。 こんな感じ。

{{- range $i, $s := .Params -}}
{{- if gt $i 0 -}}&nbsp;{{- end -}}<abbr title="{{ $s }}">
{{- if eq $s "ゴメン" -}}&#x1f647;
{{- else if eq $s "ふむむ" -}}&#x1f914;
{{- else if eq $s "はぁと" -}}&#x1f49b;
{{- else if eq $s "キーボード" -}}&#x2328;
{{- else if eq $s "はなまる" -}}&#x1f4ae;
{{- else if eq $s "錠前と鍵" -}}{{- emojify ":closed_lock_with_key:" -}}
{{- else -}}{{ emojify $s }}{{- end -}}
</abbr>{{- end -}}

これで {{< emoji ":zzz:" >}} などとすれば

<abbr title=":zzz:">💤</abbr>

という感じに展開してくれる。 あとは自分で定義名を作れば別名定義もできるし対応する絵文字を増やすこともできる。 上の shortcode だと

字形 shortcode CLDR Short Name
🙇 {{< emoji "ゴメン" >}} person bowing
🤔 {{< emoji "ふむむ" >}} thinking face
💛 {{< emoji "はぁと" >}} yellow heart
{{< emoji "キーボード" >}} keyboard
💮 {{< emoji "はなまる" >}} white flower
🔐 {{< emoji "錠前と鍵" >}} locked with key

てな感じで定義している。

【2020-10-09 追記】 絵文字のフォント指定

絵文字に関しては Google Fonts みたいなメジャーな Web フォントはないっぽいので各自ローカル環境のフォントをあてにするしかないんだけど(もう自前で Web フォントを用意したくない),これに関して Unicode 本家サイト

.chars, .charsSmall {
    text-decoration: none;
    color: #ccc;
    font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji",
        Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif,
        LastResort;
    font-variant-emoji: emoji;
}

みたいな記述があったので,ありがたくパクらせていただくことにした(笑) すなわち

abbr.emoji-chars {
  text-decoration: none;
  font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort;
  font-variant-emoji: emoji;
}

と定義して

<abbr class="emoji-chars" title=":zzz:">💤</abbr>

となるよう shortcode を書き直せばいいわけだ。 当面はこれで。

【2022-09-18 追記】

Noto Color Emoji は Google Fonts で Web フォントとして指定できるようになっていた。 ので,このブログサイトは Web フォントの絵文字を優先するようにした。

ブックマーク


  1. 海外では 💦 は男性の射精の意味で受け取られるそうで,この絵文字を含む8文字ほどをブロック対象にすると Instagram でセクハラコメントの90%を防げるそうな(笑) 世知辛い。 ↩︎

  2. 異体字セレクタのコードポイントは通常のものと区別するために E+FE0Fと表記する場合もあるらしい。 ↩︎