Skip to content

Instantly share code, notes, and snippets.

@vzvu3k6k
Forked from khsk/Qiita_Code_Number.user.js
Last active February 14, 2017 00:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vzvu3k6k/586118155b2433653c3aa676af645285 to your computer and use it in GitHub Desktop.
Save vzvu3k6k/586118155b2433653c3aa676af645285 to your computer and use it in GitHub Desktop.
Qiitaのコードの左側に選択不可能な行番号を追加するユーザースクリプト ref: http://qiita.com/khsk/items/89fc40321f1387829135
// ==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 = `
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)
let label = document.createElement('span')
// Textでは改行が反映されない
label.innerHTML += number + '\n'
label.dataset.lineNumber = i + 1
numbers.appendChild(label)
}
code.parentElement.insertBefore(numbers,code)
numbers.addEventListener('click', function(event) {
if ('lineNumber' in event.target.dataset) {
var lineNumber = parseInt(event.target.dataset.lineNumber)
selectLine(code, lineNumber)
}
})
})
function selectLine(pre, lineNumber) {
var currentLine = 1
var range = new Range()
// 以下のループでは最初の行の先頭を捕捉できないのでここで設定しておく。
if (lineNumber === 1) {
range.setStart(pre, 0)
}
// 改行がpreタグの直接の子のテキストノードの中だけに現れることを前提にしている。
// 孫ノードにも改行が含まれる場合はTreeWalkerなどを使って再帰的にノードを辿る必要がある。
childNodes: for (let node of pre.childNodes) {
if (node.nodeType === document.TEXT_NODE) {
let lines = node.wholeText.split('\n')
let offset = lines.shift().length
for (let line of lines) {
++currentLine
if (currentLine === lineNumber) {
range.setStart(node, offset + 1)
} else if (currentLine === lineNumber + 1) {
range.setEnd(node, offset)
break childNodes
}
offset += line.length + 1
}
}
}
var selection = window.getSelection()
selection.removeAllRanges()
selection.addRange(range)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment