増井俊之
繰り返し実行 (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*="..."]
{display: none !important;}
ScrapExecによるコードブロック評価
script.js
import '/api/code/masui/ScrapExec/script.js'
alert.js
alert('abc');
ScrapCalcによる式評価
script.js
import '/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`)
})
メニューにいろいろ追加
翻訳メニュー
script.js
import '/api/code/masui/Scrapboxテキストを翻訳する/script.js'
横断検索
script.js
import '/api/code/masui/選択テキストから横断検索する/script.js'
使わないPopup Menuを消す
style.css
.popup-menu .strike-button,
.popup-menu .italic-button,
.popup-menu .link-button,
.popup-menu .strong-button {
display: none !important;
}
script.jsxxxx
if(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');
Enterキーで新規ページ作成
不要になったようだ
script.js
/*
$('body').on('keydown',function(e){ // Enterキーで新規ページ作成
if(e.target.tagName != "TEXTAREA" && e.target.tagName != "INPUT"){
if(e.key == 'Enter'){
var project = location.href.split('/')[3];
location.href = `/${project}/new`;
}
}
});
*/
/* $('.btn.btn-default').on('click',function(){ */
$('button').on('click',function(){
var s = $('.form-control').val();
if(s == ''){
var project = location.href.split('/')[3];
location.href = `/${project}/new`;
}
});
新規作成ボタンを消す
style.css
.new-button { /* 新規ボタンを消す */
visibility: hidden;
}
音声入力
script.jsxxx
import '/api/code/shokai/音声入力Menu/script.js'
左上のメニューの右側にプロジェクト名を表示し、それをクリックするとトップに戻る
script.jsxxx
var __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.js
import 'https://scrapbox.io/api/code/masui/ScrapboxSaver/script.js';
script.jsxxx
const intervalPeriod = 10000
let isRunning = false
let 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);
});
},
});