JavaScript でツイート文字列の文字数を正しくカウントする

2015/09/11 Gistのライブラリをアップデートしました。
2014/10/13 Gistのライブラリをアップデートしました。

JavaScript 経由で Twitter に投稿する処理を持つウェブアプリはよくあると思う。そのときに実装する必要がある機能のひとつに文字数カウントの機能がある。

Twitter API に投稿リクエストをすれば、入力したツイートが文字数オーバーしていたかどうかはわかるけれど、ユーザー導線を考えて JavaScript 内でバリデーションを行いたい機会は少なくないはずだ。

はじめにお断りしておくと、この記事はあくまでもツイート文字列の文字数を * 正しく * 数えたい神経質な人向けなので、ある程度の精度でよいという方は他の方の作られたライブラリを参照するのがよいと思います。

ツイート文字数カウントのセオリー

ふつうに、 $('#tweet').val().length で良いじゃんと思いがちだが、文字列を正規化したり、 URL を短縮したりする処理のことを考えると一筋縄には行かない。現行の Twitter では URL は必ず短縮されることになっているため、どんなに長い URL であろうとも、 HTTP の URL なら 22 文字、 HTTPS の URL なら 23 文字としてカウントされることになっている。 23文字としてカウントされることになっている。

URL を正しく正規表現で引っ掛けるのはなかなか骨が折れる。しかし考えてみれば、ツイート文字数のカウントはウェブ版 Twitter アプリで使われているんだから、正確にカウントしたければウェブ版 Twitter で使われているロジックをそのまま流用できればよい。

都合のよいことに、 Twitter がウェブ版アプリで使っているテキスト処理は外部化されていて、 GitHubリポジトリが公開されている。

twitter/twitter-text-js

上記 URL にアクセスした先にある twitter-text.js のリンクをクリックすると、そのソースが出てくる。これを流用すれば、正確なツイート文字数カウントができるはずだ。ためしに実装してみたのが以下。 twttr.txt.getTweetLength というメソッドが文字数を数える関数で、プレーン文字列を渡せば文字数が返ってくる。

自分のウェブサイトで使う場合は、 twitter-text.js をダウンロードし、ページから読みこめばよい。

文字数を数えたいだけなのにライブラリが巨大問題

twitter-text.js は、現時点でなんと 1328 行もある。正確に数えるためとはいえ、ツイート文字数を数えるためだけにこのライブラリを導入するのはちょっと気後れする。

このライブラリは、文字数を数える以外にもいろいろな機能が含まれている。ツイートが投稿可能な正当なものであるかどうかを判別する関数であるとか、 @user やハッシュタグが含まれているツイートにリンクタグを付与する関数など。これらの機能は、文字数を数えるという目的には必要ないので削ることができる。

そこで削ってみたのが以下。

ツイートの文字数カウント (わたしの Gist に飛びます)

まだ 350 行あるが、だいぶましになった。