replace text UserScript
良さそう
スクショを貼る
使い方
選択範囲内の任意の場所に s/<before>/<after>/<flag>
を書き込んでおく
先頭に書かないと認識できないようにした
ボタンを押すと置換する
実装
実装したいアイデア
置換対象の行のみ更新する
Page menuから実行する
mobile版scrapboxからも使えるようにする
global flagを正しく認識できていない
文字列結合→置換→文字列分割という二度手間をやらないと実装できなさそう
とりあえず一行目に正規表現がない限り何もしないようにした
2023-02-14
03:17:39 動いていないっぽい?
一旦機能を変えないverを作って、しばらくそっちを使うことにしよう
script.jsconst replaceReg = /^\s*s\/(.*?)\/(.*?)\/([gimyu]*)\s*$/;
scrapbox.PopupMenu.addButton({
title: text => {
const lines = text.split('\n');
const match = lines.shift().match(replaceReg);
if (!match) return '';
const {index, length, reg} = getParam(match);
const fragments = getFragments(lines.join('\n'), [{index, length}]);
if (!fragments.some(fragment => fragment.replace ? reg.test(fragment.text) : false)) return '';
return 'replace';
},
onClick: text => {
const match = text.match(replaceReg);
if (!match) return;
const {index, length, reg, after} = getParam(match);
const fragments = getFragments(text, [{index, length}]);
// 何も置換しない場合は何もしない
if (!fragments.some(fragment => fragment.replace ? reg.test(fragment.text) : false)) return;
return fragments.map(fragment =>
fragment.replace ?
fragment.text.replace(reg, after) :
fragment.text
).join('');
},
});
置換に使うparameterを抽出する
script.jsfunction getParam(match) {
const {index} = match;
const length = match[0].length;
const [, before, after, flag] = match;
const reg = new RegExp(before, flag);
return {index, length, reg, after: after.replace(/\\n/g, '\n').replace(/\\t/g, '\t').replace(/\\\\/g, '\\')};
}
正規表現で置換する部分に印をつける
script.jsfunction getFragments(text, regLocations) {
const fragments = [];
regLocations = regLocations.sort((a, b) => a.index - b.index);
let lastPos = 0;
for (const {index, length} of regLocations) {
if (index > lastPos) fragments.push({text: text.slice(lastPos, index), replace: true});
fragments.push({text: text.slice(index, length), replace: false});
lastPos = length;
}
fragments.push({text: text.slice(lastPos), replace: true});
return fragments;
}