replace text UserScript再実装版
バグ修正
機能変更
(置換対象外|置換前後で文字列が変わらない)ときはボタンを表示しない
置換に使った文字列を消さない
2023-04-08 15:35:49 正規表現でないときは、
ReplaceAllで一致した全てを置換するようにする
script.jsimport { exec } from "./mod.js";
scrapbox.PopupMenu.addButton({
title: (text) => exec(text) ? "replace" : "",
onClick: (text) => {
const replaced = exec(text);
if (replaced === undefined) return;
return replaced;
},
});
$ deno check --remote -r=https://scrapbox.io https://scrapbox.io/api/code/takker/replace_text_UserScript再実装版/mod.js
mod.js// @ts-check
/** @param {string} text
* @return {string | undefined} 置換が実行されないときは`undefined`を返す
*/
export const exec = (text) => {
const splitPos = text.indexOf("\n\n");
if (splitPos < 0) return;
const commands = text.slice(0, splitPos).split("\n").map(
(command) => {
const [before = "", after = ""] = command.split(" => ", 2);
return [before, after];
}
);
if (commands.length === 0) return;
let lines = text.slice(splitPos + 2).split("\n");
if (lines.length === 0) return;
for (const [before, after] of commands) {
const match = before.match(/^\/(.*?)\/([gimy]*)$/);
if (match) {
const reg = new RegExp(match[1], match[2]);
lines = lines.map(
(line) => line.replace(reg, after.replaceAll("\\n", "\n"))
);
} else {
lines = lines.map(
(line) => line.replaceAll(before, after.replaceAll("\\n", "\n"))
);
}
}
const newText = `${text.slice(0, splitPos + 2)}${lines.join("\n")}`;
if (text === newText) return;
return newText;
};
$ deno test -r=https://scrapbox.io https://scrapbox.io/api/code/takker/replace_text_UserScript%E5%86%8D%E5%AE%9F%E8%A3%85%E7%89%88/mod.test.ts
mod.test.tsimport { exec } from "./mod.js";
import { assertEquals } from "https://deno.land/std@0.177.0/testing/asserts.ts";
Deno.test("exec()", async (t) =>{
await t.step("置換コマンドの文法チェック", async (t) => {
assertEquals(
exec(
String.raw`/a/g => b
abc`
),
String.raw`/a/g => b
bbc`,
);
await t.step("blank", () => {
assertEquals(
exec(
String.raw`/a/g=> b
abc`
),
undefined,
);
assertEquals(
exec(
String.raw`/a/g =>b
abc`
),
undefined,
);
assertEquals(
exec(
String.raw`/a/g=>b
abc`
),
undefined,
);
});
await t.step("2 blank lines", () => {
assertEquals(
exec(
String.raw`/a/g => b
abc`
),
undefined
);
assertEquals(
exec(
String.raw`abc
/a/g => b`
),
undefined
);
assertEquals(
exec(
String.raw`abc
/a/g => b`
),
undefined
);
});
});
await t.step("samples", () => {
assertEquals(
exec(
String.raw`/\s/g => fuga
hoge hoge hoge`
),
String.raw`/\s/g => fuga
hogefugahogefugahoge`,
);
assertEquals(
exec(
String.raw`/a|\s/g => b
ab a b a aba b a ba bb`
),
String.raw`/a|\s/g => b
bbbbbbbbbbbbbbbbbbbbbbbb`
);
});
});
txtg/cm3 => g\cdot{cm}^{-3}
g/cm => g\cdot{cm}^{-1}
ρ => \rho
τ => \tau
単位をroman体にして数式記法に変換するときに使ったコマンド
$ /\s*(\w+\s?\=\s?[.\d]+)\s?\[([^\]]+)\]\s*/g => [$ $1\mathrm{$2}]