--- title: サムネイルの用意が面倒なので絵文字を使えるようにした description: Zennのパクリ機能ですね。すいません。良いですよ。ありがとうございます。 thumbnail: emoji: 🥳 date: 2025-01-27 category: Tech tags: [Svelte, Twemoji] index: true published: true --- 🥳 ← 一番好きな絵文字のPartyfaceくん ## サムネめんどい noteとかみてるとストック画像とかにタイトルを重ねたり凝ったサムネを用意している人が多いですが、ブログを始めて自分も挑戦してみたところ、まぁこれがめんどい。記事書くのも大変なのに、んなことやってられっか ということで早々に諦め、~Zennの機能をパクって~絵文字をサムネイルに使えるようにしました。 絵文字はOS標準のものではなくTwitterがオープンソースで開発する[Twemoji](https://github.com/twitter/twemoji)を使用します。 ## ここで残念なお知らせです 「Twitterがオープンソースで開発するTwemojiを使用」と書きましたが、ご存じの通り某実業家によってTwitter社は消滅、メンテナーが解雇されTwemojiの開発は停止しています。非公開になったわけではないですが、今後開発が再開される見込みはありません。 しかし、元従業員がTwemojiをフォークし開発を続けてくれています。なので今回はこちらのTwemojiフォークを使用します。 https://github.com/jdecked/twemoji ## Twemojiのurlを取得 当初、1文字ずつUnicodeの絵文字コードポイント範囲に含まれるかをチェックしてTwemoji(のCDN)のURLを作ってたのですが、そんなことしなくても[twemoji/parser](https://www.npmjs.com/package/@twemoji/parser)なんていう便利なものが公開されているではありませんか。`npm i @twemoji/parser`でインストールしたら`import`して`parse()`にぶち込むだけです。まぁ簡単! 自分の実装では絵文字シーケンスが無視される問題がありましたが、その周りもこのライブラリが全部やってくれます。 ```mjs import { parse } from '@twemoji/parser'; const text = "aaa❤️‍🔥aaa🥰"; const emoji = parse(text); console.log(emoji); console.log(emoji[0].url); //一番最初の絵文字のurl ``` ``` [ { url: 'https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg/2764-fe0f-200d-1f525.svg', indices: [ 3, 8 ], text: '❤️‍🔥', type: 'emoji' }, { url: 'https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg/1f970.svg', indices: [ 11, 13 ], text: '🥰', type: 'emoji' } ] https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg/2764-fe0f-200d-1f525.svg ``` あまり関係ないですが、自分は文字コードとかその符号化方式の話が好きなので、いずれまとめて記事にしたいです。(長くなりそう..) ### オプション `assetType`にpngかsvgを指定することができます。(デフォルトはsvgです) ```diff - const emoji = parse(text); + const emoji = parse(text,{assetType:'png'}); 出力: https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/72x72/2764-fe0f-200d-1f525.png ``` ## ブログに実装 該当部分の抜粋です。→[コード全体](https://git.moris.day/moris/day.moris.blog) パースではTwemojiが対応する絵文字がない場合の処理を追加しています。 ```ts // https://git.moris.day/moris/day.moris.blog/src/branch/main/src/lib/server/MetaParser.ts import { parse } from '@twemoji/parser'; /* ~なんやかんやあって~ */ emoji = parse(emoji)[0]?.url ?? ''; ``` Frontmatterにサムネイル画像が設定されていない場合に絵文字を表示。それもない場合はブログ一覧では代替画像、本文では空にしました。 ```ts // https://git.moris.day/moris/day.moris.blog/src/branch/main/src/routes/%28DefaultStyle%29/post/%5Bslug%5D/+page.svelte {#if data.metadata.thumbnail} thumbnail {:else if data.metadata.emoji}
thumbnail
{/if} ``` 最後にCSSでいい感じにして完成です。🎉 ここに書いたこと以外ではOGPの設定などもしています。(`og:image`はSVG不可なので注意) ```css /* https://git.moris.day/moris/day.moris.blog/src/branch/main/src/lib/components/Markdown.css */ article { /* ~ いろいろあっての ~ */ & .thumbnail { display: block; margin: 0 auto; max-height: 50vh; } & img.thumbnail { height: 35vh; max-width: 100%; object-fit: contain; } & .emoji.thumbnail { width: 30%; max-width: 30vh; aspect-ratio: 1; @media(width<480px) { width: 50%; } & img { margin: 15%; } } } ``` ちなみに絵文字はCDNからダウンロードされますが、headerの中に``を追加しておくことで名前解決やハンドシェイクの処理を事前に行い、ちょっっっとだけ高速化できます。