Qiitaのコードの左側に選択不可能な行番号を追加するユーザースクリプト


 元ネタ

Qiita > 要望 > コード左側に行番号を表示 - Qiita

たまに作りたくなるネタを拝借しています。

最近選択不可のCSSを知ったばかりだったのでタイムリー

まぁ、個人で行番号が見えてn行目~と伝えても通じにくいんですが…

スクリーンショット

動作検証環境

  • Firefox 46
  • greasemonkey

Qiitaのコードにコピーボタンを追加するユーザースクリプト - Qiita
との併用可能を確認しています。

コード

GistスクリプトリンクQiita_Code_Number.user.js

Qiita_Code_Number.user.js
// ==UserScript==
// @name        Qiita Code Number
// @namespace   khsk
// @description コードに選択不可能な行番号を追加する
// @include     http://qiita.com/*/items/*
// @include     https://qiita.com/*/items/*
// @include     http://qiita.com/*/private/*
// @include     https://qiita.com/*/private/*

// @version     1
// @grant       none
// ==/UserScript==

var style = document.createElement('style')
style.type      = 'text/css'
style.innerHTML = `
pre.khsk-codeNumber { 
  float:               left;
  user-select:         none; /* 追加した行番号は選択不可にする */
  -webkit-user-select: none;
  -moz-user-select:    none;
  -ms-user-select:     none;
  -o-user-select:      none;
  overflow-x:          hidden !important; /* スクロールバーはあるのもないのも不自然 */
}
pre.khsk-codeNumber:after {
  clear:               both;
}
`
document.getElementsByTagName('head')[0].appendChild(style)

var codes = document.querySelectorAll('div.highlight pre')
Array.prototype.forEach.call(codes, function(code) {
  var rows = code.innerText.split('\n')
  // 最後に改行が入っていることにより、空要素が生まれるため削除
  rows.pop()
  var length = rows.length
  var numbers = document.createElement('pre')
  numbers.className = 'khsk-codeNumber'
  for (let i = 0; i < length; ++i) {
    // 桁数は3桁までとする
    let number = ('  ' + (i + 1)).slice(-3)
    // Textでは改行が反映されない
    numbers.innerHTML += number + '\n'
  }

  code.parentElement.insertBefore(numbers,code)

})

やっていることは単純に<pre>を横並びに追加して、コードの行数を数えているだけですね。
ちょっと処理時間がかかる書き方な気がしていますし、配列にするのではなく'\n'の数をカウントした方がいいかな?とも思っています。
あとはCSSで選択不可にすれば、コードのみをドラッグで選択できます。

ちょっと左右の余白が多すぎる気もするので、そこはCSSを追加したり。
もしかしたらコード側の<pre>のCSSをいじらないとスッキリしないかもしれません。

廃案

ハイライトが無効になるためお蔵入り

// ==UserScript==
// @name        Qiita Code Number
// @namespace   khsk
// @description コードに選択不可能な行番号を追加する
// @include     http://qiita.com/*/items/*
// @include     http://qiita.com/*/private/*
// @version     1
// @grant       none
// ==/UserScript==

// 追加した行番号は選択不可にする
var style = document.createElement('style')
style.type      = 'text/css'
style.innerHTML = 'span.khsk-codeNumber { user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none;}'

document.getElementsByTagName('head')[0].appendChild(style)

var codes = document.querySelectorAll('div.highlight pre')
Array.prototype.forEach.call(codes, function(code) {
  var rows = code.innerText.split('\n')
  // 最後に改行が入っているので、空要素が生まれるため削除
  rows.pop()
  rows = rows.map((row, index, array)=>{
    // 桁数は3桁までとする
    let number = ('  ' + (index + 1)).slice(-3)
    return '<span class="khsk-codeNumber">' + number + ' </span>' + row
  })
  code.innerHTML = rows.join('\n')
})

夢想

行番号をクリックしたらその行を選択済みにする、ってコピペに便利そうですけど、<pre>じゃ厳しい気がしてならない。
できそう!って教えてもらえれば頑張って調べてみる。