Scrapbox振り返り機能
ちょっと変えた
forEachをflatMapにした
外部projectリンク記法にして、リンクが残っても関連ページリストに出てこないようにした
optionを外部から注入できるようにした
code:js
(async () => {
const {setup} = await import("/api/code/takker/Scrapbox振り返り機能/script.js");
setup({
makeTitle: (today) => ${today} 振り返り,
maxLinePerSection: 16,
});
})();
code:script.d.ts
export interface SetupProps {
/** Page Menuのタイトル */
title?: string;
/** 生成する振り返りページを作る関数
* @param today yyyy-MM-ddという形式の今日の日付の文字列
*/
makeTitle?: (today: string) => string;
/** 各セクションで書き出すリンクの最大数 */
maxLinePerSection?: number;
}
export function setup(props: SetupProps): void;
code:script.js
const day = 60 * 60 * 24 * 1000;
const year = day * 365;
const project_name = scrapbox.Project.name;
const project_root = https://scrapbox.io/${project_name};
// score: 0 is best
const sections = [
{
title: "100日前",
score: (diff) => Math.abs(diff - 100 * day),
},
{
title: "1年前",
score: (diff) => Math.abs(diff - year),
},
{
title: "n年前",
score: (diff) => {
// excludes 1年前
if (diff < year * 1.5) {
return year;
}
const mod = diff % year;
return Math.min(mod, year - mod);
},
},
];
const main = ({makeTitle, maxLinePerSection}) => {
// calc scores
const now = Date.now();
const scored_pages = scrapbox.Project.pages.flatMap((page) => {
const updated = page.updated;
if (updated === 0) return [];
const diff = now - updated * 1000;
const p = { ...page };
sections.forEach((section) => {
});
});
// generate page contents
const lines = sections.flatMap(section => {
return [
section.title,
...scored_pages.slice(0, maxLinePerSection).map((page) => {
const date = strftime(new Date(page.updated * 1000));
return ${date} [/${project_name}/${title}];
}),
"",
];
});
create_page(makeTitle(strftime(new Date())), lines);
};
function create_page(title, lines) {
const body = encodeURIComponent(lines.join("\n"));
window.open(${project_root}/${title}?body=${body});
}
const zero = n => String(n).padStart(2, '0');
function strftime(d, {separator = '-'} = {}) {
return ${d.getUTCFullYear()}${separator}${zero(d.getUTCMonth() + 1)}${separator}${zero(d.getUTCDate())};
}
const WAIT = { title: "Please wait...", image: null, onClick: () => null };
const onClick = (props) => {
scrapbox.PageMenu(props.title).addItem(WAIT);
main(props);
scrapbox.PageMenu(props.title).removeAllItems();
};
export function setup(props) {
const {
title = "振り返り",
makeTitle = (yyyyMMdd) => ${yyyyMMdd}振り返り,
maxLinePerSection = 3,
} = props ?? {};
scrapbox.PageMenu.addMenu({
title,
onClick: () => onClick({title, makeTitle, maxLinePerSection}),
});
}