generated at
pin-diary-6
pin-diaryの実装その6

変更点
機能面は特になし
若干performanceが上がったかも
カスタマイズ性を上げた
日記の形式に関する処理をすべて外部に切り出した
井戸端での設定はこんな感じ
$ deno check --remote -r=https://scrapbox.io https://scrapbox.io/api/code/villagepump/pin-diary-6/script.ts
script.ts
import { launch } from "./mod.ts"; import { makeDiary, isOldDiary, } from "../pin-diary-6%2Ftemplate/mod.ts"; launch( "villagepump", { makeDiary, isOldDiary, }, );
makeDiary isOldDiary を交換すれば、どんな形式のページにも対応できる
井戸端ではpin-diary-6/templateを使っている

井戸端で使用しているscriptの導入方法
2. 生成されたscriptを自分のページのscript.jsから読み込めるようにする
ここは他のUserScriptの導入と同じ
/help-jp/UserScriptなどを参照してください

2024-05-29
17:44:13 update dependencies
2024-05-02
13:36:38 update dependencies
icon,helpfeel,infoboxの情報が正確に反映されるようにした
2023-09-14
07:06:32 convert function to arrow functions
2023-09-04
10:52:35 update dependencies
↑の条件を満たしたときにpin-diaryがエラーを吐く現象を修正しました
2023-08-17
13:08:09 update dependencies
2023-01-03
14:36:29 update dependencies
2022-11-29
12:35:05 scrapbox-userscript-stdのversionを更新
YouTube Shortsのサムネイルに対応できたはず
2022-09-01
13:42:55
scrapbox-userscript-stdのversionを更新
これにより、文字装飾記法に囲まれたアイコン記法をリンクと誤認識しないようになったはず
2022-07-26
08:22:46
scrapbox-userscript-stdのversionを更新
これにより、youtubeのサムネイルが反映されるようになった
型エラーがあったので修正
2022-05-23 17:47:48 破壊的変更:s/ filter / isOldDiary

2022-04-29 11:21:16 ゴールデンウィーク中だけ作らないようにする設定
普通に各自のuserscriptからpin-diary-6を外すだけで十分そうtakker
script2.ts
import { launch } from "./mod.ts"; import { makeDiary, isOldDiary, } from "../pin-diary-6%2Ftemplate/mod.ts"; import isWithinInterval from "https://deno.land/x/date_fns@v2.22.1/isWithinInterval/index.ts"; if (isWithinInterval(new Date(), { start: new Date(2022, 3, 29), end: new Date(2022, 5, 5) })) { launch( "villagepump", { makeDiary, isOldDiary, }, ); }

$ deno check --remote -r=https://scrapbox.io https://scrapbox.io/api/code/villagepump/pin-diary-6/mod.ts
mod.ts
/// <reference no-default-lib="true"/> /// <reference lib="esnext"/> /// <reference lib="dom"/> import { pin, unpin, patch, useStatusBar, sleep, makeSocket, disconnect, format, } from "./deps.ts"; import { listPinnedPages } from "./list.ts"; import type { Scrapbox, Socket } from "./deps.ts"; declare const scrapbox: Scrapbox; export interface DiaryInit { /** 与えられた日付の日記ページのテンプレートを作る */ makeDiary: (date: Date) => { title: string; header: string[]; footer: string[]; },

mod.ts
/** 今日以外の日記ページかどうかを判断する函数 * * @param title 判断対象のページタイトル * @param today 今日の日付 * @param 今日以外の日記ページなら`true`, それ以外のページは `false` */ isOldDiary: (title: string, today: Date) => boolean; } // initialize export const launch = ( project: string, init: DiaryInit & { interval?: number }, ) => { const interval = init.interval ?? 24 * 3600 * 1000; const handleChange = () => scrapbox.Project.name === project ? startObserve(project, interval, init) : endObserve(); handleChange(); scrapbox.addListener("project:changed", handleChange); }; let updateTimer: number | undefined; const startObserve = async ( project: string, interval: number, init: DiaryInit, ) => { endObserve(); await pinDiary(project, new Date(), init); updateTimer = setInterval( () => pinDiary(project, new Date(), init), interval, ); }; const endObserve = () => clearInterval(updateTimer);

mod.ts
export const pinDiary = async ( project: string, date: Date, { makeDiary, isOldDiary, }: DiaryInit, ): Promise<void> => { const { render, dispose } = useStatusBar(); let socket: Socket | undefined; try { // 今日以外の日付ページを外す render( { type: "spinner" }, { type: "text", text: `unpin other diary pages...`}, ); socket = await makeSocket(); for await (const { title } of listPinnedPages(project)) { if (!isOldDiary(title, date)) continue; await unpin(project, title, { socket }); } // 今日の日付ページをピン留めする const { title, header, footer } = makeDiary(date); render( { type: "spinner" }, { type: "text", text: `pin "/${project}/${title}"...`}, ); await pin(project, title, { socket, create: true }); // 今日の日付ページにtemplateを挿入する render( { type: "spinner" }, { type: "text", text: `format "/${project}/${title}"...`}, ); await patch(project, title, (lines) => [ lines[0].text, ...format( lines.slice(1).map(line => line.text), header, footer, ), ], { socket }); render( { type: "check-circle" }, { type: "text", text: `Pinned "/${project}/${title}".`}, ); } catch(e: unknown) { render( { type: "exclamation-triangle" }, { type: "text", text: e instanceof Error ? `${e.name} ${e.message}` : `Unknown error! (see developper console)`, }, ); console.error(e); } finally { if (socket) await disconnect(socket); await sleep(1000); dispose(); } };

list.ts
import { listPages, BasePage } from "./deps.ts"; /** 全てのピン留めされたページを取得する */ export async function* listPinnedPages(project: string, skip = 0): AsyncGenerator<BasePage> { const { count, pages } = await ensureList(project, skip); for (const page of pages) { if (page.pin === 0) continue; yield page; } // pinしたページこれ以上ないときは終了 if ((pages.at(-1)?.pin ?? 0) === 0) return; yield* listPinnedPages(project, skip + 1000); } const ensureList = async (project: string, skip: number) => { const result = await listPages(project, { limit: 1000, skip, }); // login errorなどは全部例外として扱う if (!result.ok) { const error = new Error(); error.name = result.value.name; error.message = result.value.message; throw error; } return result.value; };

deps.ts
export { patchTemplate as format } from "../pin-diary-5/format.ts"; export { pin, unpin, patch, useStatusBar, makeSocket, disconnect, listPages, } from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.26.1/mod.ts"; export type { Socket, } from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.26.1/mod.ts"; export { sleep, } from "https://raw.githubusercontent.com/takker99/scrapbox-userscript-std/0.26.1/sleep.ts"; export type { Scrapbox, } from "https://raw.githubusercontent.com/scrapbox-jp/types/0.7.0/userscript.ts"; export type { BasePage, } from "https://raw.githubusercontent.com/scrapbox-jp/types/0.7.0/rest.ts";

Project開くと必ず動くの、気になるのでそのうちなんとかしたいkuuote
どういうふうにすればいいかなtakker
ステータスを表示しない
多分そういうことじゃない
projectを開く && ある時間帯のみ更新する
必ずPin&Unpinしてるのが気になるなとkuuote
実装未だに読んでなくて申し訳ないけどチェックする方が面倒なら大丈夫です
pin() unpin() は、それぞれすでにpinされている、pinが外れているなら何もしませんtakker
ただし、pageIdやprojectId, userIdを毎回fetchするので、そのoverheadがあるのは否めません
ここはどう実装すべきか悩むところ
外部から pageId などを指定できるようにすればいい?
あ、そうなのか、ならよかったkuuote

UserScript