ミルヒト
https://gyazo.com/371261e4ed49254d50deb184eb0ecba9
#member
ネットウォッチャーから
X(Twitter).icon:ミルヒト(kno32)
https://twilog.togetter.com/kno32
Bluesky.icon:ミルヒト (@miruhito.bsky.social) — Bluesky
様子見中
Cosenseの魔力に呑み込まれた人
メモを作るときに情報がリンクされて得られるイベントにおもしろさを感じる
生成AIをおもちゃにしているけど、情報収集や確認はともかくメモの楽しさには届かない
AIに要約させて貼り付けるとか記載内容からタグを作らせるとかには使う
---
以下、スクリプト
UserScriptは基本拾いもの
ありがたく使わせてもらっている
日付表示形式
/help-jp/日付と時刻を入力する
/villagepump/日記ページへのリンクを出すUserScript
code:script.js
scrapbox.TimeStamp.removeAllFormats()
scrapbox.TimeStamp.addFormat("]YYYY-MM-DD[")
インデント削除 (アウトライナーから)
code: script.js
scrapbox.PopupMenu.addButton({
title: 'インデント削除',
onClick: text => {
text = text.split(/\n/).map(line => line.normalize().replace(/\s{4}/g,' ')).join('\n');
return text;
}
})
選択した文字列へ太字マーカー
/scrasobox/マーカー
code:script.js
// 選択した文字列にマーカー
scrapbox.PopupMenu.addButton({
title: 'マーカー',
onClick: text => [[${text}]]
})
/rashitamemo/長いScrapboxのページを画面下までスクロールさせたい
code:script.js
scrapbox.PageMenu.addMenu({
title: '末尾',
image: 'https://gyazo.com/c5899b2e522db2f5172f52b4fa1e3f48/raw',
onClick: () => {
$("html,body").animate({scrollTop:$('.related-page-sort-menu').offset().top});
}
})
/motoso/Scrapboxで角括弧をリンクに含めるUserScript
code:script.js
scrapbox.PopupMenu.addButton({
title: '全角[ エスケープ',
onClick: (str) => (
// リンクを全角に
str.replace(/(\|\)/g, function(match) {
return match === '[' ? '[' : ']';
})
// hashtagを全角に
.replace(/#/g, '#')
)
});
()ではなく全角の[]にするようにカスタマイズ
リンク以外でも使い道があるので
/shokai/行頭に引用符を付けるUserScript
code:script.js
scrapbox.PopupMenu.addButton({
title: '> ',
onClick: text => text.split(/\n/).map(line => > ${line}).join('\n')
})
日付をリンク化
年月日・スラッシュ区切りの日付をYYYY-MM-DD等に変換する
code:script.js
scrapbox.PopupMenu.addButton({
title: '日付リンク化',
onClick: (str) => {
const pad2 = (value) => String(Number(value)).padStart(2, '0');
const isValidYM = (year, month) => {
const y = Number(year);
const m = Number(month);
return Number.isInteger(y)
&& Number.isInteger(m)
&& y >= 1000
&& y <= 9999
&& m >= 1
&& m <= 12;
};
const isValidYMD = (year, month, day) => {
const y = Number(year);
const m = Number(month);
const d = Number(day);
if (!isValidYM(y, m)) return false;
if (!Number.isInteger(d) || d < 1 || d > 31) return false;
const date = new Date(y, m - 1, d);
return date.getFullYear() === y
&& date.getMonth() === m - 1
&& date.getDate() === d;
};
const isValidMD = (month, day) => {
const m = Number(month);
const d = Number(day);
if (!Number.isInteger(m) || m < 1 || m > 12) return false;
if (!Number.isInteger(d) || d < 1) return false;
// 年がない場合は 2/29 まで許容
const maxDays = 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31;
return d <= maxDaysm - 1;
};
return str
// YYYY年MM月DD日 → YYYY-MM-DD
.replace(/(\d{4})年\s*(\d{1,2})月\s*(\d{1,2})日/g, function(match, y, m, d) {
if (!isValidYMD(y, m, d)) return match;
return '+ y + '-' + pad2(m) + '-' + pad2(d) + '';
})
// YYYY年MM月 → YYYY-MM
.replace(/(\d{4})年\s*(\d{1,2})月/g, function(match, y, m) {
if (!isValidYM(y, m)) return match;
return '+ y + '-' + pad2(m) + '';
})
// MM月DD日 → MM-DD
.replace(/(\d{1,2})月\s*(\d{1,2})日/g, function(match, m, d) {
if (!isValidMD(m, d)) return match;
return '+ pad2(m) + '-' + pad2(d) + '';
})
// YYYY/MM/DD → YYYY-MM-DD
.replace(/(\d{4})\/(\d{1,2})\/(\d{1,2})/g, function(match, y, m, d) {
if (!isValidYMD(y, m, d)) return match;
return '+ y + '-' + pad2(m) + '-' + pad2(d) + '';
})
// YYYY/MM → YYYY-MM
.replace(/(\d{4})\/(\d{1,2})/g, function(match, y, m) {
if (!isValidYM(y, m)) return match;
return '+ y + '-' + pad2(m) + '';
})
// MM/DD → MM-DD
.replace(/(\d{1,2})\/(\d{1,2})/g, function(match, m, d) {
if (!isValidMD(m, d)) return match;
return '+ pad2(m) + '-' + pad2(d) + '';
});
}
});
AI使う際に便利なUserScript
/mrsekut-p/AI使う際に便利なUserScript
テーブル記法を箇条書きに変換する
code:script.js
scrapbox.PopupMenu.addButton({
title: text => /^\s*table:/m.test(text) ? 'table→箇条書き' : null,
onClick: convertTableToBullets,
});
function convertTableToBullets(input) {
const lines = input.split("\n");
return processLines(lines);
}
const processLines = (lines) => {
let tableBaseIndent = null;
const processedLines = lines
.map((line) => {
const { output, newTableIndent } = processLine(line, tableBaseIndent);
tableBaseIndent = newTableIndent;
return { output, isTable: getTableMatch(line) !== null };
})
.filter(({ output, isTable }) => output !== "" || !isTable)
.map(({ output }) => output);
return processedLines.join("\n");
};
const processLine = (line, tableIndent) => {
const tableMatch = getTableMatch(line);
// table:行 - 削除してネスト数を記憶
if (tableMatch) {
return {
output: "",
newTableIndent: tableMatch1.length,
};
}
// テーブル内の行
if (tableIndent !== null) {
return processTableLine(line, tableIndent);
}
// テーブル外の行はそのまま
return {
output: line,
newTableIndent: null,
};
};
const processTableLine = (line, tableIndent) => {
const lineIndent = indentLevel(line);
// テーブル終了判定(ネスト数が同じかそれより少ない)
if (lineIndent <= tableIndent) {
return {
output: line,
newTableIndent: null,
};
}
const cells = line.substring(lineIndent).split("\t");
const bulletLines = cells.map((cell, index) => {
const indent = " ".repeat(index === 0 ? 0 : 1);
return indent + cell;
});
return {
output: indent(bulletLines, tableIndent).join("\n"),
newTableIndent: tableIndent,
};
};
const indent = (lines, indent) =>
lines.map((line) => " ".repeat(indent) + line);
const indentLevel = (line) => {
const match = line.match(/^(\s*)/);
return match ? match1.length : 0;
};
const getTableMatch = (line) => line.match(/^(\s*)table:(.*)$/);
バッククオートをリンクにする
code:script.js
scrapbox.PopupMenu.addButton({
title: text => /[^]+/.test(text) ? '→[]' : null,
onClick: text => {
const result = text.replace(/([^]+)`/g, '$1');
if (text === result) return;
return result;
},
});
コロンで改行する
code:script.js
scrapbox.PopupMenu.addButton({
title: text =>
text.split('\n').some(line => splitTitleBody(line) !== null)
? ':改行'
: null,
onClick: text =>
text
.split('\n')
.map(line => splitTitleBody(line) ?? line)
.join('\n'),
});
// "タイトル: 本文" を "タイトル" + "本文"(1段深い)に分割する
// 区切りコロンがなければ null(=そのままの行を使う)
function splitTitleBody(line) {
const indent, rest = line.match(/^(\s*)(.*)$/);
const sep = findSeparator(rest);
if (!sep) return null;
const title = rest.slice(0, sep.index).trimEnd();
const body = rest.slice(sep.index + sep.length).trimStart();
if (!title || !body) return null;
return [
indent + title,
indent + ' ' + body, // 親より 1 スペース深いインデント=子要素
].join('\n');
}
// コードスパン(...)の外側にある最初の区切りコロンを再帰で探す
// 半角は ": "(コロン+スペース)、全角は ":" を区切りとみなす
function findSeparator(s, i = 0, inCode = false) {
if (i >= s.length) return null;
const c = si;
if (c === '`') return findSeparator(s, i + 1, !inCode);
if (!inCode && c === ':') return { index: i, length: 1 };
if (!inCode && c === ':' && si + 1 === ' ') return { index: i, length: 2 };
return findSeparator(s, i + 1, inCode);
}