選択範囲の行をランダムに並び替えるUserScript
選択範囲の行をランダムに並び替えるUserScript
https://gyazo.com/aa51be1f3aebd183457ad0bde2ed49ba
code:script.js
(function () {
'use strict';
// 選択範囲を置換(Scrapboxのエディタtextareaを直接操作)
function replaceEditorSelection(newText) {
const ta =
document.querySelector('textarea#text-input') ||
document.querySelector('textarea');
if (!ta) return;
const start = ta.selectionStart ?? 0;
const end = ta.selectionEnd ?? 0;
// 選択が無い場合は何もしない
if (start === end) return;
const before = ta.value.slice(0, start);
const after = ta.value.slice(end);
ta.value = before + newText + after;
// 置換後の選択位置(置換した部分を選択状態にする)
ta.selectionStart = start;
ta.selectionEnd = start + newText.length;
// Scrapbox側に変更を通知
ta.dispatchEvent(new Event('input', { bubbles: true }));
ta.focus();
}
// Fisher-Yates shuffle
function shuffleArray(arr) {
const a = arr.slice();
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[ai, aj] = [aj, ai];
}
return a;
}
// 選択範囲の行をランダム並び替え
function shuffleLines(text) {
const normalized = text.replace(/\r\n/g, '\n');
const lines = normalized.split('\n');
return shuffleArray(lines).join('\n');
}
scrapbox.PopupMenu.addButton({
title: function (text) {
const lines = text.replace(/\r\n/g, '\n').split('\n').length;
return lines > 1 ? 行をシャッフル (${lines}行) : '行をシャッフル';
},
onClick: function (text) {
const shuffled = shuffleLines(text);
// 1行以下、または結果がたまたま同一なら何もしない
if (
shuffled === text ||
shuffled.replace(/\r\n/g, '\n') === text.replace(/\r\n/g, '\n')
) return;
replaceEditorSelection(shuffled);
}
});
})();