概要
Qiitaのフィード画面で直接には見えない投稿者の名前を表示する。
検証環境
- Firefox 51
- Greasemonkey
スクリーンショット
これが
こうなる。
タグ名がリンクになるように、ユーザー名もユーザーページのリンクになっている。
フォローしている人のいいねとコメントにも対応している。
他に何かあったかな?
コード
GistスクリプトリンクQiita_show_username_to_feed.user.js
// ==UserScript==
// @name Qiita show username to feed
// @namespace khsk
// @description フィードに投稿者の名前を追加する
// @include http://qiita.com/
// @include https://qiita.com/
// @include http://qiita.com/items
// @include https://qiita.com/items
// @include http://qiita.com/stock
// @include https://qiita.com/stock
// @include http://qiita.com/mine
// @include https://qiita.com/mine
// @version 1
// @grant none
// ==/UserScript==
console.time('show name');
//const FEED_ITEMS = 20; // 一度に読み込むフィード数
const ITEN_CLASS = 'item-box track' // 'item-box track hidden'はおそらく投稿のタグを複数フォローしていたとき、ひとつ以外につけられる。だから、見るたびに同じ記事でもタグ表記が異なるフィードになることがあると思う。
const getUserName = node => {
const link = node.querySelector('div.item-box-title > h1 > a');
return link.href.match(/https?:\/\/qiita.com\/([^/]+)/)[1];
};
const createUserNameNode = parentNode => {
const userName = getUserName(parentNode);
const a = document.createElement('a');
a.href = 'https://qiita.com/' + userName;
a.innerHTML = ' ' + userName + ' ';
const span = document.createElement('span');
// タグ名みたいに太文字にするよ
span.className = 'user';
// insertBeforeが面倒くさい
span.innerHTML = ' ' + a.outerHTML + ' ';
return span;
}
const insertUserNameNode = (parentNode) => {
const userNameNode = createUserNameNode(parentNode);
// 語尾変化 : 挿入前 + 挿入後
const insertPattarn = {
'の' : /(に)(新しい投稿がありました)/,
// いいねと!コメントが!なぜか!spanに!囲まれている!!
'の投稿に' : /(が)(<span>(?:コメント|いいね)<\/span>しました)/,
// フォロイーの投稿は別にいいよね。
};
const action = parentNode.querySelector('div.item-box-header > div.action');
if (action == null) {
return;
}
let html = action.innerHTML;
// ここわかりにくい
for (let suffix in insertPattarn) {
let newHtml = html.replace(insertPattarn[suffix], '$1' + userNameNode.outerHTML + suffix + '$2');
if (newHtml != html) {
action.innerHTML = newHtml;
break;
}
}
}
const mo = new MutationObserver((mutationRecords, data2) => {
mutationRecords.forEach(mutationRecord =>{
if (mutationRecord.addedNodes == null) {
return;
}
// 追加だけでもいろいろ引っかかるので、1フィード読み込み件数をひとつのフィルターにする
// が、表示後の「n件の新しいアクティビティ」に対応できないと思う。気にしないってときは使う
// if (mutationRecord.addedNodes.length != FEED_ITEMS) {
// return;
// }
mutationRecord.addedNodes.forEach(node => {
// フィードであることをクラス名でチェック
if(node.className != ITEN_CLASS) {
return;
}
insertUserNameNode(node);
});
});
});
const items = document.getElementsByClassName('col-sm-9')[0];
const options = {childList: true, subtree:true};
mo.observe(items, options);
console.timeEnd('show name');
いつも通りですが、成長としてはMutationObserver
で追加されたDOMにだけ処理ができるようになった。
元ネタ
Qiita のフィードは投稿者の存在を蔑ろにしていると思うんだ… - Qiita
元記事やスクリプト感想
僕の Qiita 記事をクリックする人がクリックする前に見ているのは僕の名前やアイコンではなく有名なユーザさんやタグの名前とロゴなのだ。タイトルだけは自分のものだけど。
フィードを漁る身としてはいいね数と有名ユーザーさんを指標にしてたけど、投稿者としてはタイトル勝負と思ってたので自己矛盾に気づいた感じ。
Qiita のフィードは投稿者の存在を蔑ろにしていると思うんだ… - Qiita コメント:#comment-08b8fd5a940c8926f8c7
「誰が書いたか」で記事を取捨選択してほしくないという意図からあのような仕様にしているんだと思っていました。
そうなのかなーと思っていた。
知名度も実績も無い自分のような人の記事は名前で足切りされそうで、名前が出ないからタイトル勝負で開く所まではもって行けるのでは!?と思っていました。
でも単純接触効果ってものもあるし、ちらとでも名前が写らないと無い知名度も高まりませんし。
よく見る名前を覚える覚えもありますし。頑張って投稿していっぱい名前が映れば人の頭の片隅に残るんじゃないかな。
自分は週一投稿で露出しないんですが。
タイトル芸といえば、観測範囲外なのですが@harapeko_wktk のタイトルが印象に残るしちょっと楽しくなるしで、そういったアピールもありなのかなと。
今までのフィードに慣れていると投稿者名がでるだけでもごちゃっと感じて、慣れの問題だろうけど、UIのスマートさというか取捨選択もやっぱり大事だなと思いました。
だから、投稿者が(開く前に)分かることの良し悪しはまだわからないので、使っていくかは悩んでるんですけど、選択肢はあってもいいよねって。
ユーザーのアイコンは出ないの?
出ません。
qiita/ユーザー名/ユーザー名.icon
とかがユーザー画像のaliasとかになってくれていたらよかったんですけど、
現在のイマジネーションではユーザー情報取得→画像URL取得をしなければならず、
APIはリクエスト数制限あるし、
一度に20(フィード数)*(1(ユーザー情報取得) + 1(アイコン表示))
の40リクエストが読み込むたびに発生するのはダメだろうと。
ただ、一回ずつなら大丈夫だと思うので、タグアイコンにマウスを載せるとユーザーアイコンに切り替わるスクリプトも書いています。
async使っちゃったので、順調なら明日の3/7のFirefox 52で対応されるので来週ぐらいに完成できたらいいなって。
参考
手前味噌