2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Qiitaのユーザーページにナビゲーションタブを追加するUserScript作った

Last updated at Posted at 2020-03-28

Note: Qiita のアップデートにより現在は動作しない。

image.png

現状ではユーザーの「LGTMした記事」「フォローしているユーザー」「コメント履歴」「編集リクエスト履歴」を見るためにはいちいち「...」ボタンをクリックしなければいけない。これは面倒なので、より快適に閲覧できるようにナビゲーションタブを追加するUserScriptを作成した。

インストールにはUserScript管理用の拡張機能が必要。

// ==UserScript==
// @name         Qiita User Page Nav
// @namespace    https://qiita.com/righteous
// @version      0.1
// @description  Adds an navigation tab on user pages
// @author       righteous
// @match        https://qiita.com/*
// @grant        none
// ==/UserScript==

!(function () {
  const targetClassPrefixes = [
    'UserMain__ContentsContainer',
    'UserLgtms__ContentsContainer',
    'UserFollowees__ContentsContainer',
    'UserComments__ContentsContainer',
    'UserEditRequests__ContentsContainer',
  ]

  const selector = targetClassPrefixes.map(c => `[class^="${c}"],[class*=" ${c}"]`).join(',')
  const containerDOM = document.querySelector(selector)
  if (!containerDOM) return

  const [username, curPage = ''] = window.location.pathname.split('/').filter(s => s)
  if (!username) return

  const pages = [
    { path: '', label: 'マイページ' },
    { path: 'lgtms', label: 'LGTM記事' },
    { path: 'following_users', label: 'フォロー' },
    { path: 'comments', label: 'コメント' },
    { path: 'edit_requests', label: '編集リク' },
  ]

  const nav = document.createElement('div')
  nav.classList.add('qiita-user-page-nav')

  for (const page of pages) {
    const linkDOM = document.createElement('a')
    linkDOM.classList.add('ol-ItemList_tabItem')
    if (curPage === page.path) {
      linkDOM.classList.add('is-active')
    }
    linkDOM.textContent = page.label
    linkDOM.href = `/${username}/${page.path}`
    nav.appendChild(linkDOM)
  }
  containerDOM.insertBefore(nav, containerDOM.firstChild)

  const styleDOM = document.createElement('style')
  styleDOM.textContent = `
  .qiita-user-page-nav {
    background-color: white;
    display: flex;
    padding-top: 15px;
    margin-bottom: 10px;
  }

  @media (max-width: 770px) {
    .qiita-user-page-nav .ol-ItemList_tabItem {
      font-size: 8px;
    }
  }
  `
  document.head.appendChild(styleDOM)
})()

説明

要素を挿入するターゲット要素の取得

ユーザーページには「メインページ」「LGTMした記事」「フォローしているユーザー」「コメント履歴」「編集リクエスト履歴」の5種類あり、すべて同じような 2 column layout であるため、右の column の一番上にタブを追加することが方針である。しかし、それぞれのページでこの column の持つクラスが以下のように異なる。

  • メインページ: UserMain__ContentsContainer-sc-1ead6ck-3
  • LGTMした記事: UserLgtms__ContentsContainer-sc-2bd1us-3
  • ...

また、見ての通りクラス名の末尾にsc-1ead6ck-3などとついており、これはおそらくStyled Componentsによってビルド時に生成されたハッシュ値であり、ビルドするたびに変わる可能性が高い。

よってこのUserScriptではこの column の element を取得するにあたり、次のようなセレクターを作ることにした。

  • 次のいずれかを満たす要素にマッチ
    • UserMain__ContentsContainer から始まるクラスをもつ
    • UserLgtms__ContentsContainer から始まるクラスをもつ
    • ...

しかし、「〇〇から始まるクラスをもつ」という条件をきれいにセレクタで表現することはできない。なぜならclass属性の値は複数のクラス名がスペース区切りで連結されたものであるからである。よって次のようなセレクターを使う必要がある。

// 'myclass'から始まるクラスを持つ要素を取得
document.querySelector('[class^="myclass"], [class*=" myclass"]')
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?