Twitterのシェアテキストを動的生成するときは気をつけよう

# はじめに

みなさんご存知かと思いますが、シェアボタンをクリックしたときのツイートテキストは自由に設定できます。ただし、ユーザーが入力した値などの可変長文字列を含ませて動的に生成する際には、文字数制限に気をつけなければいけません。

Twitterの文字カウントは特殊で、`length` プロパティなどでは正確に文字数をカウントできないので、解決策を共有します。


# 文字数をカウントする

[twitter-text](https://github.com/twitter/twitter-text) を使います。
これは、ツイートテキストのパースやユーザー名の抽出などの機能がまとまった、Twitter公式のライブラリです。

その中で用意されている `parseTweet()` は、引数に渡したテキストの文字数や、有効なツイートであるかどうかをオブジェクトで返却してる便利メソッドです。
以下はJavaScriptの `length` プロパティと比較したコードです。
<p class="codepen" data-height="300" data-default-tab="js" data-slug-hash="jOKqQpp" data-user="TakuyaYamabana" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/TakuyaYamabana/pen/jOKqQpp">
  tweet length</a> by TakuyaYamabana (<a href="https://codepen.io/TakuyaYamabana">@TakuyaYamabana</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


# ツイートの文字数制限

Twitterの文字数制限といえば140文字、かと思いきや2017年に[日本語、中国語、韓国語以外の言語の制限文字数を280文字に引き上げ](https://blog.twitter.com/official/ja_jp/topics/product/2017/Cramming-Tweeting-Made-Easier.html)ています。

:::note info
日本語などの全角文字と半角英数が混在した場合、全角文字は2文字分としてカウントされ、最大280文字のツイートができます。
:::

もちろんハッシュタグやシェア用のURLもこの文字数に含まれます。
また、[URLはその長さにかかわらず23文字](https://help.twitter.com/ja/using-twitter/how-to-tweet-a-link)として扱われます（内部で短縮URLを生成しているようです）。

twitter-text は、このあたりの特殊な文字カウントに対応しているため、ツイートの動的生成には必須と言えます。
ただし、**TwitterではURLの文字カウントにバグがあり**（後述）、twitter-text もバグに対応できていないため、実装側で注意が必要になります。


# 文字カウントのバグ対応

バグの挙動は実際に試していただくと分かりやすいかと思います。

以下のテキストをツイートしてみてください。おそらく文字数制限のエラーでツイートできないはずです。（[Twitter ホーム](https://twitter.com/home)）

```
１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０１２３４５６７８９０example.com
```

このテキストの文字数は `１２３４5...` が260文字（全角130文字）、`example.com` は11文字で合計271文字です。`parseTweet()` メソッドで確認してみても有効なツイートであると判断されますが、実際にはツイートできません。

原因は `example.com` の部分です。
ツイート前には11文字の文字列として扱われますが、ツイートボタンを押したときにURLに変換され、23文字でカウントされます。その結果、283文字になってしまいエラーが発生しているのです。

対策として、URL（となりうる文字列）の直前に半角スペースや改行を入れることで解決できます。以下のように `parseTweet()` メソッドでも正確にカウントできています。

<p class="codepen" data-height="300" data-default-tab="js" data-slug-hash="ExRdEoq" data-user="TakuyaYamabana" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/TakuyaYamabana/pen/ExRdEoq">
  tweet length2</a> by TakuyaYamabana (<a href="https://codepen.io/TakuyaYamabana">@TakuyaYamabana</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


# おまけ
Twitterの文字数制限が280から1,000に引き上げられる可能性があります。

https://mashable.com/article/twitter-1000-characters
> Recently, a Twitter user suggested that the social media platform increases the character limit to 1,000, and Twitter owner and CEO Elon Musk responded "it's on the todo list."
>
> 訳：Twitterユーザーが、文字数制限を1,000に増やす提案をしたところ、イーロン・マスクは「それは todo リストにある」と答えました。


# 参考URL
- [twitter-text](https://github.com/twitter/twitter-text)
- [Twitterでツイートできる文字数を正確に数える(絵文字もURLも)](https://www.memory-lovers.blog/entry/2019/12/26/070000)
- [Twitterヘルプの「リンクが23文字に変換」は間違いなので注意](https://iwb.jp/twitter-help-wrong-link-converts-23-characters/)