増井俊之

繰り返し実行 (Ctrl-Rで再実行)
script.js__import "https://scrapbox.io/api/code/again/Scrapbox/script.js"KeyScriptenの導入で不要になったかも
style.css.grid-style-item[data-page-title*="settings"],.grid-style-item[data-page-title*="ブログ:"],.grid-style-item[data-page-title*="Tips:"],.grid-style-item[data-page-title*="..."],.grid-style-item[data-page-title*="_"]{display: none !important;}ScrapExecによるコードブロック評価
script.jsimport '/api/code/masui/ScrapExec/script.js'alert.jsalert('abc');ScrapCalcによる式評価
script.jsimport '/api/code/masui/ScrapCalc/script.js'style.css@import '/api/code/masui/ScrapCalc/style.css';メニューに検索を追加
script.js scrapbox.PageMenu.addItem({ title: () => "> google Site", onClick: () => window.open(`https://www.google.com/search?q=${encodeURIComponent(window.scrapbox.Page.title)}+site:scrapbox.io`) })Popup Menuのカスタマイズ
メニュー枠のサイズ調整
style.css.popup-menu .button-container { height:31px; }デフォルトのPopup Menuを消す
style.css.popup-menu .strike-button,.popup-menu .italic-button,.popup-menu .copy-plain-button,.popup-menu .link-button,.popup-menu .strong-button { display: none !important;}ボタン周りの線を消す
style.css.selections .popup-menu .button-container .button:not(:first-of-type) { border: 0 }翻訳
script.js scrapbox.PopupMenu.addButton({ title: '🟡 翻訳', onClick: text => { if(text.match(/^[a-zA-Z0-9_]*$/)){ window.open(`https://translate.google.com/#en/ja/${text}`) } else { window.open(`https://translate.google.com/#ja/en/${text}`) } } })ChatGPT
script.jsscrapbox.PopupMenu.addButton({ title: '🟢 要約', onClick: text => { window.open(`https://chatgpt.com/?q=以下を要約してください\n${text}`) } }) scrapbox.PopupMenu.addButton({ title: '🔵 ChatGPT', onClick: text => { window.open(`https://chatgpt.com/?q=${text}`) } })Google
script.jsscrapbox.PopupMenu.addButton({ title: '🟤 Google', onClick: text => { window.open(`https://google.com/search?q=${text}`) } })Cosense横断検索
script.js scrapbox.PopupMenu.addButton({ title: '⚫ SB検索', onClick: text => { window.open(`/${scrapbox.Project.name}/search/page?q=${text}`) } })EpisoPass暗号化/復号
script.jsscrapbox.PopupMenu.addButton({ title: '🟥 暗号化', onClick: text => { window.open(`https://s3-ap-northeast-1.amazonaws.com/masui.org/e/a/eab4a39ed37c0c467874d8ec32a320e1.html?seed=${text}`) } })Popup Menuから写真ページに飛ぶ
e.g. 2025/4/20
script.jsscrapbox.PopupMenu.addButton({ title: '🟨 写真', onClick: text => { var year, month, day var m; if(m = text.match(/([12]\d\d\d)\/(\d\d?)\/(\d\d?)/)){ year = m[1] month = m[2] day = m[3] } else if(m = scrapbox.Page.title.match(/予定表.*([12]\d\d\d)-(\d\d?)/)){ // 予定表ページ year = m[1] month = m[2] if(m = text.match(/(\d\d?)\/(\d\d?)/)){ day = m[2] } } else { // 入力させる? } if(year && month && day){ day = ('0' + day).slice(-2) month = ('0' + month).slice(-2) window.open(`https://scrapbox.io/masui-photos/${year}-${month}-${day}`) } } })地図
script.jsscrapbox.PopupMenu.addButton({ title: '🟫 地図', onClick: text => { window.open(`https://maps.google.com/?q=${text}`) } })Eval
script.jsscrapbox.PopupMenu.addButton({ title: '🟦 実行', onClick: text => { return String(eval(text)) } })ランダムページ表示?
script.jsif(location.href == "https://scrapbox.io/masui/masui-random"){ const button = $('.random-jump-button') if (button) { button[0].click() }}abc みたいな表記のテスト
style.css .deco-\! { color: #000; border-radius: 4px; padding: 4px; background-color: #ff0; font-size: 1.2em; }style.css/*.two-two { width: 150px !important; height: 165px !important;}*/body {}.page { //opacity: 0.93;}li.page-list-item { //opacity: 0.93;}script.jsxxx$('head > link[rel=icon]').attr('href','/api/pages/masui/壁紙/icon'); 新規作成ボタンを消す
style.css.new-button { /* 新規ボタンを消す */ visibility: hidden;}音声入力
script.jsxxximport '/api/code/shokai/音声入力Menu/script.js'左上のメニューの右側にプロジェクト名を表示し、それをクリックするとトップに戻る
script.jsxxxvar __title = $('<a>').attr('href','/') //.text('🏠 ' + $('.project-home .title').text()) .text($('.project-home .title').text()) .css('color','#555') .css('font-size','20px') .hover( function () { $(this).css('text-decoration','none'); })var __div = $('<div>') .append(__title) .css('margin-left','40px') .css('margin-top','12px')$('.navbar .container .row .col-brand').append(__div)スクリーンセーバ
script.jsimport 'https://scrapbox.io/api/code/masui/ScrapboxSaver/script.js';script.jsxxxconst intervalPeriod = 10000let isRunning = falselet interval = undefined
scrapbox.PageMenu.addMenu({ title: 'random-screen-saver', image: 'https://gyazo.com/c08a5e4439ded1540bc05b31da9d58c9/raw'})scrapbox.PageMenu('random-screen-saver').addItem({ title: () => (isRunning)? "Stop screen saver." : "Start screen saver!", onClick: () => { if (isRunning) { isRunning = false clearInterval(interval) } else { isRunning = true clickRandomButton() interval = setInterval(clickRandomButton, intervalPeriod) } }})
function clickRandomButton() { const button = $('.random-jump-button') if (!button) return button[0].click()}script.js/*LineId --- 24文字のstring
interface commit.changes { _update: LineId; lines: { origText: string; text: string; };} | { _insert: LineId | "_end"; lines: { id: LineId; text: string; };} | { _update: LineId; lines: { text: string; origText: string; };} | { title: string; titleLc: string;} | { descriptions: string[];} | { links: string[];}*/
scrapbox.PageMenu.addMenu({ title: '履歴スライダー', image: 'https://1.bp.blogspot.com/-UZtkSEX0wh4/U5l5_dNcEsI/AAAAAAAAhWs/UzJGVzyiX8Y/s800/kaichu_dokei.png', onClick: () => { const a = location.href.split('/'); const host = a[2]; const project = a[3]; const page = a[4]; const pageUrl = `https://${host}/api/pages/${project}/${page}`;
fetch(pageUrl) .then(res => res.json()) .then(pageData => { const commitUrl = `https://${host}/api/commits/${project}/${pageData.id}`; return fetch(commitUrl); }) .then(res => res.json()) .then(commitData => { // returns all changes of all commits return commitData.commits.reduce((all, rawCommit) => { const cs = rawCommit.changes.map(rawChange => { const change = {};
if (rawChange._insert) { change.type = '_insert'; change.targetId = rawChange[change.type]; } else if (rawChange._update) { change.type = '_update'; change.targetId = rawChange[change.type]; } else if (rawChange._delete) { change.type = '_delete'; change.targetId = rawChange[change.type]; } else if (rawChange.title) { change.type = 'title'; } else if (rawChange.descriptions) { change.type = 'descriptions'; } else if (rawChange.links) { change.type = 'links'; } else { console.info('unknown type. commit change: ', rawChange); }
if (rawChange.lines) { change.lines = rawChange.lines; }
return change; });
return [ ...all, ...cs, ]; }, []); }) .then(changes => { // 行の文字列のコレクション // - すべての履歴それぞれのtextを順に入れておく const texts = []; // すべてのhistoryを配列で持つ // - [{ id: LindeId, updatedAt: [idx1, ... ], deletedAt?: idx }] const allHistory = changes.reduce((history, change, i) => { if (change.type === '_insert' || change.type === '_update') { texts.push(change.lines.text); } else if (change.type === '_delete') { texts.push(null); } const textLastIndex = texts.length - 1; // console.log({ text: change.lines && change.lines.text, texts, textLastIndex, history });
// 最初のイベントは _insert か _update のはずなのでとにかく保存 if (history.length === 0) { let id; if (change.type === '_insert') { id = change.lines.id; } else if (change.type === '_update') { id = change.targetId; } return [{ id, updatedAt: [textLastIndex] }]; }
if (change.type === '_insert') { const line = { id: change.lines.id, updatedAt: [textLastIndex], };
if (change.targetId === '_end') { history.push(line); } else { const lineIndex = history.findIndex(li => li.id === change.targetId); if (lineIndex === -1) { console.info(`_insert: line index not found. commit change (${i}):`, change); return history; } history.splice(lineIndex, 0, line); } } else if (change.type === '_update') { const lineIndex = history.findIndex(h => h.id === change.targetId); if (lineIndex === -1) { console.info(`_update: line index not found. commit change (${i}):`, change); return history; } history[lineIndex].updatedAt.push(textLastIndex); } else if (change.type === '_delete') { const lineIndex = history.findIndex(h => h.id === change.targetId); if (!lineIndex) { console.info('line index not found. commit change:', change); return history; } history[lineIndex].deletedAt = lineIndex; } else { return history; }
return history; }, []);
// console.log(allHistory); return { texts, allHistory }; }) .then(({ texts, allHistory }) => { const getHistory = time => { return allHistory.reduce((all, line) => { const updated = line.updatedAt.filter(u => u <= time).pop(); const deleted = line.deletedAt <= time; if (!updated || deleted) { return all; } return [...all, { id: line.id, textIndex: updated }]; }, []); }; const showText = time => { return getHistory(time).map(line => { return texts[line.textIndex]; }).join('\n'); }; // console.log(getHistory(100)); // console.log(showText(100));
const historyContainer = document.createElement('div'); historyContainer.classList.add('history-container'); Object.entries({ 'background-color': '#555555', position: 'fixed', 'z-index': '90000', top: '5px', left: '5px', width: 'calc( 100% - 10px )', 'max-height': '100%', border: '3px solid #22cc77', overflow: 'scroll', }).forEach(([key, value]) => historyContainer.style.setProperty(key, value)); document.querySelector('body').appendChild(historyContainer);
const historyCloseButton = document.createElement('button'); historyCloseButton.classList.add('history-close-button'); Object.entries({ 'font-size': '30px', 'line-height': '1em', padding: '0', position: 'fixed', 'z-index': '90001', top: '10px', right: '10px', width: '30px', height: '30px', }).forEach(([key, value]) => historyCloseButton.style.setProperty(key, value)); historyContainer.appendChild(historyCloseButton); historyCloseButton.insertAdjacentText('beforeend', '×');
const historyBackground = document.createElement('div'); historyBackground.classList.add('history-background'); Object.entries({ position: 'fixed', 'z-index': '89999', top: '0', right: '0', width: '100%', height: '100%', 'background-color': 'rgba(255, 255, 255, 0.4)', }).forEach(([key, value]) => historyBackground.style.setProperty(key, value)); document.querySelector('body').appendChild(historyBackground);
const historyPre = document.createElement('pre'); historyPre.classList.add('history-pre'); Object.entries({ width: '100%', 'max-height': '100%', }).forEach(([key, value]) => historyPre.style.setProperty(key, value)); historyPre.insertAdjacentHTML('beforeend', showText(texts.length)); historyContainer.appendChild(historyPre);
const historySlider = document.createElement('input'); historySlider.classList.add('history-slider'); Object.entries({ position: 'fixed', 'z-index': '99999', top: '10px', width: '90%', }).forEach(([key, value]) => historySlider.style.setProperty(key, value)); historySlider.type = 'range'; historySlider.min = '0'; historySlider.max = `${texts.length}`; historySlider.value = `${texts.length}`; historySlider.step = 1; historyContainer.appendChild(historySlider);
const removeHistoryContainer = () => { historyContainer.parentNode.removeChild(historyContainer); historyBackground.parentNode.removeChild(historyBackground); }; historyCloseButton.addEventListener('click', removeHistoryContainer); historyBackground.addEventListener('click', removeHistoryContainer); const updateHistory = e => { const time = e.target.value; historyPre.innerHTML = showText(time); }; historySlider.addEventListener('input', updateHistory); historySlider.addEventListener('change', updateHistory); }); },});