Qiita投稿記事のog:descriptionに反映される本文を教えてくれるユーザースクリプト

*QiitaのUI更新により現在、動作しない可能性が高いです。当記事を元に同等の機能を実現したスクリプトは[こちら](http://qiita.com/khsk/items/3585160b0915656137b5)*

[SlackとQiitaの117文字な関係][1]
を読んで「冒頭117文字に気をつけよう！」と思ったが、117文字なんて普通分からない。
だから記事を書いている時に教えてくれるスクリプトを書いてみました。
UserScriptです。
[]:ここまでが要約です
↑までがSlackにURLを貼り付けると表示されるはず。

[Qiita summary line notification for Slack.user.js
](https://gist.github.com/khsk/d5a9826d38b0133be2bf)
Firefoxのgreasemonkeyで作成・動作検証です。

# <i class="fa fa-cubes" style="font-size:1em;"></i> 概要

入力毎に文字数を判定し、117文字の前後に本文に表示されないマークダウンを追加する。

# <i class="fa fa-video-camera"></i> デモ

![qiita動作デモ.gif](https://qiita-image-store.s3.amazonaws.com/0/62354/01330d05-eef6-439e-9e75-247ffe8cea31.gif)

# <i class="fa fa-smile-o"></i> 作ってみて得たこと

## keyイベントは大変

今まではボタンの`click`や`change`など、一種類のわかりやすいイベントを使ってきましたが、キーボード操作では`change`,`keydown`,`keypress`,`keyup`と種類が多く、どれを使えばいいのか悩みました。
[jQueryでテキストボックスの変更を監視/検知する](http://qiita.com/maruyam-a/items/cf0168f91d934b449a07)
を参考に`keyup`イベントを使いましたが、日本語入力とキャレット移動のために`keydown`も併用しました。

### `keydown`は入力前`keyup`は入力後

挿入したコメントを`Backspace`や`Delete`キーで削除しようとするとコメントをスキップして削除処理を行いたかったのですが、キー入力時に発生するイベントで処理できるのか疑問でした。
検証すると、`keydown`イベント時は入力処理(`textarea`への反映)の前に発生していました。
そこでキャレットを移動することで入力先の変更を実現しました。
`keydown`では入力処理は発生してませんが、入力したキーはわかるので、ショートカットキーの実装などができそうと感じました。

### 入力値が文字列でわかる

キーボードからの入力値といえば[謎な整数値のキーコード](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode)と思っていました。
が、[`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)で文字列で取得できると知りました。

### 日本語の入力値を取得することは難しい

`textarea.val()`ではなく、日本語の変換から確定までの入力です。

調べただけでも日本語入力であれこれする方法は色々出てきます。
困る原因は日本語入力時に`KeyboardEvent`に渡されるものが`Enter`なことが原因かと思います。

自分の場合は、

* 「何を入力したか」は必要なく、「何文字入力したか」が必要だった
* 直前にキャレットの移動を学んでいた

ため、`keydown`時のキャレット(入力前)と`keyup`時のキャレット(入力後)の差を入力文字数として扱ってみました。
「何を入力したか」を調べるときも、この2つのキャレットの範囲内の文字列を取得すればわかるんじゃないかなとぼんやり考えています。

### イベントは手動でfireできる

`form.submit()`や`button.click()`は今まで使ったことがありましたが、`textarea.keyup()`なんて見かけたことがありませんでした。

調べてみると、[Javascript で強制的にイベントを発生させる方法](http://www.dugsite.net/post/javascript-createevent)という記事から`document.createEvent()`を知り、
[`document.createEvent`](https://developer.mozilla.org/ja/docs/Web/API/Document/createEvent)と[`KeyboardEvent.initKeyEvent()`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/initKeyEvent)でイベントを発生させることができました。

## [JavaScript MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript) の有用性

今までは体感で検索順位が低かったのであまり読まず、ブログの記事などを読んでいました。
今回はjQueryを封印してみた結果、一般の記事はjQueryが多くて参考になりにくく、素のJavaScriptでわかりやすいものとなるとここになりました。
初めて使うメソッドが多いのも一因でしたでしょうが、後半はまず`mdn`を付けて検索していました。
API Doc風なサイトは最初は使いづらいのですが、慣れるとやはり便利でした。
 
## OGPという存在を知った

最近良く見かけるカード形式の記事リンクなどは、表示元がリンク先を読み込んでHTML全体から動的に作っているとなんとなく思っていました。
[SlackとQiitaの117文字な関係][1]
もSlackが本文の117文字を読み込んでいて、URLだけになるページはSlack側が非対応なのだと思っていました。

が、実はOGPという`meta`タグによる仕様でした。
[これだけは知っておきたいOGP （Open Graph Protocol）](http://nex.fm/ogp/)

なので、もしかしたらTwitterやFacebookにURLを貼るときにも最適化されているかもしれません。(未検証)

[PHPマニュアルのURLを入れたのにプレビューが出ないと頭を抱えていた謎も解けました](http://qiita.com/khsk/items/a83827ef8e2f07362634#slackで動作確認)

ちなみになぜ本文の117文字かというと、Qiita側が想定する`og:description`の最大文字数が120文字で、後略の`...`をいれて120文字、だと思います。
`description`はもうちょっと長いです。`description`は下の記事だと120文字以内にしましょうと書いているのですが、文字数の最大値は結構ばらばらでSEOはさっぱりな自分にはよくわかりません。

[SEO嫌いにお送りするSEO策。これでもうSEOについてしばらく考えなくて良いぜ！！](http://qiita.com/taiyop/items/050c6749fb693dae8f82#description%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)

こちらのコメントなどが腑に落ちますが、多分いろいろ変動するものなんでしょうね。
[【SEO】descriptionsタグの文字数ってGoogleに書いてあった](http://qiita.com/siluejp/items/24ec5265c94d6db59bd8)

## ピクトグラムやアイコンに対する認識が人と違うかもしれないという気付き

UI?を具体的に考える実体験を初めて持てました。

機能のON,OFFを付けたとき、最初はただのチェックボックスでしたが
[Qiita の記事の見出しに Font-Awesome を利用して見栄えを良くする #qiita](http://qiita.com/tbpgr/items/361d8aaa38fb57d75216)
を読んで次の記事はFont-Awesomeを使おうと思っていて、Qiitaで読込済みなのですぐに使えると思い出しました。

そこで現在のような
<i class="fa fa-check-circle"></i><i class="fa fa-check-circle-o"></i>
を付けたのですが、[Font Awesome](http://fortawesome.github.io/Font-Awesome/icons/)ではモノクロだったので、なんとなく<i class="fa fa-check-circle"></i>をON時のアイコンにしました。
しかし、表示してみると、<i class="fa fa-check-circle-o"></i>が緑色で、「Qiitaは白地のアイコンを有効とみなしている」と感じました。
(主観です。Qiitaが緑にしたのか・有効的なイメージをもたせているのかはわかりません)
自分がデザインに無頓着なのはまだいいとしても、何も考えずに作って利用者に混乱を与えるのは良くないなぁと実感しました。

[`<i class="fa fa-toggle-on"></i>`](http://fortawesome.github.io/Font-Awesome/icon/toggle-on/),[`<i class="fa fa-toggle-off"></i>`](http://fortawesome.github.io/Font-Awesome/icon/toggle-off/)
は使えなかったうえ、なじみがない自分にはこれもどっちがONかわからないんですよね。
ここらへんの一般常識を知りたいです。

# <i class="fa fa-frown-o"></i> 作ったうえで悪いこと・わからないこと

## テキストをすべて変数に入れている

`keyboardevent`のテクニックとして紹介されていたので、差分があれば処理を行うようにしたのですが、こんな文量を毎回変数に入れるのはメモリの無駄使いなのではないかと感じます。

## `keyboardevent`による負担

当たり前ですがキー入力のたびにイベントが発生して処理が走るので、重くならないかが心配です。
現在は特に違和感を感じませんが、ユーザー操作に影響しない処理の上限や処理が必要ない場合に早めに終了するためのテクニックなどを身につけなければならないと思います。(処理はクライアント依存でしょうが)

## コメント部が操作できる

`\n[]:ここまでが要約です\n`の一部を削ると`\n[]:ここまでが要約です\n`がぽこぽこ増えます。
ここは進入禁止にするなり入力禁止にするなりすればよかったのですが、手間と毎回走る処理の増加に対して効果がイマイチかなと見送りました。
ぶっちゃけ面倒でした。
ここらへんの細かいけど面倒な処理を時と場所を指定して10年20年以内に実装できるよう善処します。

## 非イベントによる動作

Qiitaの各クリック箇所の多くはマウスオーバーで色が変わったりしますが、インスペクタで見ても`mouseover`イベントとかは設定されていないんですよね。
多分cssや擬似要素だと思いますが、謎です。
そこら辺の知識を身につけたいです。

## 改行が発生する
コメントを入れたまま投稿すると、本文と`meta`タグの`description`に改行が入ってしまいます。インラインコメントができればよかったのですが、その方法が見つかりませんでした。
また、コメントは`<!-- -->`では空行が直前に必要だったので改行数が多くなってしまいました。

## 互換性を考えていない

JavaScriptの動作はブラウザに依存します。
今回なら`keyboardevent`の発生はFirefoxとそれ意外で異なってますし
[日本語IMEで未確定文字が無く且つ変更されたらハンドラを実行するjQueryプラグインを作ってみた](http://qiita.com/hnakamur/items/9a9ca2663285e19088c7#2-3)
`keyup`を手動で起こすための`KeyboardEvent.initKeyEvent()`は*非推奨*らしく、代案も見つけられませんでした。

[KeyboardEvent.initKeyEvent()](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/initKeyEvent)
[KeyboardEvent.initKeyboardEvent()](https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent#initKeyboardEvent%28%29)


# <i class="fa fa-flag-checkered"></i> おわり

実際に使いながらこれを書きました。
あたりまえですが、冒頭を書くのは最初だけです。
納得できる117文字が決まれば、この機能は不要になるんですよね。
なので、ユーザースクリプトで常時監視しなくても、ブックマークレットで都度起動しどこまでが117文字かを通知する方式でもいいと思いました。
(そのクリックを嫌ってユーザースクリプトにしましたが、あまりに用途が限定的過ぎでした)

また、どこまでが117文字か、に関しても、わざわざ`textarea`にコメントを挿入せずに空きスペース(投稿ボタンの隣とか)に117文字の末尾10文字でも表示するだけで十分なんじゃないかとも思いました。
するとキーボード操作のあれやこれやも全く不要になりますね…

やはり作るだけでなく使ってみてのフィードバックも大切と思いました。
(そもそも設計段階でコメント挿入を思いつくのが愚案でしたが)
「じゃあ作りなおせよ」となりますが、クソコードでも公開したほうがいいとどこかで見ましたので、公開します。

[1]:http://qiita.com/suin/items/c2cdf9d51198bfb714b2