scrapboxのページを一つにまとめるUserScript
ノートを印刷してチェックしてもらう都合上、そうせざるを得ないので作る。
2022-04-26
10:23:07 リンクを検出する正規表現を直した
2022-04-17
18:08:17 バグ修正
17:45:32 TS化
PopupMenuで使う例
shdeno cache -r=https://scrapbox.io https://scrapbox.io/api/code/takker/scrapboxのページを一つにまとめるUserScript/popupMenu.ts
popupMenu.tsimport { serialize } from "./mod.ts";
import { insertText } from "../scrapbox-userscript-std/dom.ts";
import type { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts";
declare const scrapbox: Scrapbox;
scrapbox.PopupMenu.addButton({
title: "serialize",
onClick: (text) => {
(async () => {
const serialized = await serialize(text, { level: 3 });
await insertText(serialized);
})();
return "";
},
});
mod.tsimport { pool } from "../async-lib/mod.ts";
import { encodeTitleURI } from "../scrapbox-userscript-std/dom.ts";
import type { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts";
declare const scrapbox: Scrapbox;
export interface SerializeOption {
level?: number;
}
export const serialize = async (text: string, options?: SerializeOption): Promise<string> => {
const lines = text.split("\n");
const pooled = pool(
5,
lines,
async (line) => {
const title = line.match(/\[([^\[$!"#%&'()\*\+,\-\.\/\{\|\}<>_~][^\[\]]*)\]/)?.[1];
if (!title) return line;
const res = await fetch(
`/api/pages/${scrapbox.Project.name}/${encodeTitleURI(title)}/text`
);
if (!res.ok) return line;
const [headLine, ...rest] = (await res.text()).split("\n");
return ["[/icons/hr.icon]", `[*** ${headLine}]`, ...rest].join("\n");
},
);
return (await Promise.all([...pooled]))
.map((result, i) => {
if (result.success) return result.value;
// 失敗したら元の文字列を返す
console.warn(result.reason);
return lines[i];
})
.join("\n");
};