この日記は「日記」なので、日付単位で出している。新しい日付順 (date DESC) かつ、同一日付内では上が古い時系列 (time ASC)。そして日付単位では全てのエントリを出す。

トップページにおいては10日分を一気に表示するようにしてたけど、これだとすごく活発に日記を書いてるときは長大なページになってしまう。

これを若干ややこしい処理にかえた。10日分のエントリをすべてひいてくるが、エントリ数が10以下になるまで日付を減らしていく、というものに。

来週健康診断で気が重い

「公開を遅延」する機能はもともとあったけど、予約投稿もどうせなら欲しいなと思って実装してみた。しかし思ったよりも大変だった。

考えかたとして「予約投稿」で指定した日付に新規投稿されるだけだから、そんなに難しくないのだが、再編集を考慮しはじめると一気に複雑性が増す。

# エントリのステータスとパス(URL)決定ロジック

本プロジェクトにおけるエントリのステータス管理は、「URL(パス)がいつ確定するか」という一点において区別されます。

## 1. コンセプト:URLの確定タイミング

| ステータス | 役割 | URLの確定タイミング |
| :--- | :--- | :--- |
| **`public`** | 即時公開 | **保存時**に確定する。 |
| **`scheduled`** | 公開を遅延 | **保存時**に確定する(公開まで非表示なだけ)。 |
| **`reserved`** | 予約投稿 | **公開当日**の最新番号で確定する(未来の新着として扱うため)。 |

*   **`scheduled`** は「URLを今日の日付で固定したまま、公開だけを未来(30日後など)にしたい」場合に使用します。`public` と同様の扱いです。
*   **`reserved`** は「公開されるその日の新着記事として予約したい」場合に使用します。公開されるまで URL は未確定です。

## 2. URLの不変原則

一度確定した URL (`YYYY/MM/DD/N`) は、**原則として変更されません**。
本文の修正、`public``scheduled` の切り替え、あるいは一旦 `draft`(下書き)に戻して再公開した場合でも、最初期に確定した URL が維持されます。

### 唯一の例外:`reserved` による「未来への移動」
公開済みの記事を `reserved` に変更して未来の日付を指定した場合のみ、URL が変更(再採番)されます。これは、その記事を未来の「新着記事」として扱い直すための特別な操作です。

## 3. 状態遷移の基本ルール

| 行先ステータス | パス (`path`) の扱い |
| :--- | :--- |
| **`draft`** | 既存パスがあれば維持。なければ空。 |
| **`public`** | 既存パスがあれば維持。なければ**保存時**に採番。 |
| **`scheduled`** | 既存パスがあれば維持。なければ**保存時**に採番。 |
| **`reserved`** | 既存パスがあれば維持。ただし無視し、**公開時**にその日の最新番号で採番。 |

## 4. `date` との関係

`path``YYYY/MM/DD/N` の場合、 `date``YYYY-MM-DD` となる

テストも全遷移を一応テストさせている。これに加えて不安なシナリオのテストもある…… golang だと fmt が自動でかかるので空白いれてテーブルテストを成形するのが難しい。しょうがないので文字数をあわせてるけど、LLMはこの手の操作が死ぬほど下手なのがつらい。もっと良い方法あるのだろうか……

	tests := []struct {
		ST        Transition
		SavedPath string
		PubAt     time.Time
		WantStat  string
		WantPath  string
		Name      string
	}{
		//    Transition        SavedPath  PubAt    WantStat  WantPath
		// --- New Entry ---
		{FromTo(NONE_, DRAFT), _____, ZERO_, DRAFT, EMPT_, "New -> Draft"},
		{FromTo(NONE_, PUBLI), _____, ZERO_, PUBLI, GENT_, "New -> Public"},
		{FromTo(NONE_, PUBLI), _____, FUTUR, PUBLI, GENT_, "New -> Public (Future Ignored)"},
		{FromTo(NONE_, SCHED), _____, FUTUR, SCHED, GENT_, "New -> Scheduled"},
		{FromTo(NONE_, RESER), _____, FUTUR, RESER, EMPT_, "New -> Reserved"},

		// --- From Draft ---
		{FromTo(DRAFT, DRAFT), _____, ZERO_, DRAFT, EMPT_, "Draft -> Draft"},
		{FromTo(DRAFT, PUBLI), _____, ZERO_, PUBLI, GENT_, "Draft -> Public"},
		{FromTo(DRAFT, SCHED), _____, FUTUR, SCHED, GENT_, "Draft -> Scheduled"},
		{FromTo(DRAFT, SCHED), _____, FUTUR, SCHED, TODAY + "/1", "Draft -> Scheduled (Path is Today, not Future)"},
		{FromTo(DRAFT, RESER), _____, FUTUR, RESER, EMPT_, "Draft -> Reserved"},

		// --- From Public (URL Immutability) ---
		{FromTo(PUBLI, DRAFT), P2025, ZERO_, DRAFT, KEEP_, "Public -> Draft (Keep URL)"},
		{FromTo(PUBLI, PUBLI), P2025, ZERO_, PUBLI, KEEP_, "Public -> Public (Keep URL)"},
		{FromTo(PUBLI, SCHED), P2025, FUTUR, SCHED, KEEP_, "Public -> Scheduled (Keep URL)"},
		{FromTo(PUBLI, RESER), P2025, FUTUR, RESER, KEEP_, "Public -> Reserved (Keep URL until publish)"},

		// --- From Scheduled (URL Immutability) ---
		{FromTo(SCHED, DRAFT), P2025, ZERO_, DRAFT, KEEP_, "Scheduled -> Draft (Keep URL)"},
		{FromTo(SCHED, PUBLI), P2025, ZERO_, PUBLI, KEEP_, "Scheduled -> Public (Keep URL)"},
		{FromTo(SCHED, SCHED), P2025, FUTUR, SCHED, KEEP_, "Scheduled -> Scheduled (Keep URL)"},
		{FromTo(SCHED, RESER), P2025, FUTUR, RESER, KEEP_, "Scheduled -> Reserved (Keep URL until publish)"},

		// --- From Reserved ---
		{FromTo(RESER, DRAFT), _____, ZERO_, DRAFT, EMPT_, "Reserved -> Draft"},
		{FromTo(RESER, PUBLI), _____, ZERO_, PUBLI, GENT_, "Reserved -> Public"},
		{FromTo(RESER, SCHED), _____, FUTUR, SCHED, GENT_, "Reserved -> Scheduled"},
		{FromTo(RESER, RESER), _____, FUTUR, RESER, EMPT_, "Reserved -> Reserved"},

		// --- From Draft with Path (Previously Published) ---
		{FromTo(DRAFT, DRAFT), P2025, ZERO_, DRAFT, KEEP_, "Draft(P) -> Draft (Keep URL)"},
		{FromTo(DRAFT, PUBLI), P2025, ZERO_, PUBLI, KEEP_, "Draft(P) -> Public (Keep URL)"},
		{FromTo(DRAFT, SCHED), P2025, FUTUR, SCHED, KEEP_, "Draft(P) -> Scheduled (Keep URL)"},
		{FromTo(DRAFT, RESER), P2025, FUTUR, RESER, KEEP_, "Draft(P) -> Reserved (Keep URL until publish)"},
	}

よく昔の日記を検索してはりつけるので、さっさと作ればよかった。

Ctrl-L で起動して、Ctrl-N Ctrl-P で選択し、よくわからんかったら一度 Shift-Enter で別窓で開き、確定なら Enter で挿入できる。すごい便利

スクリーンレコードしたやつを video 要素でそのまま貼る。

↑試しにスクリーンレコード(OBS)したものを以下のように AV1 + webm にして、video 要素ではりつけてみた。107KB

こういうことするとき anigif を貼り付けてたけど、もうそんなことしないでもよい時代になっているか?

$ ffmpeg -ss 1 -i "/Users/cho45/Movies/2026-01-14 23-01-13.mkv" \
	-t "5" \
	-vf "scale=1280:-2" \
	-an \
	-c:v libsvtav1 \
	-crf 45 \
	-preset 4 \
	-svtav1-params tune=0:enable-overlays=1 \
	-pix_fmt yuv420p \
	"./foo.webm"
  1. トップ
  2. tech
  3. 日記の編集画面に過去エントリのリンクを一瞬で貼れる機能をつけた

Gemini はレートリミットはなんかちょっと小賢しい。細かい単位(数十秒程度)でリミットをかけて「AIの思考時間」を装っている感じ。