![NagiLog — 書いて、貼って、ゆるっと公開。](../img/ogp/nagilog-ogp.png)

**日本語** | [English](README-LOG.en.md)

# NagiLog（個人用LOG）

[![NagiLog v0.13.0](https://img.shields.io/badge/NagiLog-v0.13.0-2563eb?style=flat-square&logo=rss&logoColor=white)](#デモ)
[![NagiManga v0.13.0](https://img.shields.io/badge/NagiManga-v0.13.0-c2410c?style=flat-square&logo=bookstack&logoColor=white)](README.md)
[![Latest release](https://img.shields.io/github/v/release/Lichiphen/NagiSwipe?style=flat-square&logo=github&label=release)](https://github.com/Lichiphen/NagiSwipe/releases/latest)
[![GitHub](https://img.shields.io/badge/GitHub-Lichiphen%2FNagiSwipe-181717?style=flat-square&logo=github)](https://github.com/Lichiphen/NagiSwipe)
[![GitLab](https://img.shields.io/badge/GitLab-lichiphen%2Fnagiswipe-FC6D26?style=flat-square&logo=gitlab&logoColor=white)](https://gitlab.com/lichiphen/nagiswipe)
[![Documentation](https://img.shields.io/badge/docs-nagiswipe.pages.dev-F38020?style=flat-square&logo=cloudflarepages&logoColor=white)](https://nagiswipe.pages.dev/nagilog.html)
[![PHP 8.1+](https://img.shields.io/badge/PHP-8.1%2B-777BB4?style=flat-square&logo=php&logoColor=white)](#設置とログイン)
[![License: MIT](https://img.shields.io/badge/License-MIT-eab308?style=flat-square)](../LICENSE)

文章、画像、漫画を、自分のサイトへ気軽に投稿できるLOGです。NagiSeries（[NagiSwipe](../README.md#nagiswipe)・[NagiManga](README.md)・NagiLog）の1つです。
データベースを使わず、NagiMangaの漫画管理とログインを共用します。
スマホの投稿画面は、NagiMemoの画面構成と操作の分け方を参考にしました。

NagiLogは、NagiManga v0.4.0から配布ZIPに含めています。

[![NagiManga・NagiLog をダウンロード（ZIP）](https://img.shields.io/badge/%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89-NagiManga%E3%83%BBNagiLog%EF%BC%88ZIP%EF%BC%89-c2410c?style=for-the-badge&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyLjYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI%2BPHBhdGggZD0iTTEyIDN2MTIiLz48cGF0aCBkPSJtNiAxMCA2IDYgNi02Ii8%2BPHBhdGggZD0iTTQgMjBoMTYiLz48L3N2Zz4%3D&logoColor=white&labelColor=9a3412)](https://lichiphen.com/tool/link/r/NagiManga)
[![ドキュメントサイト](https://img.shields.io/badge/%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%82%B5%E3%82%A4%E3%83%88-nagiswipe.pages.dev-F38020?style=for-the-badge&logo=cloudflarepages&logoColor=white&labelColor=b45309)](https://nagiswipe.pages.dev/nagilog.html)

<!-- TOC -->
## 目次

- [デモ](#デモ)
- [仕様のまとめ](#仕様のまとめ)
- [画面](#画面)
- [できること](#できること)
- [メリット](#メリット)
- [デメリットと向いている規模](#デメリットと向いている規模)
- [設置とログイン](#設置とログイン)
- [設定と公開範囲](#設定と公開範囲)
- [ローカルで続けて使う](#ローカルで続けて使う)
- [公開URL](#公開url)
- [投稿、画像、漫画](#投稿画像漫画)
  - [見出し](#見出し)
  - [記事の目次](#記事の目次)
  - [投稿のMarkdown](#投稿のmarkdown)
  - [ルビ（読み仮名）](#ルビ読み仮名)
  - [注意書きと図（Mermaid）](#注意書きと図mermaid)
- [閲覧注意（センシティブ・R-18・R-18G）](#閲覧注意センシティブr-18r-18g)
- [SNSや動画の埋め込み](#snsや動画の埋め込み)
  - [ブログカード](#ブログカード)
  - [ページ埋込](#ページ埋込)
- [画像の形式・容量・管理](#画像の形式容量管理)
  - [SVG](#svg)
- [動画と音声](#動画と音声)
- [記事と専用画像を削除する](#記事と専用画像を削除する)
- [カテゴリとハッシュタグ](#カテゴリとハッシュタグ)
- [デザインとキャッシュ](#デザインとキャッシュ)
  - [フッターのリンク](#フッターのリンク)
  - [LiteSpeed Cache](#litespeed-cache)
  - [キャッシュされない表示も速くする](#キャッシュされない表示も速くする)
  - [読み込み中の表示](#読み込み中の表示)
- [追加CSS](#追加css)
  - [構文チェック](#構文チェック)
  - [効き方](#効き方)
  - [保存先と更新](#保存先と更新)
  - [カスタマイズに使えるクラス・要素](#カスタマイズに使えるクラス要素)
- [検索](#検索)
- [一覧の見せ方と関連記事](#一覧の見せ方と関連記事)
- [ピン留め](#ピン留め)
- [パスワード（鍵）](#パスワード鍵)
- [いいね](#いいね)
- [サイドバーの並び替えとHTML枠](#サイドバーの並び替えとhtml枠)
- [タイトルロゴと紹介文](#タイトルロゴと紹介文)
- [ファビコンとホーム画面のアイコン](#ファビコンとホーム画面のアイコン)
- [トップメニュー](#トップメニュー)
- [固定ページ](#固定ページ)
  - [トップページとブログ](#トップページとブログ)
- [SEOとOGP](#seoとogp)
  - [パンくずリスト](#パンくずリスト)
  - [検索エンジンに載せない](#検索エンジンに載せない)
  - [サイトマップ](#サイトマップ)
  - [RSS](#rss)
  - [説明文（description）](#説明文description)
- [画像収集BOTへの対策](#画像収集botへの対策)
- [保存先を守る](#保存先を守る)
- [保存構造とバックアップ](#保存構造とバックアップ)
- [検証と残る確認](#検証と残る確認)
- [参照元と文章](#参照元と文章)
<!-- /TOC -->

## デモ

**https://notebook.lichiphen.com/nagimanga/**

作者が実際に使っているLOGです。公開側の表示、スマホのメニュー、メールのダイアログ、404を試せます。
投稿や設定の画面は、作者だけが使えます。ログインしたときの見え方は、下の「画面」で紹介します。
漫画ビューアーのデモ（[demo.html](https://notebook.lichiphen.com/nagimanga/demo.html)）と同じ設置です。1つの設置で、漫画の管理とLOGの両方が動きます。

## 仕様のまとめ

| 項目 | 内容 |
| --- | --- |
| 版 | 0.9.0（NagiManga v0.9.0に同梱） |
| 動作環境 | PHP 8.1以上（GD・fileinfo・mbstring）。バックアップとEPUBにはZipArchive、HTML枠とSVGにはDOM拡張も使います。HTTPSと、`.htaccess` が効くサーバー（Apache・LiteSpeed）をおすすめします |
| 保存 | データベースを使いません。投稿は1件ずつファイルで保存し、NagiMangaと保存先・ログインを共用します |
| 公開範囲 | 全体公開か、自分専用のMemo（ログインしたときだけ読める）を選べます |
| 投稿 | 本文の1行目がタイトルです。Markdown（太字・斜体・見出し・箇条書き・引用・表など）、URL、ハッシュタグ、漫画カード、埋め込みを使えます。見出しが4つ以上ある記事には目次が付きます。下書き、編集、書きかけの自動保存に対応します。スマホでも書けます |
| メディアの配置 | 画像・動画・音声は本文のカーソル位置に「〔メディア1〕」の行で置き、本文の中の帯をドラッグして動かせます。ドロップ・貼り付けでも追加できます |
| 画像 | JPEG・PNG・GIF・WebP・AVIF・BMPを受け付け、読み直してWebPかJPEGで保存します（4096pxを超える画像は縮小、GIFアニメはGIFのまま）。上限は1〜200MBで設定でき、初期値は30MBです。SVGも内容を検査して取り込めます（2MBまで）。続けて並べた画像はギャラリーになり、NagiSwipeで拡大できます |
| 動画・音声 | 動画はMP4・MOV・WebM、音声はMP3・M4A・OGG・WAV・FLAC（1ファイル1GBまで、分けて送ります）。音声は波形のプレーヤーで、つなぎ目のないループ再生と、ジャケット・ループ位置（`LOOPSTART`）の読み取り・書き込みに対応します。動画は「ふつう」「GIFのように」「自動再生」「くり返し」から再生のしかたを選べます |
| 閲覧注意 | 記事とメディアに、センシティブ・R-18・R-18Gを付けられます。ぼかし・折りたたみ・年齢確認で表示し、共有カードも自動でぼかします |
| 埋め込み | URLを1行に貼るだけで、YouTube・X・Instagram・Spotify・SoundCloud・Bluesky・TikTok など22のサービスと、マンガサイト（少年ジャンプ＋などGigaViewerの19サイト）、動画ファイルを埋め込みます。対応していないページは、OGPを読んだブログカードで表示します |
| URL | 記事は `./20261004123033`、固定ページは `./privacy` のような、`?` のないURLです（`.htaccess` が効くサーバー）。以前の `./?id=…` `./?pg=…` は新しいURLへ301で転送します |
| 一覧と表示 | ミニブログとタイル、3種類のページ送り、ピン留め（複数・並べ替え）、新着の印、関連記事、いいね、シェア、検索、カレンダー。デザインは6種類（ライト3・ダーク3）で、どれもWCAG 2.2 AAの色のコントラストを満たします |
| サイトの作り | 固定ページ（Markdown）、トップページを固定ページにして投稿を `./blog` へ（オン・オフ）、トップメニュー、フッターのリンク、タイトルロゴ、ファビコンとホーム画面のアイコン（1枚から全サイズを作成）、サイドバーの並び替えとHTML枠、プロフィールとリンク集、ブラックホールの404 |
| 管理画面 | 投稿一覧（検索・一括削除）、メディア一覧（検索・差し替え）、カテゴリとハッシュタグの改名・並び替え。表示は日本語と英語から選べます。管理画面を英語にすると、公開ページも英語になります |
| 検索エンジン・共有 | canonical、OGP、パンくずリスト（JSON-LD）、サイトマップ、RSS（全体・カテゴリ・タグ）、すべてのページを検索に載せない設定 |
| 速さ | LiteSpeed Cacheに対応します。版番号付きのJS・CSSは、ブラウザーに1年保存させます。画面の外の記事は後から組み立て、動画・音声は少しずつ配信します |
| 安全 | パスワード、IP制限、試行回数の制限、CSP、画像の読み直し、SVGの検査、画像収集BOTへの対策。ログインは30日（設定で1年）続きます。記事と固定ページには、読者用のパスワード（鍵）をかけられます |
| バックアップ | LOG用ZIPで、投稿・メディア・設定を保存・復元します。復元は画像を少しずつ変換し、進み具合を表示します |
| 規模 | 1人で使う、小さなサイト向けです |

## 画面

投稿欄・設定・画像一覧・固定ページの操作例は、2026年10月7日にローカルで撮影しています。本文や選択項目は説明用の例です。

**パソコン**: 左に投稿、右にプロフィールとリンク集を並べます。記事の上には、投稿した日付を表示します。

![パソコンで見たLOGのトップ。左に投稿、右にプロフィールとリンク集](docs/images/log-pc.jpg)

**スマホ**: 投稿は横幅いっぱいです。右上の「MENU」から、パソコンと同じサイドバーを開きます。
メールのボタンを押すと、アドレスをコピーするか、いつものメールアプリで送るかを選べます。

<table>
<tr>
<td align="center"><img src="docs/images/log-phone.jpg" width="240" alt="スマホで見たトップ"><br>トップ</td>
<td align="center"><img src="docs/images/log-phone-menu.jpg" width="240" alt="MENUを開いた画面。アイコンへ向かう吹き出しとリンク集"><br>MENU</td>
<td align="center"><img src="docs/images/log-phone-mail.jpg" width="240" alt="メールのダイアログ。コピーとメールアプリで送信のボタン"><br>メールのダイアログ</td>
</tr>
</table>

**ログイン中**: トップページの先頭に投稿欄が出ます。画像・動画・音声は本文の下にサムネイルで並び、本文中の「メディア1」のような目印で位置を確認できます。カテゴリや閲覧注意などは、道具のアイコンを押したときだけ下に開きます。選んだ項目は、本文の下にチップで表示します。

下へスクロールすると、サイドバーの右端にそろえた「書く」ボタンが出ます。記事・検索・分類などほかのページには投稿欄を出さず、開いてすぐ「書く」ボタンがふわっと現れます。

<table>
<tr>
<td><img src="docs/images/log-owner-compose.jpg" alt="ログイン中の投稿欄。本文中の画像1の目印と、その下のサムネイル、道具のアイコン"></td>
<td><img src="docs/images/log-owner-fab.jpg" alt="スクロールすると出る書くボタン"></td>
</tr>
</table>

**404**: ブラックホールの中を描いています。ベージュの帯が波打ち、光の波が何度も打ち付けます。

![404ページ。ベージュの帯が波打つ空間](docs/images/log-404.jpg)

## できること

| 機能 | 使い方・表示 |
| --- | --- |
| 投稿と下書き | ログインすると、トップページの先頭で書けます。投稿欄がスクロールで隠れると「ペン＋書く」が出ます。パソコンでは、サイドバーの右端にそろえて出します。ボタンは下からせり上がり、その上に「スパナ＋管理」のボタンが横から出ます。ほかのページでは投稿欄を出さず、2つのボタンが開いてすぐふわっと現れます。 |
| 太字とリンク | 選んだ文字を、道具の列の「B」（太字）で強調できます。トリプルクリックで行ごと選んでも、改行は太字の外に残します。本文のURLはリンクになります。HTMLは文字として表示します。 |
| 埋め込みとカード | URLだけを1行に貼ると、YouTubeやXなどはドメインを見て自動で埋め込みます。ほかのページは、OGPを使ったブログカードで表示します。 |
| 画像 | 選択、ドロップ、貼り付けで追加できます。サムネイルをまとまりごとに並べ、本文中の目印で表示位置を決められます。公開画像はNagiSwipeで拡大・縮小でき、GIFアニメも動いたまま表示します。 |
| 閲覧注意 | 記事と画像に「センシティブ」「R-18」「R-18G」を付けられます。読者には、センシティブは画像をぼかし、R-18・R-18Gは本文を折りたたみ、開く前に年齢を確認します。投稿欄から2回押すだけで付けられます。 |
| 漫画 | 新しい作品から、タイトルと表紙で選べます。本文に漫画カードを表示し、その場でビューアーを開けます。 |
| 編集と差し替え | 投稿を編集できます。「画像一覧・差し替え」で、画像の説明や画像そのものを変更できます。 |
| カテゴリ | 投稿時に作成・選択できます。LOG・投稿の「カテゴリ・タグ」で、名前と並び順を変更できます。 |
| ハッシュタグ | 本文の `#らくがき` などがリンクになります。投稿欄には、直近で使った8件を表示します。LOG・投稿から改名・並び替えできます。 |
| メール | リンク集にメールアドレスを登録できます。押した人は、コピーするか、既定のメールアプリで送るかを選べます。 |
| 検索 | サイドメニューの検索欄から、本文・タイトル・ハッシュタグ・カテゴリ名で探せます。管理画面の投稿一覧にも検索欄があり、下書きも探せます。 |
| サイドメニュー | プロフィールとリンク集、検索、カレンダー、最新の公開投稿3件、カテゴリ、ハッシュタグ、最終更新日を表示します。設定で並び替え・非表示にできます。 |
| HTML枠 | 上級者向けに、グリッドリンク・枠なしバナー・自由なHTMLのテンプレートから追加できます。 |
| スマホ表示 | 投稿は横幅いっぱいです。右上を追尾する、三本線と「MENU」の文字が入ったボタンからメニューを開けます。 |
| デザイン | ライト3種類、ダーク3種類から選べます。アイコンと共通のOGP画像も設定できます。 |
| ファビコン | 512×512pxの画像を1枚選ぶと、favicon.ico、iPhone・Androidのホーム画面用のアイコン、ウェブアプリの設定（manifest）を自動で作ります。 |
| 404 | 見つからないページに、ブラックホールの中を描いたアニメーションを表示します。端末の「動きを減らす」設定にも対応します。 |
| ログインの保持 | 最後にログインした日から30日間、ログインしたままです。設定で1年（365日）にもできます。 |
| 公開範囲 | 全体公開と、自分専用のMemoを選べます。Memoは記事とLOG画像をログイン時だけ表示します。 |
| ページ送り | 一覧の下に「新しい投稿」「過去の投稿」と、1・2・3…のページ番号を出します。全体の件数と今の位置（例: 124件中 51〜60件目）も表示します。記事のページには、前後の投稿と「すべての投稿」を出します。 |
| シェア | 公開中のLOGでは、各記事の下に「Share」と「Copy」を出します。どちらも「記事タイトル＋改行＋記事のURL」を使います。Share は、スマホでは端末の共有画面を、PCではX・はてなブックマーク・LINE・Instagramを選ぶ画面を開きます。Instagramは文を受け取る共有URLがないため、シェア文をコピーしてからInstagramを開く案内を出します。アイコンはサービスの公式ロゴではない独自の絵です（`server/viewer/link-icons/README.txt`）。 |
| いいね | 記事の下の「Share」の左に、ハートのボタンを出します。タップで1つ、長押しで10ずつ増えます。同じ回線・同じ端末から1つの記事に押せるのは1日100までです。設定でオフにできます。数は記事の編集画面で確認・変更・削除できます。 |
| 一覧の見せ方 | 記事を全文で並べる「ミニブログ」と、サムネイル・投稿日・タイトルを並べる「タイル」を選べます。新しい記事には「NEW」の印を付けます（期間と文字は設定で変更）。 |
| 関連記事 | 記事の下に、同じカテゴリやハッシュタグの記事を6件出します。ランダムか、更新が新しい順かを選べます。 |
| ピン留め | WordPressの「先頭に固定」のように、記事をトップページの最初に出せます。いくつでも（30件まで）留められ、管理画面で順番を並べ替えられます。管理画面の投稿一覧でも最上部に出します。 |
| パスワード（鍵） | 記事と固定ページにパスワードをかけられます。読者にはタイトルと入力欄だけを見せ、正しいパスワードを入れた人にだけ本文と画像を表示します。開いた印はクッキーに残し、パスワードそのものはブラウザーに保存させません。 |
| RSS・サイトマップ | LOG全体、カテゴリ別、ハッシュタグ別のRSSを出します。設定画面でURLを作ってコピーできます。検索エンジン向けのサイトマップも出します。 |
| 検索エンジン | 一覧の見せ方に合わせて、検索に載せるページを決めます。二次創作などのために、すべてのページを検索に載せない設定もあります。 |
| 投稿一覧 | 本文を省いた短い行に、日時・タイトル・小さな画像・記事を見る・編集・削除を並べます。いいねがある記事には、ハートと数を出します。一括削除も使えます。 |
| トップメニュー | サイト名の下に、固定ページ・カテゴリ・ハッシュタグなどへのリンクを並べられます。スマホでは左右にスワイプできます。 |
| 固定ページ | プロフィールや利用規約などをMarkdownで作れます。本文に画像を入れ、保存前にプレビューを確認できます。 |
| トップページとブログ | 設定でオンにすると、トップに固定ページを出し、投稿の一覧を `./blog` へ移せます。トップメニューとフッターにブログへのリンクを出せます。 |
| フッター | サイト下部の文章と、HOME・利用規約などへのリンクを別々に設定できます。 |
| バックアップ | LOG用のZIPで、投稿、下書き、画像、分類、公開範囲、表示設定、いいねの数を保存・復元できます。 |

投稿のタイトルは、入力本文の1行目です。
本文は2行目以降を表示し、タイトル行を繰り返しません。
タイトルは通常の見出し文字で表示します。太字やURL・ハッシュタグのリンクは2行目以降の本文で使えます。
タイトル行のハッシュタグも、分類には含めます。
長いタイトルは投稿の見出しに全文を表示し、サイドメニューや共有情報では80文字で省略します。
1行目の画像・漫画タグは本文へ残すので、消えません。
画像だけの投稿は「画像の記録」と表示します。

## メリット

- データベースの準備や移行が不要です。投稿は1件ずつファイルで保存します。
- 公開LOGと、自分だけのMemoを同じ仕組みで選べます。
- 文章、絵、漫画を同じ投稿欄に置けます。画像はまとまりの目印を動かし、漫画はタグを貼り直すと、表示位置を変えられます。
- 公開後に編集してもURLは変わりません。漫画の改題や画像の差し替えでも、本文との結び付きが残ります。
- NagiMangaの認証、画像変換、バックアップを使います。LOGのために別の管理者アカウントや外部サービスを増やす必要はありません。

## デメリットと向いている規模

個人が1人で使う、小さなサイト向けです。
複数の投稿者、コメント、フォローはありません。
検索は、保存した本文から言葉を探す簡単な仕組みです。表記ゆれを広く吸収する全文検索エンジンは使っていません。
大量の投稿や画像、アクセスが集中するサイトでは、ファイルの読み取りや保存時の待ち時間が増えます。
大量データでの負荷試験は、まだ行っていません。

本文は、太字、URL、ハッシュタグ、画像・漫画タグ、埋め込みを使う簡単な形式です。
投稿本文では自由なHTMLや、Wordのような編集機能は使えません。
サイドバーにはHTML枠を追加できますが、使える要素と属性を限定しています。
画像は読み直して保存するため、撮影情報などは残りません。GIFアニメはコマを保ったまま保存します。
SVGも使えますが、内容を検査し、描画に使う要素と属性だけを保存します。元画像を保管したい場合は、別に残してください。

同じ画像タグを使う投稿は、画像を差し替えるとすべて変わります。
一部の投稿だけ変えたいときは、新しい画像として追加してください。
カテゴリやハッシュタグを削除する専用画面はありません。名前変更と、各投稿から外す操作に対応します。

> [!CAUTION]
> 記事の削除は取り消せません。その記事だけで使っていた画像も削除するため、
> 残しておきたい記事や画像は、先にLOGのバックアップを保存してください。

## 設置とログイン

必要なのは、PHP 8.1以上と、GD、fileinfo、mbstringです。
バックアップと復元、漫画EPUBの取り込みにはZipArchiveも使います。
サイドバーのHTML枠とSVGの取り込みには、PHPのDOM拡張も必要です。
HTTPSで使い、保存先にPHPから書き込める権限を付けてください。

1. [配布ZIP（`nagimanga-v0.9.0.zip`）](https://lichiphen.com/tool/link/r/NagiManga)をダウンロードし、中の `nagimanga/` をアップロードします。隠しファイルの `.htaccess` も送ってください。
2. 初回は `/nagimanga/admin/` を開き、FTP で `data/setup-key.php` に書いてある「セットアップの鍵」を貼り付けて、管理者パスワードを決めます。「おもに使うもの」は **NagiLog** を選ぶと、ログインしたときに LOG・投稿の画面が開きます。
3. 表示された管理用URLをブックマークします。初めてログインすると、パスキーか二段階認証の設定をすすめるダイアログが出ます。できるだけ、ここで設定してください。
4. 設定の「共通・安全」にある「公開URL」に、`https://example.com/nagimanga` のように設置先を入力します。`log.php` は付けません。
5. 設定の「LOG」で、公開範囲、サイト名、紹介文、名前、デザイン、アイコンを選びます。
6. `data` が外から読めないことと、画像・漫画の表示を確認します。

製品の既定パスワードはありません。初回に自分で設定します。
管理者パスワードは10文字以上です。初回セットアップでは、現在のIPアドレスだけに管理画面を許可する設定がオンです。必要なら、あとから設定を変えられます。
公開LOGの「アイコン＋ログイン」からは、`admin/login.php` に入れます。
v0.10.0 からは、新しく設置すると「秘密のログイン URL からだけ」がオンで、このリンクと `admin/login.php` は使いません。LOG用には、ログイン URL の後ろに `&p=log` を付けた「NagiLog 用」の URL をブックマークしてください（設定の「ログイン URL」に表示します）。ログイン画面でも、ログイン後に NagiLog と NagiManga のどちらを開くかを選べます。
どちらの入口でも、ログイン条件はパスワード（またはパスキー）、IP制限、試行回数の制限です。
同じIPアドレスから15分以内に5回ログインに失敗すると、一時的にログインできなくなります（IPv6は先頭の/64をひとつとして数えます）。
サイト全体で1時間に40回失敗すると、初めてのブラウザーはしばらく待たされます。一度ログインしたブラウザー（持ち主の印があるもの）、パスキー、許可したIPアドレスからは、そのあいだも入れます。

ログイン状態は、最後にログインした日から30日間続きます。ブラウザを閉じてもログインしたままです。
「設定 → 共通・安全」の「ログインを保つ期間」で、1年（365日）にもできます。

![設定のログインを保つ期間。30日と1年を選べる](docs/images/log-login-days.jpg)

> [!TIP]
> 共用のパソコンでは、使い終わったらログアウトしてください。パスワードを変えると、ほかの端末はログアウトされます。
> 別のブラウザに同じCookieを持ち込んでも、ログインにはなりません。ブラウザの更新でバージョンが変わっても、ログインは続きます。
> ゲスト（閲覧のみ）は、30分操作がないか、入ってから12時間で終わります。
> スマホでIP制限を使うときは、自宅Wi-Fiと携帯回線の違いにも注意してください。

ソースから設置する場合は、`manga/server/` の中身に加えて、リポジトリの
`NagiSwipe-main.js` と `NagiSwipe-main.css` を設置先の `viewer/` にコピーします。
配布ZIPには、この2ファイルを含めています。
既存環境を更新するときは、先にバックアップを取り、プログラムを上書きしてください。
自分の `data/` と `lib/paths.php` は上書きしません。

## 設定と公開範囲

設定は「NagiMANGA」「LOG」「共通・安全」のタブに分けています。
漫画の作品ページはNagiMANGA、LOGの公開範囲やデザインはLOGで設定します。
ログイン、保存先のURL、画像の上限、BOT対策は共通です。
タブを移動しても入力は残ります。キーボードの左右キーでも、タブを移動できます。

保存ボタンは、画面の下に固定した「設定を保存」の1つだけです。3つのタブで変えた設定を、まとめて保存します。
変えたブロックは左端に線が付き、目次にも点が付きます。保存ボタンの横には、まだ保存していないブロックの名前が出ます。
送るのは変えたブロックだけです。どれか1つでも入力に誤りがあると、ほかのブロックも保存しません。そのブロックのタブを開いて誤りを知らせ、入力した内容は画面に残します。
保存すると画面を読み込み直し、サーバーで整えた値を表示します。
管理者パスワードとログインURLの変更は、すぐに効くため、それぞれのボタンで別に行います。

保存していない変更があるまま別のページへ移ろうとすると、確認の画面を出します。「編集に戻る」「保存せずに移動」「保存して移動」から選べます。
メニューやリンク、ログアウトのほか、ブラウザーの「戻る」やスマホの戻るスワイプでも確認します。タブを閉じる・再読み込みするときは、ブラウザーの確認を出します。

設定画面には目次があります。パソコンでは左の列に、3つのタブすべてのブロック名を並べます。
押すとそのタブに切り替えてブロックまで移動し、読んでいるブロックの名前を目次で強調します。
広い画面でも、目次と設定の2列にします。設定のブロックは1列に並べ、入力欄が横に広がりすぎないようにしています。
スマホでは、画面の右下に「目次」のボタンが浮かびます（保存ボタンの上）。押すと目次の画面が開き、1回押すだけで別のタブのブロックにも移動できます。
目次の一番上には「管理画面に戻る」（LOG・投稿）と「公開ページを見る」（新しいタブ）のボタンがあり、スマホの目次の画面にも同じボタンを出します。下までスクロールしていても、すぐに移動できます。
ブロックの中に小見出し（「新着の印」「パンくずリストの先頭」など）があるときは、ブロック名の下にその名前をラベルで並べます。押すとその項目まで移動し、閉じている折りたたみは開きます。目次にはブロック名だけを載せます。

下の例は「LOG」タブを開いた状態です。スマホの目次にも、3つのタブの設定項目をまとめて表示します。

<table>
<tr>
<td><img src="docs/images/log-settings-pc.jpg" alt="パソコンの設定画面。左の目次、3つのタブ、画面下に固定された設定を保存ボタン"></td>
<td align="center"><img src="docs/images/log-settings-phone-toc.jpg" width="240" alt="スマホで設定の目次を開いた画面。管理画面に戻る、公開ページを見る、設定項目の一覧"></td>
</tr>
</table>

LOGは既定で全体公開です。「自分専用のMemo」にすると、記事とLOG画像は管理者だけが読めます。
未ログイン、ゲスト、期限切れのセッションには、一覧・個別記事・分類ページ・画像を404で返します。
ログイン中のページと画像は`private, no-store`、公開ページは`Vary: Cookie`を指定します。
以前からログインしている場合は、管理画面を一度開き直すと、新しいCookieの範囲へ切り替わります。

> [!WARNING]
> Memoを全体公開へ切り替えると、保存済みの記事とLOG画像も公開されます。下書きは公開しません。
> 公開後に誰かが保存した画像や、外部サービスの既存キャッシュは回収できません。
> NagiMANGAの作品は、LOGとは別の公開範囲です。作品のパスワードなどで管理してください。
> Memoでも、保存先への直接アクセス拒否は必要です。後述の「保存先を守る」を確認してください。

サイトのメニューには、未ログインなら「ログイン」、管理者なら「管理ページ」と表示します。
「設定 → LOG → サイドバー・メニュー」で「ログイン・管理ページ」のスイッチをオフにすると、このブロックを隠せます。
入口を隠す場合は、管理URLを先にブックマークしてください。
スイッチをオフにしようとすると、管理用URLを表示した確認が開きます。「URLをコピー」「新しいタブで開く」でブックマークでき、「ブックマークした（隠す）」を選んだときだけオフになります。「まだ（表示したままにする）」やEscキーでは、オンのまま残ります。
ログインしていない状態で管理画面のURL（鍵なし）を開くと、「ログイン」を表示しているあいだは、パスワード欄だけのログイン画面へ移ります。ログイン後は管理画面の投稿一覧を開きます。リンクを隠しているときと、違う鍵を付けたときは、これまでどおり404です。
ログインの入口とパスワードによる保護は、設定をオフにしても残ります。

| 一覧 | 既定の件数 | 変更する場所 |
| --- | --- | --- |
| サイトのトップ・日付・月・カテゴリ・タグ | 10件 | 設定の「LOG → 1ページの投稿数」。共通で1〜100件を指定できます。一覧をタイルにする場合は、偶数がおすすめです。 |
| 管理画面の投稿一覧 | 20件 | 一覧上部の「1ページの表示件数」。1〜100件を指定できます。下には公開ページと同じ番号つきのページ送りを出します（画像一覧も同じ）。 |

管理画面の件数は、そのログインセッションの間だけ記憶します。
公開側の件数とは別なので、読者のページ送りには影響しません。
管理一覧はテーブルを使わず、短い行に日時・タイトル・サムネイル・記事を見る・編集・削除を並べます。
長いタイトルは一覧で省略します。編集画面では元の入力を確認できます。

公開側のページ送りは、「設定 → LOG → 公開範囲・表示件数・ページ送り」で選べます。

| 形式 | 表示 | 向いているLOG |
| --- | --- | --- |
| 番号つき（標準） | 「新しい投稿」「過去の投稿」と、`1 … 5 6 7 … 13` のようなページ番号。8ページ以上あると、ページ番号を入力して移動する欄も出します。 | 投稿が多く、前に読んだ場所へ戻りたい読者がいるLOG |
| 新しい・過去だけ | 「新しい投稿」「過去の投稿」の2つのボタン | 投稿が少ないLOG、すっきり見せたいLOG |
| もっと見る | 押すと、同じページの下に続きの投稿を足すボタン | スマホで続けて読まれるLOG |

どの形式も、ページ送りは普通のリンクです。JavaScriptが動かなくても次のページへ進め、検索エンジンも2ページ目以降をたどれます。
自動で続きを読み込む「無限スクロール」にはしていません。フッターやサイドメニューに届かなくなり、戻ったときに読んでいた位置も失いやすいためです。
「もっと見る」で読み込んだあとは、アドレスを読み込んだページの番号に変えます。再読み込みした場合は、そのページから表示し、「最新の投稿から見る」で先頭へ戻れます。
「新しい投稿」は左、「過去の投稿」は右に固定しています。最初や最後のページでも、押せないボタンとして同じ位置に残すので、続けて押しても位置がずれません。
スマホでは、ページ番号を上に、2つのボタンを下に横幅いっぱいで並べます。

あわせて、次の2つも選べます。どちらも標準はオンです。

- 「124件中 51〜60件目」のような、全体の件数と今の位置
- 記事のページの下に出す、前後の投稿と「すべての投稿」

「すべての投稿」は、サイドメニュー・カテゴリやタグの一覧・記事のページで同じ見た目のボタンにそろえ、全体の件数を添えます。
最後のページより先の番号（例: 投稿が13ページ分なのに `?page=99`）は、空の一覧ではなく404を返します。

## ローカルで続けて使う

作業中のLOGは、`http://127.0.0.1:5197/`で確認できます。
サーバーを終了したあとも、PowerShellでリポジトリのルートから次を実行すると、
同じ投稿・画像・設定を使って再開できます。

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File .\manga\dev\start_preview.ps1
```

どのフォルダーで開いたPowerShellからでも、ファイルの場所を絶対パスで書けば起動できます。
次の例は、リポジトリを`D:\000_tool\NagiSwipe`に置いた場合です。

```powershell
powershell -ExecutionPolicy Bypass -File D:\000_tool\NagiSwipe\manga\dev\start_preview.ps1 -Lan
```

Claude Codeの入力欄で実行するときは、先頭に`!`を付けます。自分で開いたPowerShellでは`!`を付けません。

保存先は`manga/dev/results/log-preview-data`です。2回目以降の起動では、データを作り直しません。
終了は`Ctrl+C`です。すでに5197番でサーバーが動いている場合は、その案内だけを表示します。
別のアプリが使っているときは`-Port 5199`のように番号を変えてください。

初めて起動するときは、このPCにあるサンプル（`manga/dev/sample/`の2つのZIP）から投稿・画像・漫画・設定を復元します。
サンプルは確認用の素材なので、リポジトリと配布ZIPには含めません。ZIPがない場合は、空のLOGで始めます。
サンプルの管理パスワードは`log-test-password`です。このPCで確認するためだけに使ってください。
ZIPはアプリのバックアップ機能で作るため、管理パスワードのハッシュ・秘密鍵・ログイン鍵は含みません。設置のたびに新しく作ります。
サンプルの作成にはPython 3が必要です。

| 追加の指定 | 動き |
| --- | --- |
| `-Lan` | 同じWi-Fiのスマホからも開けるようにし、スマホ用のURLを表示します。スマホで読み込みが終わらないときは、Windowsのファイアウォールが `php.exe` への接続を止めていないか確かめてください（Wi-Fiが「パブリック」のときに起きやすい）。 |
| `-Reset` | サンプルからやり直します。今までの保存先は日時付きの名前で残します。 |
| `-Empty` | サンプルを使わず、空のLOGで始めます。管理URLからパスワードを決めます。 |

今のプレビューの内容を新しいサンプルにするときは、プレビューを起動したまま`python manga/dev/sample_data.py export`を実行します。

`demo-site`の予行演習は、見本漫画用の一時データを毎回作り直す別の道具です。
このLOGを続けて使う場合は、上の起動方法を使ってください。

## 公開URL

| ページ | URLの例 |
| --- | --- |
| トップ | `https://example.com/nagimanga/` |
| 個別投稿 | `https://example.com/nagimanga/20261004123033` |
| カテゴリ | `https://example.com/nagimanga/?category=abcdef123456` |
| ハッシュタグ | `https://example.com/nagimanga/?tag=らくがき` |
| 日付・月 | `?date=2026-10-04` / `?month=2026-10` |
| 固定ページ | `https://example.com/nagimanga/profile` |
| ブログ（[トップページとブログ](#トップページとブログ)をオンにしたとき） | `https://example.com/nagimanga/blog`（カテゴリなどは `./blog?category=…`） |

個別投稿と固定ページは、`?` のないURLです。
同梱の `.htaccess` が `./20261004123033` を記事に、`./profile` を固定ページにつなぎます（Apache・LiteSpeedの `mod_rewrite`）。
今までの `./?id=20261004123033`・`./?pg=profile`・`log.php?id=…` と、末尾に `/` を付けたURLは、新しいURLへ301で転送します。
貼ってあったリンクやブックマークはそのまま使え、検索エンジンも新しいURLへ移します。
`.htaccess` が効かないサーバー（nginxなど）では、`.htaccess` の書き換えが届いていないことをLOGが見分けて、今までどおり `./?id=…` と `./?pg=…` のURLを使います。転送もしません。
固定ページのURL名が `admin`・`viewer` などLOGのフォルダー名と同じ場合や、記事の番号と同じ形の場合は、そのページだけ `./?pg=…` のままにします。新しく付けるURL名には使えません。

記事の上には、個別投稿へのリンクとして日付（例：`2026/10/04`）だけを表示します。時刻は、マウスを重ねると出ます。
投稿番号は、初めて公開した日本時間の年・月・日・時・分・秒です。
同じ秒に重なると `20261004123033-02` のように連番を付けます。
下書きには仮番号を使い、初回公開時に日時の番号へ変えます。
公開後に下書きへ戻した投稿は、再公開しても同じURLです。

以前の `log.php` と `log.php?id=…` は、対応する新URLへ301転送します。
サーバーでは `index.php` をディレクトリの入口にしてください。
PHPのファイル名をURLから外すだけで、安全性が高まるわけではありません。
認証、保存先の保護、入力の検証は別に必要です。

「公開URL」を空欄にすると、アクセス時のHostから共有URLを作ります。
公開前に正しいURLを設定し、canonicalとOGPが自分のドメインになることを確認してください。

## 投稿、画像、漫画

管理者としてログインすると、トップページの先頭に投稿欄が、各記事に編集ボタンが出ます。公開ページ（記事ページや記事一覧）から「編集」を開いた場合は、編集画面の上に「記事ページに戻る」（一覧からなら「公開ページに戻る」）が出ます。これや、スマホの「閉じる」、保存後のダイアログから、元のページの同じ記事の位置に戻れます。管理画面の記事一覧から開いた場合は「投稿一覧に戻る」だけです。
投稿欄が画面の上へ隠れると「ペン＋書く」が表示され、投稿画面を開けます。
トップページ以外（記事、検索、分類、日付、2ページ目以降）では、投稿欄を出さずに「ペン＋書く」をすぐ表示します。
管理一覧では「新しく書く」から開きます。Memoの保存ボタンは「メモを保存」です。

投稿欄は、本文、本文の画像、設定した項目のチップ、道具のアイコン1列でできています。

| アイコン | 動き |
| --- | --- |
| 画像・動画・音声を追加・メディア一覧から選ぶ | 本文のカーソル位置に置きます（下の説明）。動画・音声も同じ列に並びます。 |
| 漫画を選ぶ | 本文のカーソル位置に漫画のタグを入れます。 |
| B・I・リンク | 選んだ文字を太字・斜体・リンクにします。同じボタンをもう一度押すと太字・斜体は外れます。 |
| 装飾（Aと3本線） | 見出し・取り消し線・コード・ルビ・箇条書き・番号付きリスト・引用・表・区切り線・コードブロックを選ぶ画面を開きます（下の「見出し」「投稿のMarkdown」）。スマホでも道具の列が長くならないよう、ここにまとめています。 |
| #・フォルダー・注意の三角・? | 最近のハッシュタグ、カテゴリ、閲覧注意、使い方を、道具の列の下に1つずつ開きます。 |
| 目 | プレビューを開く・閉じる。 |

PCや横向きにした端末では、道具の列を本文欄の上に出し、#などで開く設定もその下（本文欄の上）に開きます。プレビューは本文欄の上の「書く」「プレビュー」のタブで切り替え、本文欄と同じ場所に、同じくらいの高さで表示します（長い記事は枠の中でスクロールします）。目のアイコンでも切り替わります。
見出し（「いま、何を残す？」）の横の「本文へ」を押すと、プレビュー・開いている設定・メディア一覧のタブを閉じ、本文欄が見える位置までスクロールして、カーソルを元の位置に戻します。プレビューや設定を開いているときや、本文欄が画面の外にあるときは、ボタンを色付きにして知らせます。
幅1600px以上のPCでは、記事の編集画面と固定ページの編集画面を広げます（1100px → 1440px）。投稿一覧などの一覧と、トップページの投稿欄はそのままです。
左側には「メディア」の欄を開いたままにします。投稿画面を全画面で開いたときと記事の編集画面では本文の左の列に、トップページの投稿欄では左の余白に浮かべて出します（余白が足りない幅では出しません）。浮かべた欄は、下へスクロールすると上へ隠れ、上へスクロールすると戻ります。
- 「この投稿」のタブ（最初に開くタブ）: 本文に入れたメディアのまとまり（サムネイル・並べ替え・閲覧注意・＋）を、本文欄の下の代わりにここへ並べます。タブの数字は入っているメディアの数です。まだないときは、追加やメディア一覧へのボタンを出します。
- 「メディア一覧」のタブ: 画像・動画・音声を説明文で探して、押すと本文のカーソル位置に入ります。道具の「メディア一覧から選ぶ」はこのタブの検索に移ります。アップロードした分は一覧の先頭に加わります。
本文の左に列があるときは、本文欄を高めにし、「下書き保存」「投稿する」を画面の下に固定します。
スマホを縦にしているときは、道具の列は本文欄のすぐ下で、本文に入れたメディアのサムネイルはその下に並びます。目のアイコンを押すと、プレビューを画面いっぱいに開き、公開ページの記事と同じ大きさで表示します。下の「閉じて編集に戻る」はスクロールしても画面の下に残ります（Escでも閉じます）。プレビューの画像を押すと、公開ページと同じように大きく表示します。開いたまま横向きにすると、「プレビュー」のタブに切り替わります。列に入りきらない道具は横にスクロールでき、続きがある側の端に半透明のグラデーションと矢印を出します（矢印を押しても動きます）。目のアイコンは右端のままです。

カテゴリや閲覧注意を設定すると、本文の下にチップで表示します。チップを押すと、その設定を開きます。
画像・動画・音声（メディア）は、SNSの投稿のように本文欄の下にサムネイルで並べます。本文欄にはメディアのタグを出しません。
メディアは「メディア1」「メディア2」のような**まとまり**ごとに1行で並び、まとまりごとに本文の中の置き場所を決められます。
- 追加したメディアは、本文のカーソル位置に `〔メディア1〕` のような目印の行で置きます。本文の最後に置くときも目印の行を入れるので、本文欄を見れば、どこに入ったかがわかります。
- カーソルの後ろに文があれば、その行の下に目印の行を作ります（行の頭にカーソルがあるときは、その行の上）。文の途中で切ることはありません。カーソルが目印の行にあるとき（すぐ下の行の頭も含む）は、そのまとまりに足します。一度に追加した分は、同じまとまりに入ります。
- 置いた場所は、送っている間から欄の下のメッセージ（「本文のカーソル位置（「〔メディア2〕」の行）に置きます」など）で知らせ、本文の中の帯とその下のまとまりの列を光らせます。帯が本文欄の外にあるときは、見える位置まで本文欄を動かします。
- まとまりの＋から追加したときは、カーソルの位置にかかわらず、そのまとまりに入ります。
- 投稿を開き直したときも、本文の最後のまとまりを含め、すべてのまとまりに目印の行を付けて表示します。
- 「本文の最後へ」で目印の行を消すと、そのまとまりは本文の最後に並びます（目印のないまとまりは本文の最後）。
- 文の途中に置くときは、まとまりの「カーソルの位置へ」で、本文のカーソル位置に目印の行を入れることもできます。保存すると、その行がそのまとまりのタグに置き換わります。
- 別の場所にも置くときは「別の場所にもメディアを置く」を押します。カーソル位置に新しい目印の行と、空のまとまりができます。まとまりの＋から追加します。
- 本文の中の目印の行には、テーマのアクセント色の帯と小さなサムネイルを重ねて表示します。帯をドラッグすると、目印の行を別の行へ動かせます（離した行の上に入ります。最後の行より下で離すと本文の最後）。
- サムネイルをドラッグすると、まとまりの中の並べ替えや、別のまとまりへの移動ができます。スマホは長押ししてから動かします。キーボードでは、サムネイルを選んで左右の矢印キーで並べ替え、上下の矢印キーで前後のまとまりへ移します。
- 右上の×で、その投稿から外せます。ファイルそのものはメディア一覧に残ります。
- 番号は書いているあいだは変えません（消した目印を元に戻すと、同じまとまりに戻ります）。投稿を開き直すと、上から順に振り直します。
- 以前の `〔画像1〕` の形の目印も、そのまま使えます。

メディアを文の途中に置いた例です。本文の目印と、その下のサムネイルの列が対応しています。「本文の最後へ」を押すと目印が消え、本文の最後へ戻します。

<table>
<tr>
<td><img src="docs/images/log-compose-groups.jpg" alt="パソコンの投稿編集画面。本文中の画像1の目印と、対応する画像のまとまり、本文の最後へボタン"></td>
<td align="center"><img src="docs/images/log-compose-groups-phone.jpg" width="240" alt="スマホの投稿編集画面。本文中の画像1の目印、サムネイル、別の場所にも画像を置くボタン"></td>
</tr>
</table>

本文欄に画像タグを手で書いたり貼り付けたりすると、新しいまとまりに移し、タグがあった位置に目印の行を置きます。
以前の書き方の投稿（本文に画像タグを書いた投稿）は、開くと画像の並びごとにまとまりへ分けます。2か所以上に分かれていても、そのまま編集できます。
サムネイルや本文の画像を本文欄へドラッグしても、同じ画像をもう一度アップロードしません。

本文を入れ、「投稿する」か「下書き保存」を選びます。本文の上限は100,000バイトです。
未保存の入力は、このタブの保存領域にも残します。
別の端末への同期や正式なバックアップにはならないので、書き終えたら保存してください。
公開ページの「書く」欄の書きかけは、同じタブで開いた別の記事でも戻します。書きかけがあるあいだは「書く」ボタンに点が付きます。
戻した書きかけは「書きかけを消す」で消せます。
ページを移る前の確認は、そのページで入力したときだけ出します。戻しただけの書きかけはタブに残るため、確認しません。
別タブで先に編集された場合は、その上へ保存せず、開き直すよう案内します。

画像のタグは `[Image:画像番号]`、漫画のタグは `[Mangaタイトル名]` です。
保存される本文では、画像も漫画もこのタグで書かれています。漫画のタグや、以前の書き方の投稿の画像タグは、切り取って貼り直すと本文中の位置を変えられます。
画像タグを改行だけで続けて並べると、正方形のサムネイルを並べたギャラリーにします（NagiMemoと同じ形）。スマホは2列、PCは3枚以上なら3列です。2枚と4枚は、PCでも2列で並べます。あいだに文字があれば別の並びになり、1枚だけのときは今までどおり元の比率で出します。押すと元の画像を拡大表示します。
画像・ギャラリー・漫画のカード・埋め込み・ブログカードのすぐ次の行に書いた文は、空行を挟まずに続けます。間を空けたいときは、空行を1行入れてください。
同名の漫画は、タグに識別番号を添えて区別します。
漫画の改題後も作品IDで結び付けるため、以前の投稿から読めます。

パスワード付き漫画は、公開カードに表紙を出さず、読むときにパスワードを確認します。
個別ページを非公開にした漫画も、カードの表紙には共通画像を使います。
未ログインでは、LOGの下書きと、それだけに使っている画像は404になります。
全体公開のLOGでは、アイコンと共通OGPの画像も公開します。
自分専用Memoでは、この画像も管理者としてログインしたときだけ読めます。
画像一覧からの削除では、投稿、下書き、アイコン、共通OGP、サイドバーで使っている画像を保護します。

### 見出し

本文の行頭に `## ` を付けるとその行は見出し２（h2）、`### ` で見出し３（h3）、`#### ` で見出し４（h4）になります。`#` が1つだけの行はハッシュタグとして扱い、見出しにしません。公開ページでは、見出し２は下線、見出し３は左の線で表示します。

Markdownを書かない場合は、投稿欄の「装飾」を使います。押すと見出しや箇条書きを選ぶ画面が出ます。

- 文字を選んでいるときは、その行を見出しにします。何も選んでいないときは、カーソルのある行です。
- 空の行では `## 見出し` を入れ、「見出し」の部分を選んだ状態にします。そのまま打ち替えられます。
- 同じ見出しをもう一度選ぶと、元の行に戻ります。

「設定 › LOG › 一覧の見せ方・記事の下 › 投稿欄の装飾メニューの見出し」で、画面に出す見出しを選べます。外した見出しも、本文に直接書けば見出しになります。

### 記事の目次

見出し（h2〜h4）が4つ以上ある記事には、記事のページで最初の見出し２の真上に目次を入れます。項目を押すと、その見出しへ移動します。トップやカテゴリなどの一覧には出しません。固定ページにも同じ条件で入ります。

同じ目次を、画面の広さに合わせてもう1つ出します。

- 広いPC（幅1500px以上。幅狭1カラムの固定ページは1200px以上）では、本文の左にスクロールしても付いてくる目次を出します。読んでいる見出しに丸いハイライトが移り、上のバーで読んだ割合を示します。
- それより狭い画面とスマホでは、本文の目次が画面の上へ流れたあと、右下に「目次」ボタンを出します。周りのリングが読んだ割合です。押すと下から目次のシートが開きます。ボタンは、ログインしていなければ「書く」の位置に、ログイン中は「書く」「管理」の上に重ならないように置きます。
- R-18・R-18Gで折りたたんだ記事には出しません。

「設定 › LOG › 一覧の見せ方・記事の下 › 記事の目次」で、「畳んで表示」（初期値）「開いて表示」「表示しない」を選べます。

### 投稿のMarkdown

投稿の本文は、固定ページと同じMarkdownで書けます（書き方の表は「固定ページ」）。投稿では次の点が違います。

- 改行も空行も、書いたとおりに残します。段落には分けません。
- 見出しは `##` からです。`#` が1つだけならハッシュタグです。
- `#タグ` はハッシュタグのリンクになります。URLだけの行は、これまでどおり埋め込みやブログカードになります。
- ```` ``` ```` で囲んだコードの中は、見出しにも埋め込みにもしません。長い行は横にスクロールせず折り返し、枠の右上の「COPY」ボタンでコードをそのままコピーできます（記事・固定ページとも）。

### ルビ（読み仮名）

投稿・固定ページの本文と、投稿のタイトル（1行目）に、青空文庫や小説投稿サイトと同じ書き方でルビを振れます。読み仮名は文字の上に小さく出ます。

| 書き方 | 表示 |
| --- | --- |
| `\|親文字《おやもじ》` | 「親文字」の上に「おやもじ」。`\|` は全角の `｜` でも同じです |
| `漢字《かんじ》` | 《 の直前に続く漢字にだけ振ります（`\|` を省ける書き方）。ひらがなやカタカナが混ざる語は `\|` から書きます |
| `\|《` | 《 をそのまま表示します |

- 投稿欄・固定ページの「装飾 › 文字 › ルビ（読み仮名）」で、選んだ文字に `|…《》` を付け、読み仮名を入れる位置にカーソルを置きます。同じものを選んでもう一度押すと外れます。
- 表の中では `|` が列の区切りになるので、全角の `｜` を使います。コードの中では記号のまま表示します。
- ルビに対応していない表示（RSSを読むアプリなど）では、「親文字（おやもじ）」のように括弧で出ます。
- ページの題名・説明文・検索結果・一覧には、親文字だけを出します。検索は読み仮名でも見つかります（`漢字` も `かんじ` も同じ記事に当たります）。

### 注意書きと図（Mermaid）

投稿・固定ページの本文に、GitHubと同じ書き方で注意書きの箱を、Mermaidと同じ書き方で図を入れられます。

| 書き方 | 表示 |
| --- | --- |
| `> [!NOTE]` | 補足（青） |
| `> [!TIP]` | ヒント（緑） |
| `> [!IMPORTANT]` | 重要（紫） |
| `> [!WARNING]` | 注意（橙） |
| `> [!CAUTION]` | 警告（赤） |
| ```` ```mermaid ```` で囲む | 図（フローチャートとシーケンス図） |

- 注意書きは、1行目に印だけを書き、2行目から `> ` を付けて本文を書きます。印の後ろに文を続けると、ふつうの引用になります。小文字（`[!note]`）でも同じです。
- 注意書きは、点線の枠の上の辺に、見出し（補足・ヒントなど）を丸いステッカーのように貼って表示します。クラス名はGitHubと同じ（`.markdown-alert` `.markdown-alert-note` `.markdown-alert-title` など）なので、GitHub向けに書いたCSSも追加CSSで使えます。英語の公開ページでは、見出しが Note・Tip などになります。
- 図はLOGの中で描きます（外部のライブラリやサービスは使いません）。描けるのは次の2種類です。ほかの種類（`pie` など）は、元の文をそのまま表示します。
  - フローチャート（`graph` / `flowchart`、向きは `TD` `TB` `BT` `LR` `RL`）: 箱の形 `[四角]` `(角丸)` `([丸み])` `((円))` `{ひし形}` `{{六角形}}` `[(円柱)]` `[[二重線]]` `[/平行四辺形/]` `>旗]`、線 `-->` `---` `-.->` `==>` `--o` `--x` `<-->`、線の文字 `-->|はい|` `-- はい -->`、まとめて `A & B --> C`。`classDef` や `style` などの色の指定は使わず、LOGのテーマの色で描きます。
  - シーケンス図（`sequenceDiagram`）: `participant` `actor`（`as` で表示名）、メッセージ `->>` `-->>` `->` `-->` `-x` `-)`、`Note left of` / `right of` / `over`、`loop` `alt` / `else` `opt` `par` / `and` `critical` `break` の枠、`autonumber` の番号。
- 図は本文の幅に合わせて縮みます。箱は小さなカード、注釈は少し傾いた付箋のように描き、色はLOGのテーマに合わせます。追加CSSでは `.log-dg { --dg-edge: …; }` で色を変えられます。
- 図の右上の「拡大」で、図を画面いっぱいに開きます。最初は図そのものの大きさで、縦横にスクロールできます。「−」「＋」（Ctrl＋ホイール、キーボードの `-` `+` でも）で大きさを変え、％の数字を押すと画面に合わせます。スマホで細かい図を読むときに使います。
- 書き間違いで描けない図は、読めなかった行と元の文を表示します。
- 投稿欄・固定ページの「装飾」の「注意書き」と「まとまり › 図（Mermaid）」から入れられます。

## 閲覧注意（センシティブ・R-18・R-18G）

肌の露出が多い絵、性的な絵、流血やグロテスクな絵を、読者が心の準備をしてから見られるようにします。
記事にも画像にも付けられます。画像に付けた区分は、その画像を使うすべての記事・タイル・関連記事に効きます。

| 区分 | 向いている内容 | 読者の見え方 |
| --- | --- | --- |
| なし | ― | そのまま表示します。 |
| センシティブ | 肌の露出、軽い流血など | 画像をぼかし、「押して表示」で開きます。本文はそのまま読めます。 |
| R-18 | 性的な表現 | 本文と画像を折りたたみます。開く前に「18歳以上ですか？」と確認します。 |
| R-18G | 強い流血・暴力・グロテスク | 本文と画像を折りたたみます。R-18と同じく、開く前に年齢を確認します。 |

<table>
<tr>
<td align="center"><img src="docs/images/log-veil-sensitive.jpg" width="240" alt="センシティブの記事。画像がぼかされ、押して表示のボタンがある"><br>センシティブ</td>
<td align="center"><img src="docs/images/log-veil-r18.jpg" width="240" alt="R-18の記事を開こうとしたときの年齢確認"><br>R-18の年齢確認</td>
<td align="center"><img src="docs/images/log-veil-tiles.jpg" width="240" alt="タイルの一覧。閲覧注意の記事はぼかしとラベル"><br>タイル</td>
</tr>
</table>

**付け方**

- 記事ごと: 道具の列の注意の三角を押し、区分を選びます（2回）。任意で「流血表現があります」のような注意書きを40文字まで付けられます。入力欄の下の定型文（流血表現・肌の露出・性的な表現・暴力表現・グロテスク・ホラー・死を扱う内容・虫・苦手な方はご注意ください）を押すと欄に入り、そのまま書き足せます。定型文は「設定 → LOG → 閲覧注意の定型文」で、1行に1つ（40文字まで・30個まで）書き換えられます。空にして保存すると標準の9つに戻ります。「選んだとき、本文の画像にも同じ注意を付ける」がオンなら、その時点の本文の画像にも同じ区分を付けます。
- 画像ごと: 本文の下のサムネイルの左下のボタンを押し、区分を選びます（2回）。1つの記事で、1枚だけ区分を変えることもできます。
- あとから: 「画像一覧・差し替え」で、画像ごとに変えられます。

記事に付けた区分と画像の区分のうち、強いほうを記事の区分として使います。強さは、なし → センシティブ → R-18G → R-18 の順です。
たとえば、記事は「なし」でも、R-18の画像を1枚含むなら、その記事はR-18として折りたたみます。
投稿欄のチップには、画像から決まった区分を「R-18（画像）」のように表示します。

**読者の側**

- 一度開くと、「このブラウザでは、次から確認せずに表示しますか？」と聞きます。選ぶと、そのブラウザでは同じ区分を最初から表示し、タイルのぼかしも外します。ページの下の「閲覧注意を毎回確認する」で戻せます。
- R-18・R-18Gの年齢確認は、そのタブを閉じるまで覚えます（どちらかで答えれば、もう一方でも聞きません）。「このブラウザでは次から確認しない」にチェックすると、その区分は次から聞かずに開きます。
- 覆っている間は、画像の拡大用リンクを外しています。NagiSwipeで隣の画像へめくっても、まだ開いていない画像は出ません。
- JavaScriptが動かないブラウザでも、押せば開きます（`<details>`）。その場合、年齢確認は出ません。

**共有と検索**

| 場所 | 閲覧注意のある記事 |
| --- | --- |
| OGP（共有カード） | 注意のない画像があれば、その最初の1枚を使います。注意つきの画像しかない記事（記事全体に注意を付けた記事も）は、その画像を強くぼかし、区分の名前を重ねたWebPを自動で作って使います（下の「SEOとOGP」）。パスワード（鍵）をかけた記事は、注意の有無にかかわらず最初の画像をぼかし、鍵の印を重ねます。 |
| 説明文・RSS | R-18・R-18Gは本文を出さず、「閲覧注意（R-18）の記事です。」と注意書きにします。センシティブは今までどおりです。 |
| 検索エンジン | R-18の記事は`noindex,follow`にし、サイトマップにも載せません。 |
| タイル・関連記事 | サムネイルをぼかし、区分のラベルを重ねます。 |
| 管理画面 | ぼかさずに表示し、区分のラベルと「読者には…表示します」の案内を出します。投稿一覧のタイトルにも区分を添えます。 |

> [!WARNING]
> 閲覧注意は、読者が見る前に準備するための表示です。アクセス制限ではありません。
> 画像のURLを直接開けば見られますし、年齢確認は自己申告です。公開できない画像は、そもそも投稿しないでください。
> タイトル（本文の1行目）は折りたたまずに表示します。タイトルにはきつい言葉を入れないでください。

## SNSや動画の埋め込み

URLだけを1行に貼ると、ドメインを見て自動で埋め込みます。特別な書き方はいりません。
URLを貼ると埋め込まれる仕組みは、ほかのブログやCMSにもよくある機能です。NagiLogでは独自に組み立てており、埋め込みに対応していないページも、OGPを読んだブログカードで表示します（下の「ブログカード」）。
文の途中に書いたURLは、埋め込まずに普通のリンクにします。紹介したいときは単独の行に、話の中で触れるだけなら文中に書いて使い分けます。

| 埋め込むもの | 貼るURLの例 |
| --- | --- |
| YouTube（動画・ショート・ライブ・再生リスト、`t=`の開始位置） | `https://youtu.be/動画ID`、`https://www.youtube.com/watch?v=…` |
| ニコニコ動画 | `https://www.nicovideo.jp/watch/sm9`、`https://nico.ms/sm9` |
| Spotify（曲・アルバム・プレイリスト・アーティスト・ポッドキャスト） | `https://open.spotify.com/track/…` |
| Apple Music（曲・アルバム・プレイリスト） | `https://music.apple.com/jp/album/…` |
| Amazon Music 日本版（曲・アルバム・プレイリスト） | `https://music.amazon.co.jp/albums/…?trackAsin=…`、`https://music.amazon.co.jp/playlists/…` |
| SoundCloud（公開曲・プレイリスト） | `https://soundcloud.com/ユーザー名/曲名`、`https://soundcloud.com/ユーザー名/sets/プレイリスト名` |
| YouTube Music（曲・動画・プレイリスト） | `https://music.youtube.com/watch?v=…`、`https://music.youtube.com/playlist?list=…` |
| Bandcamp（曲・アルバム） | `https://アーティスト名.bandcamp.com/track/…`、`/album/…` |
| TikTok（動画・写真の投稿） | `https://www.tiktok.com/@ユーザー名/video/番号`、`/photo/番号` |
| Blueskyの投稿 | `https://bsky.app/profile/アカウント名/post/投稿ID` |
| Mastodonの公開投稿 | `https://サーバー名/@ユーザー名/投稿番号` |
| Mixcloud（公開番組・プレイリスト） | `https://www.mixcloud.com/ユーザー名/番組名/`、`/playlists/名前/` |
| Audiomack（曲・アルバム・プレイリスト） | `https://audiomack.com/ユーザー名/song/…`、`/album/…`、`/playlist/…` |
| Facebook（公開投稿・動画・リール） | `https://www.facebook.com/ページ名/posts/投稿ID`、`/videos/動画ID`、`/reel/動画ID` |
| Threadsの公開投稿 | `https://www.threads.com/@ユーザー名/post/投稿ID`（`threads.net`も対応） |
| Vimeoの動画 | `https://vimeo.com/動画ID`（限定公開のハッシュ付きURLも対応） |
| Twitch（配信・録画・クリップ） | `https://www.twitch.tv/チャンネル名`、`/videos/動画ID`、`https://clips.twitch.tv/クリップID` |
| X（Twitter）のポスト | `https://x.com/ユーザー名/status/番号` |
| Instagramの投稿・リール | `https://www.instagram.com/p/…`、`/reel/…` |
| CodePen | `https://codepen.io/ユーザー名/pen/…` |
| note、Voicy、Steam | 記事・チャンネル・ストアのページのURL |
| マンガ（少年ジャンプ＋などGigaViewerの19サイト） | `https://shonenjumpplus.com/episode/番号` |
| 動画ファイル（mp4・webm・ogv・mov・m4v） | `https://example.com/movie.mp4` |

1行目が埋め込みのURLだけの投稿は、「YouTubeの記録」のようなタイトルになります。説明文では「（YouTube）」と表示します。
配色がダークのときは、Xの埋め込みもダーク表示にします。プレビューでも埋め込みを確認できます。

Amazon Musicは、曲を聴いているときの「共有」からコピーしたリンクを、そのまま1行に貼れます。
たとえば、`https://music.amazon.co.jp/albums/B0CY5SN6Y4?trackAsin=B0CY5ST1FH` は「ポッケ村のテーマ」のプレーヤーになります。
曲の指定がないアルバムのリンクや、プレイリストのリンクは曲一覧を表示します。
Amazon公式の試聴プレーヤーなので、フル再生を保証するものではありません。
投稿の配色を変えても、プレーヤー内部はAmazonのデザインのままです。
`music.amazon.co.jp` の通常の共有リンクに対応しています。短縮URLは、開いた先のURLを貼ってください。

SoundCloudも「共有」でコピーした通常のリンクを、そのまま1行に貼れます。
たとえば、`https://soundcloud.com/sei_peridot/sets/peritunematerial` は、曲一覧のあるプレイリストになります。
曲は波形が見えるプレーヤーで表示し、ページを開いただけでは再生しません。
文の途中のURLは普通のリンクのままです。短縮URLは、開いた先のURLを貼ってください。
非公開リンクには対応していません。埋め込みを許可していない曲や削除された曲は、SoundCloud側の表示に従います。

YouTube MusicのURLは、YouTubeのプレーヤーで表示します。
Bandcamp、Bluesky、Mastodonは、保存やプレビューのときに曲や投稿の情報を確認します。
確認できないときは、元のページを開くリンクを表示します。
たとえばMastodonは、サーバーが返す公式の埋め込み先が、その投稿と一致するかを確認します。
外部から受け取ったHTMLを、そのまま本文へ貼ることはありません。

確認した情報は`data/log/embeds/`に保存します。1週間以内の再保存では取り直しません。
取得に失敗した場合は、翌日以降に保存やプレビューを開くと再確認します。
ブログカードと同じく、取得先の公開アドレス、時間、転送回数、容量を制限します。
読者が投稿を見るときは、保存済みの情報を使い、外部へは問い合わせません。
バックアップの復元などで引っ越した直後は、この情報がありません。管理者としてログインした状態で記事や一覧を開くと、足りない分をその場で取りに行きます（投稿を保存し直しても取り直します）。

追加したサービスの枠には、元の投稿を開くリンクも付けます。
Facebookの枠は、投稿の中身に合わせて高さを変えます。
Facebook、Instagram、Threadsなどは、公開設定、ログイン状態、地域やCookieの設定で表示が変わることがあります。
短縮URLや共有画面専用のURLは、通常の投稿URLに開き直してから貼ってください。
Twitchは設置先のドメイン名を自動で指定します。公開サイトはHTTPSで開いてください。
Twitchの枠は最小400×300pxです。縦向きの小さいスマホ画面ではプレーヤーを出さず、「横向きにすると表示されます」という案内とTwitchで開くリンクを表示します。

埋め込みの枠は、URLから読み取ったIDを使って、このプログラムが組み立てます。
本文に`<script>`を書き出すことはありません。X、Instagram、noteの公式スクリプトは、その埋め込みがあるページだけで`viewer/log-embed.js`が読み込みます。
セキュリティ設定（CSP）で、埋め込みの枠は上の各サービスだけ、外部のスクリプトはX・Instagram・noteだけに限っています。
YouTubeは、Cookieを使わない`youtube-nocookie.com`で埋め込みます。

埋め込みを表示すると、訪問者のブラウザが各サービスへ接続します。IPアドレスなどがそのサービスに伝わり、サービス側のCookieが使われる場合もあります。
削除された投稿や非公開の投稿は、各サービスの表示に従います。必要に応じて、サイトのプライバシーポリシーに書いておいてください。

### ブログカード

埋め込みに対応していないURLを1行に貼ると、そのページのOGP（タイトル・説明・サイト名・画像）を使ったカードで表示します。
OGPがないページは、`<title>`と説明文を使います。取得できないページは、普通のリンクのままです。

ページを読みに行くのは、管理者が投稿を保存したときと、プレビューを開いたときだけです。訪問者がページを見るたびに外部へ取りに行くことはありません。
取得した内容は`data/log/cards/`に保存し、1週間たってから保存し直したときに取り直します。読めなかったページは、翌日以降の保存で再び試します。
カードの画像は、このサーバーに取り込んで縮小し、読み直して保存します。訪問者のブラウザは外部サイトへ接続せず、画像の中に隠したデータも残りません。

外部のページを読み込むため、次の制限を設けています。

<details><summary>ブログカードを取りに行くときの制限</summary>

- 読みに行けるのは`http`と`https`の80番・443番ポートだけです。URLにユーザー名やパスワードを含むものは読みません。
- 名前解決した先が、ループバック、社内向けの範囲、リンクローカル（クラウドのメタデータを含む）、CGNAT、予約済みの範囲なら読みません。確かめたアドレスにだけ接続し、名前解決のすり替えも防ぎます。
- 転送は3回まで、転送先も同じように確かめます。ページは1MB、画像は8MBまで、1回の保存で10件・合計20秒までです。
- 文字コードはShift_JISやEUC-JPにも対応します。カードの文字はHTMLとして解釈せず、エスケープして表示します。

</details>

LOGのバックアップには、カードの保存内容は含めません。引っ越し先では、その投稿を保存し直すとカードを作り直します。

### ページ埋込

上の一覧にないページも、`[ページ埋込]URL[/ページ埋込]` を1行に書くと、枠に入れて本文の中に表示できます。ブラウザーで遊ぶゲームのように、画面いっぱいに広がるページを貼るときに向いています。投稿でも固定ページでも使えます。

| 書き方 | 表示 |
| --- | --- |
| `[ページ埋込]https://example.com/game/[/ページ埋込]` | 横長（16:9）の枠 |
| `[ページ埋込 4:3]https://example.com/game/[/ページ埋込]` | 枠の形を指定（`16:9` `4:3` `3:2` `1:1` `2:3` `3:4` `9:16` `21:9`） |

- 最初は表紙を表示し、読者が「ページを読み込む」を押したときに初めてページを読み込みます。重いゲームを、スクロールしただけで読み込まないためです（スマホではメモリーが足りないとページが閉じることがあります）。表紙には、ブログカードと同じように取りに行ったページのタイトルと画像を出します。
- 枠の下の「全画面」で、枠を画面いっぱいに広げます。全画面の機能がないブラウザー（iPhoneなど）では、ウィンドウいっぱいに広げます。右上の「閉じる」で戻ります。
- 枠の高さは画面の高さの8割までで、縦長の枠は幅を狭めて収めます。枠の下に、新しいタブで開くリンクを付けます。
- 英語では `[Embed]URL[/Embed]` とも書けます。投稿欄・固定ページの「装飾 › まとまり › ページ埋込」からも入れられます。
- ページは、このサイトの `embed.php` を通して枠に入れます。`embed.php` が開くのは、このサイトが本文を表示するときに署名したURLだけなので、ほかの人がこのサイトのアドレスで別のページを見せることはできません。公開ページのCSPに相手のサイトを足す必要もありません。
- 枠の中のページは、スクリプト・保存（セーブ）・全画面・ゲームパッドを使え、新しいウィンドウも開けます。枠の中のページが、このサイトのページを別のページに移すことはできません（v0.12.0 から。読者がリンクを押しても同じです）。外へのリンクは、新しいタブで開くもの（`target="_blank"`）にしてください。
- 相手のサイトが枠に入れることを禁じている（`X-Frame-Options` や CSP の `frame-ancestors`）ページは表示できません。その場合は枠の下のリンクから開いてもらいます。

## 画像の形式・容量・管理

画像はJPEG、PNG、GIFに加えて、WebP、AVIF、BMPを受け付けます。WebP・AVIF・BMPの取り込みには、サーバーのGDが各形式の読み込みに対応している必要があります。取り込んだ画像はサーバーで読み直して保存し、WebPを書き出せる環境ではWebP、それ以外ではJPEGに変換します。縦か横が4096pxを超える画像は、Xと同じく4096×4096に収まるよう縮小してから保存します（縦横比はそのまま、透過も保ちます）。ファイルが軽くなり、スマホでも拡大表示が崩れにくくなります。縦に長い画像は、横幅もそれに合わせて小さくなります。GIFアニメと、NagiMANGAの漫画のページは縮小しません。

2コマ以上のGIFアニメは、GIFのまま保存します。本文の小さな表示も、NagiSwipeでの拡大表示も動きます。
GDはアニメーションを書き出せないため、GIFの中身を区切りごとに読み、絵を描く部分だけで組み直します。
コマの画像、表示時間、繰り返しの指定は残し、コメント、独自のデータ、終わりの印より後ろのデータは捨てます。
画像に紛れ込ませたPHPやHTMLは、この組み直しで残りません。配信も`image/gif`と`nosniff`の指定で行います。
コマは3,000枚まで、コマ数×縦×横は15億画素までです。1コマだけのGIFや、形の崩れたGIFは、これまでどおりWebPかJPEGに変換します。

画像の上限は「共通・安全 → 設置先と画像アップロード」で1〜200MBに設定できます。初期値は30MBです。PHPの`upload_max_filesize`もアップロードできる容量に影響します。画像は一辺16,000px、総画素数5,000万までです。画像処理に必要なメモリが足りない場合も取り込めません。

画像の画質も共通設定で調整でき、60〜100の範囲で指定します。初期値は90です。

「メディア一覧・差し替え」（以前の「画像一覧・差し替え」）は1ページ40件で、一覧の上の「1ページの表示件数」で1〜100件に変えられます（ログイン中は覚えます）。上の検索欄では、画像の説明（最初はファイル名）、その画像を使っている記事のタイトル、アイコン・共通OGP・サイドバーでの使用、追加した日付で探せます。「使用中・未使用」と「注意あり・なし」（閲覧注意）でも絞り込めます。説明を保存したり画像を削除したりしたあとも、同じ検索結果とページに戻ります。各画像の説明を300文字まで編集でき、使用件数と、使っている記事（編集画面へのリンク）、アイコン・共通OGP・サイドバーでの使用状況を確認できます。「画像を差し替える」から選ぶほか、差し替えたい画像の枠へ新しい画像をドラッグ＆ドロップしても差し替えられます。画像を差し替えると、同じ画像タグを使う投稿や設定すべてに反映されます。削除できるのは未使用の画像だけです。投稿、下書き、アイコン、共通OGP、サイドバーで使っている画像は削除できません。

「メディア一覧・差し替え」の上の「メディアだけを追加」に画像をドロップする（この画面のどこへドロップしても同じです）か、「ファイルを選ぶ」から選ぶと、投稿を書かずに画像だけを追加できます。複数枚まとめて追加できます。サイドバーのHTML枠、固定ページ、タイトルロゴなどに使う画像を先に置いておけます。画像の枠の上にドロップした場合は、これまでどおりその画像の差し替えです。追加しただけの画像は、投稿・サイドバー・固定ページ・設定のどこかで使うまで、公開ページでは404です（ログイン中は見られます）。各画像の「URL」「Markdown」ボタンで、`./?media=…` のURLと、固定ページに貼る `![説明](./?media=…)` をコピーできます。

画像一覧では、上の枠から画像だけを追加し、検索欄で必要な画像を探せます。各画像の「URL」「Markdown」は、固定ページやHTML枠へ貼る文字列のコピーに使います。「画像を差し替える」は、すでに使っている画像の内容を変更します。

![画像一覧をpancakeで検索した例。画像だけを追加する枠、絞り込み、画像の説明とURL・Markdownのボタン](docs/images/log-media-library.jpg)

### SVG

SVGもアップロードできます（投稿、画像一覧、アイコン、タイトルロゴ）。SVGは絵ではなく文書なので、プログラムやほかのサイトへの参照を入れられます。そこで取り込む前に簡易のウイルスチェックをし、次のものが見つかったSVGは理由を表示して取り込みません。

<details><summary>取り込まないSVG（理由を表示して断ります）</summary>

- `<script>`、`<foreignObject>`（HTMLの埋め込み）、`<iframe>`・`<embed>`・`<object>`、HTMLの要素
- `onload` `onclick` などイベントで動く属性（大文字・小文字を問いません）
- `javascript:` `vbscript:` `data:text/html` などのURL（空白や文字参照で崩したものも含みます）
- ファイルの外を読む参照（`<image>` `<use>` `<feImage>` の外部URL、CSSの `@import`、外部の `url()`、`image-set()`）。参照できるのはファイルの中の `#id` と、ファイルに埋め込んだ画像（`data:image/png;base64,…` など）だけです
- `href` やイベントを書き換えるアニメーション（`<animate attributeName="href">` `<set attributeName="onclick">`）
- DOCTYPE・ENTITY宣言（外部ファイルの読み込みや、展開で膨らませる攻撃に使われます）、`<?xml-stylesheet?>` などの処理命令
- CSSのエスケープ（`u\72l(` のように、上の言葉を隠す書き方）
- 圧縮SVG（SVGZ）、2MBを超えるもの、要素が5万を超えるもの、大きさ（width・height か viewBox）のないもの

</details>

チェックを通ったSVGも、そのまま保存しません。描画に使う要素と属性だけを書き出し直し、Inkscape・Illustratorの編集用データ、コメント、`<metadata>`、未知の名前空間は捨てます。リンク（`<a>`）は外して、中の絵だけを残します。グラデーション、フィルター（影など）、クリップ、マスク、`<style>`、テキスト、SMILのアニメーションはそのまま使えます。拡張子が `.png` でも中身がSVGなら同じチェックをし、拡張子が `.svg` でも中身がHTMLなら取り込みません。

公開ページはSVGを `<img>` で表示するので、ブラウザーはSVGの中のプログラムを動かしません。画像のURLを直接開いた場合に備えて、SVGは `Content-Security-Policy: default-src 'none'; …; sandbox` と `nosniff` を付けて配信します。SNSはSVGのOGP画像を表示しないため、共通のOGP画像にはSVGを選べず、記事のOGPにもSVGは使いません（共通の画像になります）。バックアップから復元するSVGも、アップロードと同じチェックを通します。

## 動画と音声

投稿欄の「画像・動画・音声を追加」、ドロップ、貼り付け、またはメディア一覧の「メディアだけを追加」から、動画と音声も追加できます。画像と同じく本文の下のまとまりに並び、記事では画像のまとまりとは別の行にプレーヤーを出します。

| 種類 | 形式 |
| --- | --- |
| 動画 | MP4（iPhoneのMOVを含む）、WebM |
| 音声 | MP3、M4A、OGG、WAV、FLAC |

- 形式は、ファイル名ではなくファイルの先頭の中身で確かめます。動画・音声に見せかけたファイルは断ります。
- 大きなファイルは、ブラウザがサーバーのアップロード上限より小さく分けて送り、サーバーでつなぎます。途中で一部が届かなかったときは、その部分だけ送り直します。1ファイル1GBまでです。
- 長さ、動画の縦横、音声の波形は、アップロードのときに管理画面のブラウザで一度だけ測って保存します。読者が記事を開くたびに音声を解析しないので、軽く表示できます。150MBを超える音声は波形を測らず、細いバーで表示します。
- 音声のファイルにジャケット画像が入っていれば（MP3・M4A・FLAC・OGG・WAV）、取り出してプレーヤーの左に出します。OGGは `METADATA_BLOCK_PICTURE`（または `COVERART`）、WAVは `id3 ` チャンクの画像を読みます。なければ曲名と波形だけのすっきりした形です。制作途中の音源も、そのまま載せられます。
- 曲の中にループ位置が書かれていれば、アップロードのときに読み取って保存します。ゲームの曲で使う `LOOPSTART` と `LOOPLENGTH`（または `LOOPEND`）のタグ（OGG・FLAC・MP3のTXXX・M4A）と、WAVの `smpl` チャンクの最初のループに対応しています。値はサンプル数で、ファイルのサンプリング周波数から秒に直します。
- ジャケットとループ位置の書き込み: 投稿画面のサムネイル右下のボタンか、メディア一覧の「ジャケットとループ位置」で、曲のファイルそのものにジャケット画像とループ位置を書き込めます（MP3・M4A・FLAC・OGG・WAV）。ほかのタグや音はそのまま残し、書き込んだファイルでサーバーのファイルを差し替えます。「書き込んだファイルを保存」で、手元に保存することもできます。
  - ジャケットは、1200pxを超える画像を縮めてJPEGで入れます。「ジャケットを外す」で取り除けます。
  - ループ位置は「分:秒.ミリ秒」か秒で書き、下の再生位置を「今の位置」で入れられます。「つなぎ目を聞く」で、ループの終わりの3秒前から再生し、始まりへ戻るところを確かめられます。再生バーは指を離した位置から鳴らし、ループの終わりより後に動かしたときは、曲の最後まで流してからループへ入ります。ファイルには `LOOPSTART` と `LOOPLENGTH`（サンプル数）で入れ、WAVには `smpl` チャンクも入れます。
  - 書き込む形式: MP3はID3v2（APIC・TXXX）、M4AはiTunesの項目（covr・----）、FLACはPICTUREとVORBIS_COMMENT、OGG（Vorbis・Opus）は `METADATA_BLOCK_PICTURE` とコメント、WAVは `id3 ` チャンクと `smpl` チャンクです。書き込んだあと、もう一度読み取って確かめてから送ります。
- 動画は、最初のほうのコマを表紙にします。表紙は一覧のタイル、OGPの画像にも使います。
- 曲名・動画のタイトルは、最初はファイル名（拡張子を除く）です。メディア一覧の「タイトル」で変えられます。

> [!TIP]
> 動画も音声も、届いたファイルをそのまま保存します。レンタルサーバーには変換の仕組みがないためです。再生できるかは見る人のブラウザ次第で、たとえばHEVC（H.265）で撮ったiPhoneの動画は、Androidやパソコンでは映らないことがあります。迷ったらH.264のMP4にしてください。

記事のプレーヤーは、サイトのデザインの色に合わせて表示します。

- 音声: 再生ボタン、波形、時間を1行に並べます。波形がそのまま再生位置のバーで、押した場所から再生します。キーボードでは左右の矢印で5秒、Home・Endで最初と最後へ動きます。ループ再生中にループの終わりより後へ動かすと、そこから曲の最後まで流してから、ループの始まりへ戻ります。
- ループ再生: 音声の右端のボタンで、1曲をくり返します。押すと曲をブラウザで一度だけ読み込んで（Web Audio）、サンプル単位でつなぐので、くり返しのつなぎ目に隙間ができません。ループ位置のある曲は、最初から再生してループの終わりまで来ると、ループの始まりへ戻ります（イントロは1回だけ）。8分を超える曲や、ブラウザが読めない形式は、メモリを使いすぎないよう、ふつうの再生のままくり返します（この場合はつなぎ目に一瞬の間ができます）。iPhoneでは、マナーモードでも音が出るようにしています（ふつうの再生と同じ）。
- 動画: 表紙の中央に大きな再生ボタンを出し、再生中は下に操作バー（再生、再生位置、時間、音量、全画面）を出します。操作が止まると隠れ、マウスを動かすか画面をタップすると戻ります。縦に長い動画は、縦横比のまま中央に置きます。
- 動画の再生のしかた: 投稿画面のサムネイル右下のボタンか、メディア一覧の「再生のしかた」で選びます。「ふつう」「GIFのように（見えたら音なしで自動再生し、くり返す）」「自動再生（見えたら音なしで1回）」「くり返し（再生ボタンで、音ありでくり返す）」の4つから選び、右のプレビューですぐ確かめられます。「ふつう」と「くり返し」は、最初は音を消しておくこともできます。その動画を使うすべての記事に効きます。
- 自動再生は、ブラウザの決まりで音なしで始まります。動画が半分以上見えている間だけ再生し、画面の外では止めます。音なしで再生している間は右上に「音を出す」ボタンを出します。読者が止めた動画は、また見えても勝手には動き出しません。動きを減らす設定（prefers-reduced-motion）の読者には自動で再生しません。音なしの動画は、ほかのプレーヤーを止めません。
- 同時に鳴るのは1つだけです。別のプレーヤーを再生すると、前のものは止まります。
- 閲覧注意を付けると、プレーヤーを折りたたんで表示します。
- 途中から再生できるよう、配信はRange（ファイルの一部だけを返す仕組み）に対応しています。1回に返すのは512KBまでで、続きはプレーヤーがあらためて求めます。スマホのブラウザは、ファイル全体を求めたあと途中で受け取りを止めることがあり、全体を返そうとするとサーバーのPHPがその接続で待ち続けるためです。iPhoneのSafariは、これがないと動画を再生しません。画像収集BOTへの対策は、再生の途中の読み込みを数えません。
- LOGのバックアップには動画と音声も入ります。ファイルが大きいとバックアップのZIPも大きくなるので、復元するサーバーのアップロード上限に注意してください。

## 記事と専用画像を削除する

投稿一覧の「削除」で、1件の記事を削除します。
ログイン中は、公開ページの各記事（一覧と個別ページ）の上にも「編集」と並んで「削除」が出ます。確認のあと削除して、公開ページのトップに戻ります。
「まとめて削除」を開くと、記事を選んで一度に削除できます。
選んでいる間は、ボタンが濃い色の「× 選ぶのをやめる」に変わり、削除のバーは赤みのある色で表示します。
「このページをすべて選ぶ」は、今のページにある記事だけが対象です。
確認画面に選択件数を表示し、実行前に削除を確かめます。
最初はキャンセルボタンに選択を置きます。Escキーでも取り消せます。

選んだ記事の原本と、その記事だけで使っていた画像・縮小画像・画像情報・保存受付記録を削除します。
ほかの記事や下書き、アイコン、共通OGP、サイドバーでも使う画像は残します。
本文の原本から共有を確認するため、一覧用ファイルが古くても共有画像を保護します。
無関係な未使用画像、漫画の原本、カテゴリ設定、セキュリティログは消しません。

選んだ全記事の更新番号を確認してから削除します。
別の画面で更新された記事が含まれていれば、全体を中止します。
途中の移動や一覧更新に失敗した場合は、移した記事と画像を戻します。
正常に終わると一時フォルダを消し、空になった年・下書きフォルダも整理します。
保存先の権限不足や処理の強制終了では、掃除や復旧が完了しない場合があります。

削除した記事の古い編集欄からは保存できません。
新規投稿欄の再送防止記録も整理するため、古い新規投稿欄を再送すると新しい記事になる場合があります。
同じ秒のうちに削除・再投稿した場合は、削除した投稿番号を再び使う場合があります。
削除後は古い投稿欄を閉じ、画面を開き直してください。

## カテゴリとハッシュタグ

カテゴリの選択・新規作成は、投稿欄の「カテゴリを選ぶ・作る」から行えます。
新規作成では「日記、制作メモ」のように「、」で区切れます。
カテゴリ名は40文字まで、1投稿に20個までです。

本文の `#らくがき` や `#制作メモ` は、同じタグの投稿を読むリンクになります。
タグ名には、文字、数字、アンダースコアを使えます。長さは60文字までで、区切りは空白や句読点です。
URL内の `#`、画像タグ、漫画タグは、ハッシュタグとして数えません。
投稿欄の最近使ったタグを押すと、本文に挿入できます。

「LOG・投稿 → カテゴリ・タグ」で名前を変更できます。
持ち手をドラッグするか、上下ボタンで並び順を変えられます。
マウスとタッチに対応し、並び替えた順番はその場で保存します。
カテゴリはサイトのメニューと投稿欄へ、ハッシュタグはサイトのメニューへ反映します。
記事の下には「カテゴリ」の見出しに続けて、フォルダのアイコンとカテゴリ名を表示します。複数あるときは「,」で区切ります。
サイドバーでは、カテゴリをフォルダのアイコンと件数付きの一覧に、ハッシュタグを「#」付きの文字の並びにして、見分けやすくしています。
投稿欄の直近8件のハッシュタグは、手動の順番に変えず、使用履歴から表示します。
別の画面でも分類を変えていた場合は保存せず、画面を開き直すよう案内します。
カテゴリの改名後も、URLの番号は同じです。
ハッシュタグの改名は、公開済みの本文と下書きにも反映します。
改名前のハッシュタグURLからは、自動転送しません。

## デザインとキャッシュ

ライトブルーが標準です。ほかにライトセージ、ライトペーパー、
ダークネイビー、ダークチャコール、ダークプラムを選べます。
色見本を押すとラジオボタンも選ばれ、その画面で見比べられます。
公開サイトへの反映は保存後です。スマホではラジオボタンを色見本の下に置きます。

6種類のテーマはどれも、WCAG 2.2のレベルAAの色のコントラストを満たします。
文字は背景に対して4.5:1以上（大きな文字は3:1以上）、入力欄の枠・スイッチ・キーボード操作の枠は3:1以上です。
入力欄の中の例文（プレースホルダー）、検索で見つかった語の印、通知、閲覧注意の画面、ホバー中の表示も含めて確かめています。
閲覧注意の画像の上の文字は、画像が真っ白でも読めるよう、影の濃さを決めています。
NagiMANGAの管理画面（ライト・ダーク）も同じ基準です。

スマホでは、サイト名の行だけを右上の「MENU」ボタンと重ならない幅にし、紹介文は画面の右端まで使います。
サイト名が8文字以上のときは、文字数から幅を見積もり、1行に収まる大きさまで小さくします（最小15px）。行間も詰めています。それでも入らない長さのときは、行間を詰めたまま折り返します。

「LOG → サイト下部の表記」で、フッターの文章の表示・非表示と文章を変更できます。
標準の文章は「Powered by NagiLog＆NagiManga」です。以前の標準「Powered by NagiManga / NagiSwipe」のまま保存していたサイトも、新しい標準の表示に変わります。200文字までの1行で入力でき、HTMLは文字として扱います。
空欄にすると、この文章は表示しません。フッターのリンクは別に設定します。各ソースのライセンス表記はそのまま残ります。

404は、ブラックホールの中をSVGとCSSで描きます。中の様子には諸説ありますが、何十ものベージュが波打つ美しい空間という説を形にしました。
6つの束に分けた36本の帯が、それぞれ違う速さと向きで流れます。数秒ごとに光の波が左から何度も打ち付け、帯は上から順に大きく波打ってから静まります。
ぼかしの効果は使わず、帯の移動と伸び縮みだけで動かすため、ちらつきが出にくい作りです。
外部画像やJavaScriptを読み込まず、端末の「動きを減らす」設定ではアニメーションを止めます。
ページの内容を示さない通常の404応答と、検索から除外する指定は共通です。

スクロールバーは、各配色に合わせた丸い形です。見た目はブラウザによって異なります。
JSとCSSのキャッシュバスターは、内容の変更に応じて変わる更新番号です。
更新番号は`data/asset-versions.php`に控え、ファイルの大きさと更新日時が変わったときだけ計算し直します。
更新番号の付いたJS・CSS・SVG・PNGは、Apache・LiteSpeedの`.htaccess`でブラウザーに1年保存させます（`max-age=31536000, immutable`）。ページを移るたびの確認の通信がなくなります。ページ本体は今までどおり毎回確認します（`no-cache`）。
漫画CSSだけの変更も、読み込み用JSの更新番号へ反映します。
差し替えた画像のURLにも新しい版番号を付けます。
共有先サービスのOGPキャッシュを強制的に消す機能はありません。

### フッターのリンク

「設定 → LOG → フッターのリンク」で、ページの一番下に利用規約やプライバシーポリシーなどのリンクを並べられます。
作り方は[トップメニュー](#トップメニュー)と同じです。表示名に固定ページやカテゴリの名前の一部を入れて候補を選び、ドラッグか矢印のボタンで並べ替えます。反映するには、画面下の「設定を保存」を押します。

先頭には、家のアイコンと「HOME」のトップへのリンクを出します。この文字はパンくずリストの先頭と同じで、「一覧の見せ方・記事の下」で変更できます。トップへのリンクだけをオフにすることもできます。
リンクは左から順に表示し、スマホでは入りきらない分を折り返します。「サイト下部の表記」で文章を隠しても、ここで設定したリンクは表示します。

### LiteSpeed Cache

LiteSpeedのサーバーでは、公開LOGのページをサーバー自体がキャッシュし、PHPを動かさずに返します。
LiteSpeedかどうかは自動で判断します。LiteSpeedでないサーバーでは何も送らず、これまでどおりに動きます。
設定の「共通・安全 → LiteSpeed Cache」で、使っているかどうかを確認できます。LiteSpeedのサーバーでは、ここからオフにもできます。

| ページ | キャッシュ |
| --- | --- |
| ログインしていない人が見る公開LOG（トップ・記事・分類・日付） | する（1時間） |
| 管理画面、ログイン中の表示、ゲスト | しない |
| 自分専用のMemo、404 | しない |
| 投稿画像・カード画像 | しない（画像収集BOTへの対策をPHPで続けるため）。代わりに閲覧者のブラウザーへ1日保存させます |

ログインCookieを持つ人は、キャッシュとは別に扱います。キャッシュした訪問者用のページが、管理者に表示されることはありません。
管理画面で投稿・画像・漫画・設定を変えたり、復元したりすると、LOGのキャッシュを消します。消し方は変更の種類で分けています。

| 変更 | 消し方 |
| --- | --- |
| 公開する投稿の新規・編集、サイト名やデザイン、サイドバー、フッター、分類の並び・名前、画像の追加と説明、漫画の作成・編集 | 次の1人には前のページをすぐ返し、そのあいだに新しいページを作ります（LiteSpeedの`stale`） |
| 記事の削除、下書きへの保存、公開範囲・表示件数・ページ送りの保存、復元、画像や漫画の削除、作品の公開設定やパスワード | すぐに消します。消したものは1回も表示しません |

投稿の直後に見に来た人も、作り直しを待たずに表示できます。
見せたくない内容を記事から消すときは、記事を削除するか下書きに戻してください。すぐに表示されなくなります。記事の修正だけの場合、直後の1人には修正前のページが1回表示されることがあります。
カレンダーの「今日」を正しく保つため、キャッシュは1時間で作り直します。
FTPでプログラムを上書きした場合も、プログラムのファイルの更新日時が変わったことを最初の表示で見つけ、古いキャッシュを1回だけ消します。
同梱の`.htaccess`に、LiteSpeedのときだけ働く`CacheLookup on`を入れています。サーバー側でキャッシュ機能が無効の場合は、この設定も働きません。

### キャッシュされない表示も速くする

サーバーのキャッシュを使えない表示（ログイン中、画像、検索の1回目、投稿直後など）のために、次の工夫をしています。

| 対象 | 工夫 |
| --- | --- |
| 投稿画像 | URLに版番号が入っているため、ブラウザーへ1日保存させます（`Cache-Control: public, max-age=86400`）。`ETag`と`Last-Modified`も付け、1日を過ぎても変わっていなければ、本体を送らない304で返します。ページを移っても、同じ画像は取り直しません。非公開にした画像は、保存の確認より先に公開状態を調べるため、404になります |
| 最終更新日 | 画像や漫画を保存した時刻を`data/content-updated.txt`の1か所に記録し、表示のたびに全部の画像・作品の情報を開かないようにしました |
| 検索 | 投稿を保存するたびに、検索用にそろえた本文を`data/log/search.php`へまとめます。検索のたびに全部の投稿を開かずに済みます。古い・壊れた検索用ファイルは使わず、投稿を直接読んで探し、次の保存で作り直します |
| 画像収集BOTへの対策 | 取得回数の記録は、閲覧者（IP）ごとの小さなファイルをその場で書き換えます。全員で1つの順番待ちをしないため、画像を並行して返せます |
| 1回の表示 | 投稿の一覧、設定、分類、サイドバーは、1回の表示の中で1度だけ読みます。表示中に保存したときは読み直します |
| 読み込むJS | 画像ビューア（NagiSwipe）は画像へのリンクがあるページだけ、漫画リーダーは漫画のあるページだけ読みます。「もっと見る」の続きがあるページとログイン中は、今までどおり両方読みます |
| 最初の画像 | ページの1枚目の画像は後回しにせず、優先して読み込みます |
| 読み込むCSS | 投稿画面と管理画面だけで使う見た目は`viewer/log-owner.css`に分け、ログイン中と管理画面だけで読みます。閲覧者が読むCSSは約125KBから約70KBに減りました |
| 画面の外 | 2件目からの記事は、画面に近づいてから組み立てて描きます（`content-visibility:auto`）。記事の多いページも最初の表示が速くなります。NEWの印が付いた記事は、記事の上にはみ出す印が欠けないよう対象外です。スマホのメニューも、閉じている間は組み立てを後回しにします |

ログイン中の管理者の表示や管理画面の画像は、これまでどおりブラウザーにも保存させません（`private, no-store`）。

### 読み込み中の表示

投稿画面・固定ページの編集・画像一覧で、アップロードや保存、プレビューを待っている間は、メッセージの前に小さな波が流れます。
ページを移るとき、1秒以上かかった場合だけ、画面の下に読み込み中の表示を出します（テーマの色の水滴が広がる輪と、上端を流れる細い光）。すぐに開くページでは何も出しません。画像の拡大表示・漫画・新しいタブ・ダウンロードでは出さず、15秒たっても移らないときは消します。「視差効果を減らす」設定の端末では動きを止めます。

## 追加CSS

公開LOGの見た目を、自分で書いたCSSで調整できます。
「設定 → LOG」の「追加CSS」にある「追加CSSを編集」を押すと、同じタブで専用の編集ページが開きます。

![追加CSSの編集ページ。「公開ページに適用中」と「適用を止める」、保存・CSSファイルを選ぶ・保存したCSSをダウンロード・公開ページを開くのボタン、行番号と色分けの付いた編集欄](docs/images/log-css-editor.jpg)

| 操作 | 内容 |
| --- | --- |
| 入力 | 直接入力のほか、.cssファイルのドラッグ＆ドロップか「CSSファイルを選ぶ」で読み込めます。スマホではファイル選択を使います。読み込むと編集中の内容と置き換え、未保存の編集があるときは先に確認します |
| 上限 | UTF-8で256KiBです。ファイルは読み込む前に、保存する内容はサーバーでも確かめます |
| 編集欄 | 行番号と色分けがあります。入力を止めて0.3秒ほどで構文を確かめ、エラーと警告の一覧を押すとその場所へ移ります。Tabで字下げします（Escのあとに押すと次の項目へ移ります）。Ctrl+S（Macは⌘S）でも保存できます |
| 保存 | 「保存」で公開ページに反映します。保存に失敗しても、編集中の内容は画面に残ります |
| 適用のオン・オフ | 「適用を止める」で、保存した内容を残したまま公開ページから外します |
| 一覧の形ごとの適用 | 「ミニブログのとき」「タイルのとき」のチェックで、設定の「一覧の形」ごとに読み込むかを選びます。チェックを外した形のときは、一覧・記事・固定ページのどれにも読み込みません。最初は両方オンです |
| ダウンロード・復元 | 保存したCSSを.cssファイルでダウンロードできます。「直前の保存に戻す」で、1つ前に保存した内容と入れ替えます |

追加CSSは管理画面には適用しません。公開側のデザインが崩れても、編集ページから直したり、適用を止めたりできます。

> [!IMPORTANT]
> 構文エラーがあると保存せず、公開中のCSSをそのまま使います。

### 構文チェック

| 種類 | 対象 | 保存 |
| --- | --- | --- |
| エラー | コメント・文字列・url()・かっこの閉じ忘れ、対応する相手のない閉じかっこ、セレクターのない「{」、「:」のない宣言、ルールの外に書いた宣言、「{ }」のないセレクター | しない（行・列・理由を表示） |
| 警告 | 開いているブラウザーが知らないプロパティ・値・セレクター・@ルール、ほかのルールより後ろの@import、ほかのサイトのURL | できる |

エラーの判定は、編集ページとサーバーが同じ規則で行います。
警告の判定には、ブラウザーの`CSS.supports()`を使います。新しいCSS、CSS変数、ブラウザーごとの接頭辞（`-webkit-`など）は、そのブラウザーが知らなくてもほかのブラウザーで使えることがあるため、拒否しません。
ページによって表示されない要素（記事の下、固定ページ、ログイン中だけの表示など）もあるため、セレクターが「存在しない」とは判定しません。

### 効き方

- 公開LOGのページ（一覧・記事・固定ページ・検索・アーカイブ）に、LOG本体のCSS（`viewer/log.css`）と画像ビューアーのCSSのあとで読み込みます。漫画ビューアーのCSSはあとから読み込まれますが、追加CSSより前に入れます。
- 同じ詳細度なら追加CSSが勝ちます。本体のほうが詳細度の高いセレクターや`!important`を使っている場合は、追加CSSが効かないことがあります。そのときは、セレクターをより具体的にします（例：`.log-site .log-post`）。
- CSS変数（`--log-accent`など）を上書きすると、テーマの色をまとめて変えられます。テーマごとに変えるときは`html[data-log-theme="dark-navy"]`のように書きます。
- `url()`の相対パスは、LOGのトップ（`log.php`のあるフォルダ）が基準です。例：`url(viewer/og.jpg)`。LOGに載せた画像は、`./?media=…`のURLを使えます。
- 公開ページのCSP（Content-Security-Policy）は、追加CSSのために緩めません。画像はこのサイトと`data:`、フォントと`@import`はこのサイトのファイルだけを読み込めます。ほかのサイトの画像・フォント・CSSは読み込まれません。
- CSSは`./?css=内容のハッシュ`から`text/css`で配信し、ブラウザーに1年保存させます。内容を変えるとURLも変わるため、古いCSSが残りません。LiteSpeed Cacheを使っている場合は、保存・オンオフ・復元のたびにページのキャッシュを消します。
- 404のページ、NagiMangaの作品ページ（`read.php`）、ほかのサイトに埋め込んだビューアーには適用しません。

### 保存先と更新

追加CSSは`data/log/custom-css/`に、LOG本体のCSSとは別に保存します。
使用中の内容と直前の内容を、内容のハッシュを名前にした`.css`ファイルで置き、どちらを使うかを`state.php`に書きます。アップロードしたファイルの名前は使いません。
新しい内容を書き終えてから`state.php`を切り替えるため、途中で失敗しても直前の有効なCSSが残ります。
`data/`は外から読めないままで、配信は`./?css=`の処理だけが行います。保存した内容をPHPとして実行することはありません。
保存には、ほかの設定と同じログイン・ゲストの拒否・CSRF対策・ロックを使います。ほかのタブや端末で先に保存されていた場合は、どちらを残すかを選べます。

更新（管理画面からの自動更新・更新の取り消し・FTPでの上書き）は`data/`に触れないため、追加CSSは変わりません。
配布ZIPに利用者のCSSや、その保存先を上書きするファイルは入っていません。本体を更新しても、追加CSSを自動で直したり初期化したりしません。
LOG用のバックアップZIPには、追加CSSと適用のオン・オフを含めます。上書きで復元すると戻ります。上書きしない復元では、まだ追加CSSを保存したことがない場合だけ入れます。追加CSSを含まない旧形式のZIPでは、今の追加CSSを維持します。

### カスタマイズに使えるクラス・要素

編集ページの下に、カスタマイズ向けの公開セレクターとCSS変数の一覧があります。用途、対象の画面、記述例、追加したバージョンを表示し、絞り込みもできます。
内部用・状態用の名前は折りたたんだ一覧に分けています。予告なく変わることがあるため、カスタマイズには向きません。
「初期一覧」は、v0.6.0の時点にあった名前です。それより前の追加時期は記録していません。
バージョンごとの変更（追加・変更あり・非推奨・改名・廃止）は、比較元のバージョンを選ぶと、途中のバージョンも含めてまとめて表示します。

今のバージョンの一覧は次のとおりです。

<details open>
<summary>公開セレクターとCSS変数の一覧</summary>

<!-- css-catalog:begin (generated by manga/dev/css_catalog_check.py --write-docs) -->

**公開セレクター**

| 名前 | 用途 | 対象の画面 | 記述例 | 追加 |
| --- | --- | --- | --- | --- |
| `html[data-log-theme]` | テーマの切り替え。値はテーマ名（light-blue・dark-navy など） | すべてのページ | `html[data-log-theme="dark-navy"] { --log-accent: #7dd3fc; }` | 初期一覧 |
| `.log-site` | 公開ページのbody | すべてのページ | `.log-site { letter-spacing: .02em; }` | 初期一覧 |
| `.log-site-header` | サイト名・ロゴ・紹介文の見出し部分 | すべてのページ | `.log-site-header { padding-block: 32px; }` | 初期一覧 |
| `.log-site-title` | サイト名（一覧ではh1、記事ではp） | すべてのページ | `.log-site-title a { color: var(--log-accent); }` | 初期一覧 |
| `.log-site-logo` | タイトルロゴの画像 | すべてのページ | `.log-site-logo { max-height: 56px; }` | 初期一覧 |
| `.log-site-avatar` | サイト名の横のアイコン | すべてのページ | `.log-site-avatar { border-radius: 12px; }` | 初期一覧 |
| `.log-site-description` | サイト名の下の紹介文 | すべてのページ | `.log-site-description { font-size: 13px; }` | 初期一覧 |
| `.log-topmenu` | トップメニュー | すべてのページ | `.log-topmenu { border-bottom: 1px solid var(--log-line); }` | 初期一覧 |
| `.log-menu-toggle` | スマホのMENUボタン | すべてのページ | `.log-menu-toggle { background: var(--log-accent); }` | 初期一覧 |
| `.log-site-grid` | 本文とサイドバーを並べる枠 | すべてのページ | `.log-site-grid { max-width: 1200px; }` | 初期一覧 |
| `.log-site-main` | 本文の列（投稿一覧・記事・固定ページ） | すべてのページ | `.log-site-main { gap: 32px; }` | 初期一覧 |
| `.log-breadcrumb` | パンくずリスト | 投稿一覧・記事のページ・固定ページ | `.log-breadcrumb { font-size: 12px; }` | 初期一覧 |
| `.log-archive-head` | カテゴリ・タグ・日付・検索の一覧の見出し部分 | 投稿一覧 | `.log-archive-head { margin-bottom: 24px; }` | 初期一覧 |
| `.log-archive-title` | 上の見出しの文字 | 投稿一覧 | `.log-archive-title { font-size: 22px; }` | 初期一覧 |
| `.log-post` | 1件の投稿（ミニブログ表示・記事のページ） | 投稿一覧・記事のページ | `.log-post { border-radius: 4px; }` | 初期一覧 |
| `.log-post.is-pinned` | ピン留めした投稿 | 投稿一覧 | `.log-post.is-pinned { outline: 2px solid var(--log-accent); }` | v0.7.0 |
| `.log-post-meta` | 投稿のアイコン・名前・日付の行 | 投稿一覧・記事のページ | `.log-post-meta time { font-weight: 700; }` | 初期一覧 |
| `.log-pin-badge` | ピン留めの印 | 投稿一覧 | `.log-pin-badge { color: var(--log-accent); }` | v0.7.0 |
| `.log-body` | 投稿の本文 | 投稿一覧・記事のページ | `.log-body { line-height: 2; }` | 初期一覧 |
| `.log-figure` | 本文の画像1枚 | 投稿一覧・記事のページ | `.log-figure img { border-radius: 0; }` | 初期一覧 |
| `.log-gallery` | 続けて並べた画像のまとまり | 投稿一覧・記事のページ | `.log-gallery { gap: 2px; }` | 初期一覧 |
| `.log-categories` | 投稿の下のカテゴリ | 投稿一覧・記事のページ | `.log-categories { font-size: 12px; }` | 初期一覧 |
| `.log-share` | 投稿の下の共有・いいねの行 | 投稿一覧・記事のページ | `.log-share { justify-content: flex-end; }` | 初期一覧 |
| `.log-like` | いいねボタン | 投稿一覧・記事のページ | `.log-like { color: #e0245e; }` | 初期一覧 |
| `.log-lock-form` | 鍵付きの投稿・固定ページのパスワード入力欄 | 記事のページ・固定ページ | `.log-lock-form { max-width: 420px; }` | v0.7.0 |
| `.log-tiles` | タイル表示の一覧 | タイル表示の一覧 | `.log-tiles { gap: 8px; }` | 初期一覧 |
| `.log-tile` | タイル1枚 | タイル表示の一覧 | `.log-tile { border-radius: 0; }` | 初期一覧 |
| `.log-tile-title` | タイルの題名 | タイル表示の一覧 | `.log-tile-title { font-size: 13px; }` | 初期一覧 |
| `.log-page` | 固定ページの本体 | 固定ページ | `.log-page h1 { text-align: center; }` | 初期一覧 |
| `.log-page-body` | 固定ページの本文 | 固定ページ | `.log-page-body { line-height: 1.9; }` | 初期一覧 |
| `.log-layout-wide` | 幅広レイアウトの固定ページ（bodyに付きます） | 固定ページ | `.log-layout-wide .log-page { max-width: none; }` | 初期一覧 |
| `.log-layout-narrow` | 狭いレイアウトの固定ページ（bodyに付きます） | 固定ページ | `.log-layout-narrow .log-page { max-width: 640px; }` | 初期一覧 |
| `.log-md-table` | 固定ページの表 | 固定ページ | `.log-md-table th { background: var(--log-field); }` | 初期一覧 |
| `.log-pager` | 一覧のページ送り | 投稿一覧 | `.log-pager { margin-top: 40px; }` | 初期一覧 |
| `.log-post-nav` | 記事の下の前後の記事へのリンク | 記事のページ | `.log-post-nav { gap: 8px; }` | 初期一覧 |
| `.log-related` | 記事の下の関連記事 | 記事のページ | `.log-related h2 { font-size: 16px; }` | 初期一覧 |
| `.log-empty` | 記録がないときの文 | 投稿一覧 | `.log-empty { text-align: center; }` | 初期一覧 |
| `.log-sidebar` | サイドバー | サイドバー | `.log-sidebar { font-size: 14px; }` | 初期一覧 |
| `.log-sidebar-block` | サイドバーの各項目。data-sidebar-id で項目を選べます（例：[data-sidebar-id="calendar"]） | サイドバー | `.log-sidebar-block[data-sidebar-id="calendar"] { display: none; }` | 初期一覧 |
| `.log-widget` | 枠付きのサイドバー項目 | サイドバー | `.log-widget { box-shadow: none; }` | 初期一覧 |
| `.log-profile-links` | プロフィールとリンク集 | サイドバー | `.log-profile-links { padding-top: 0; }` | 初期一覧 |
| `.log-profile-icon` | プロフィールのアイコン | サイドバー | `.log-profile-icon img { border-radius: 16px; }` | 初期一覧 |
| `.log-profile-name` | アイコンの下の名前 | サイドバー | `.log-profile-name { font-size: 18px; }` | v0.7.0 |
| `.log-profile-message` | リンクの上のメッセージ（吹き出し） | サイドバー | `.log-profile-message { text-align: left; }` | 初期一覧 |
| `.log-link-buttons` | リンクボタンの並び | サイドバー | `.log-link-buttons { gap: 6px; }` | 初期一覧 |
| `.log-link-button` | リンクボタン1つ | サイドバー | `.log-link-button { border-radius: 999px; }` | 初期一覧 |
| `.log-search` | サイドバーの検索欄 | サイドバー | `.log-search input { border-radius: 999px; }` | 初期一覧 |
| `.log-calendar` | カレンダー | サイドバー | `.log-calendar td { font-size: 12px; }` | 初期一覧 |
| `.log-tag-cloud` | ハッシュタグの一覧 | サイドバー | `.log-tag-cloud a { font-size: 12px; }` | 初期一覧 |
| `.log-custom-block` | 自分で追加したHTML枠 | サイドバー | `.log-custom-block { text-align: center; }` | 初期一覧 |
| `.log-site-footer` | サイト下部 | サイト下部 | `.log-site-footer { padding-block: 40px; }` | 初期一覧 |
| `.log-footer-nav` | フッターのリンク | サイト下部 | `.log-footer-nav a { color: inherit; }` | 初期一覧 |
| `.log-footer-text` | サイト下部の表記 | サイト下部 | `.log-footer-text { font-size: 11px; }` | 初期一覧 |
| `.log-toc` | 記事・固定ページの目次（見出しが4つ以上のとき、最初の見出し２の上） | 記事のページ・固定ページ | `.log-toc { background: var(--log-card); }` | v0.8.0 |
| `.log-toc-list` | 目次の項目のリスト（.log-toc-2〜4 が見出しの大きさ） | 記事のページ・固定ページ | `.log-toc-list .log-toc-3 { padding-left: 2em; }` | v0.8.0 |
| `.log-toc-rail` | 記事の左に付いてくる目次（広い画面） | 記事のページ・固定ページ | `.log-toc-rail-card { border-radius: 12px; }` | v0.8.0 |
| `.log-toc-fab` | 目次のボタン（狭い画面の右下。読んだ割合をリングで表示） | 記事のページ・固定ページ | `.log-toc-fab { color: var(--log-cyan); }` | v0.8.0 |
| `.log-toc-sheet` | 目次のボタンで開くシート | 記事のページ・固定ページ | `.log-toc-sheet { border-radius: 16px 16px 0 0; }` | v0.8.0 |
| `.log-code-block` | 記事・固定ページのコードブロックの枠。中に pre.log-md-code と COPY ボタン | 記事のページ・固定ページ | `.log-code-block pre { font-size: 13px; }` | v0.8.2 |
| `.log-code-copy` | コードブロックの右上の COPY ボタン（コピーしたあとは .is-copied） | 記事のページ・固定ページ | `.log-code-copy { color: var(--log-accent); }` | v0.8.2 |
| `.markdown-alert` | 注意書きの箱（> [!NOTE] など。GitHubと同じクラス名） | 記事のページ・固定ページ | `.markdown-alert { border-radius: 4px; }` | v0.11.0 |
| `.markdown-alert-note` | 補足（NOTE）の箱 | 記事のページ・固定ページ | `.markdown-alert-note { --alert: #0969da; }` | v0.11.0 |
| `.markdown-alert-tip` | ヒント（TIP）の箱 | 記事のページ・固定ページ | `.markdown-alert-tip { --alert: #1a7f37; }` | v0.11.0 |
| `.markdown-alert-important` | 重要（IMPORTANT）の箱 | 記事のページ・固定ページ | `.markdown-alert-important { --alert: #8250df; }` | v0.11.0 |
| `.markdown-alert-warning` | 注意（WARNING）の箱 | 記事のページ・固定ページ | `.markdown-alert-warning { --alert: #9a6700; }` | v0.11.0 |
| `.markdown-alert-caution` | 警告（CAUTION）の箱 | 記事のページ・固定ページ | `.markdown-alert-caution { --alert: #d1242f; }` | v0.11.0 |
| `.markdown-alert-title` | 注意書きの見出し（アイコンと「補足」などの文字） | 記事のページ・固定ページ | `.markdown-alert-title { font-size: 15px; }` | v0.11.0 |
| `.log-mermaid` | 図の枠（```mermaid で書いたフローチャート・シーケンス図） | 記事のページ・固定ページ | `.log-mermaid { background: var(--log-bg); }` | v0.11.0 |
| `.log-mermaid-zoom` | 図の右上の「拡大」ボタン | 記事のページ・固定ページ | `.log-mermaid-zoom { color: var(--log-accent); }` | v0.11.0 |
| `.log-mermaid-sheet` | 「拡大」で開く、画面いっぱいの図 | 記事のページ・固定ページ | `.log-mermaid-sheet { background: var(--log-card); }` | v0.11.0 |
| `.log-dg` | 描いた図（SVG）。--dg-edge（枠と矢印の色）・--dg-line（線の色）・--dg-box（箱の色）・--dg-ink（文字の色）で色を変えられます | 記事のページ・固定ページ | `.log-dg { --dg-edge: #e0607e; }` | v0.11.0 |
| `.log-frame` | ページ埋込（[ページ埋込]URL[/ページ埋込]）の全体。--frame-width で枠の幅を変えられます | 記事のページ・固定ページ | `.log-frame { --frame-width: 100%; }` | v0.11.0 |
| `.log-frame-stage` | ページ埋込の枠（読み込む前は表紙、押すとページ） | 記事のページ・固定ページ | `.log-frame-stage { border-radius: 0; }` | v0.11.0 |
| `.log-frame-play` | ページ埋込の表紙の「ページを読み込む」ステッカー | 記事のページ・固定ページ | `.log-frame-play { transform: none; }` | v0.11.0 |
| `.log-frame-bar` | ページ埋込の下の行（別のタブで開くリンクと「全画面」ボタン） | 記事のページ・固定ページ | `.log-frame-bar { font-size: 13px; }` | v0.11.0 |

**CSS変数**

| 名前 | 用途 | 対象の画面 | 記述例 | 追加 |
| --- | --- | --- | --- | --- |
| `--log-accent` | テーマの強調色（ボタン・リンク・フチ） | すべてのページ | `:root { --log-accent: #e85d75; }` | 初期一覧 |
| `--log-bg` | ページの背景色 | すべてのページ | `:root { --log-bg: #fffaf3; }` | 初期一覧 |
| `--log-card` | 投稿や枠の背景色 | すべてのページ | `:root { --log-card: #ffffff; }` | 初期一覧 |
| `--log-cyan` | アイコンの文字などの補助色 | すべてのページ | `:root { --log-cyan: #0e7490; }` | 初期一覧 |
| `--log-field` | 入力欄やチップの背景色 | すべてのページ | `:root { --log-field: #f3f4f6; }` | 初期一覧 |
| `--log-line` | 線・区切りの色 | すべてのページ | `:root { --log-line: #e5e7eb; }` | 初期一覧 |
| `--log-muted` | 薄い文字の色（日付・補足） | すべてのページ | `:root { --log-muted: #6b7280; }` | 初期一覧 |
| `--log-on-accent` | 強調色の上の文字の色 | すべてのページ | `:root { --log-on-accent: #fff; }` | 初期一覧 |
| `--log-radius` | 角の丸み | すべてのページ | `:root { --log-radius: 6px; }` | 初期一覧 |
| `--log-shadow` | 投稿や枠の影 | すべてのページ | `:root { --log-shadow: none; }` | 初期一覧 |
| `--log-text` | 文字の色 | すべてのページ | `:root { --log-text: #222; }` | 初期一覧 |

<!-- css-catalog:end -->

</details>

一覧は`server/lib/css-catalog.json`に手で書きます。管理画面は読むだけで、一覧の作成や比較はサーバーやスマホでは行いません。
`dev/css_catalog_check.py`は、`log.css`とコードから名前を拾い、一覧との食い違いを調べます。CSSにあるのに一覧にない名前、もうないのに一覧に残る名前、前のリリース（最新の`v*`タグ）から公開セレクターが消えたり改名されたりしたのに変更履歴がない場合に失敗します。名前を組み立てて付けるクラスは`dynamic`に登録します。
GitLab CIとGitHub Actionsでも同じチェックを実行します。リリースの前に、一覧の`"next"`を出すバージョン番号に書き換え、`python manga/dev/css_catalog_check.py --write-docs`でREADMEの一覧も書き直します（`dev/build_release.py`が確認し、残っているとZIPを作りません）。下の一覧は、このコマンドが`css-catalog.json`から作ります。

## 検索

公開ページのサイドメニューに検索欄があります。スマホでは右上の「MENU」の中です。
本文・タイトル・ハッシュタグ・カテゴリ名・本文に入れた漫画のタイトルから探します。公開中の記事だけが対象で、下書きは出しません。

| 入力 | 見つかるもの |
| --- | --- |
| `ねこ` | 「ねこ」「ネコ」のどちらを含む記録も |
| `ＡＢＣ１２３` | 半角の `abc123` を含む記録も（全角・半角、大文字・小文字を区別しません） |
| `ねこ 散歩` | 「ねこ」と「散歩」の両方を含む記録だけ（空白で5語まで） |
| `#らくがき` | 本文にそのハッシュタグがある記録 |

結果は「「ねこ」の検索結果　12件」の見出しの下に、ふだんの一覧と同じ形で並びます。ページ送りでも検索の言葉を保ちます。
検索結果のページは、検索エンジンに登録しない（`noindex`）設定です。
サイドメニューの検索欄は、「設定 → LOG → サイドバー・メニュー」で並び替え・非表示にできます。以前から使っているLOGでは、プロフィール・リンク集のすぐ下に追加されます。

管理画面の「LOG・投稿」にも、一覧の上に検索欄があります。キーボードの `/` で検索欄へ移れます。
下書きも含めて探せ、「すべて・公開・下書き」で絞り込めます。
結果には、見つかった言葉を黄色で示した本文の一部と、カテゴリ、公開サイトのトップから数えて何ページ目にあるか（例: 「トップの3ページ目」）を出します。押すと、そのページを開きます。

## 一覧の見せ方と関連記事

「設定 → LOG → 一覧の見せ方・記事の下」で選びます。

| 見せ方 | 一覧の表示 | 向いているLOG |
| --- | --- | --- |
| ミニブログ（標準） | 記事を最初から最後まで並べます。一覧のページだけで読めます。 | ひとことの記録が多いLOG |
| タイル | サムネイル・投稿日・タイトルのタイルを、2列（スマホも2列）で並べます。1ページの投稿数は偶数がおすすめです。奇数だと、各ページの最後の行が1つ空きます。 | 長めの記事が多いLOG、WordPressのブログのように見せたいLOG |

タイルのサムネイルは、本文の上から見て最初に見つかったものです。
LOGの画像、漫画の表紙（パスワードのない公開作品）、YouTubeの動画のサムネイル、ブログカードの画像の順に探します。
どれもない記事は、タイトルの最初の1文字を大きく置いたパネルにします。
サムネイルは一覧用の派生情報（`log/index.php`）に控えるので、タイルの一覧は記事の原本を開かずに作れます。
古い版の一覧用ファイルは、最初に表示したときに1回だけ作り直します。
YouTubeのサムネイルは、読者のブラウザーが `i.ytimg.com` から読み込みます。

**新着の印**

投稿から一定の期間の記事に、印を付けます。タイルではサムネイルの左上、ミニブログでは記事の枠の左上に出します。
「設定 → LOG → 一覧の見せ方・記事の下 → 新着の印」で、期間（標準は7日、0日で付けない）と文字（標準は`NEW`。「新」「New!」など10文字まで）を変えられます。
記事のページ（1件だけの表示）には付けません。
ページをキャッシュしていても、期間が過ぎた印はブラウザーで外します（`viewer/log-new.js`）。

関連記事は、記事の下（前後の投稿の上）に6件出します。

- 関連とみなす分類: 「カテゴリとハッシュタグ」（標準）「カテゴリだけ」「ハッシュタグだけ」
- 並び順: 「ランダム」（標準）と「更新が新しい順」

ランダムでは、関係の深い記事（同じカテゴリは2点、重なるハッシュタグは1つ1点）から最大18件をページに入れ、ブラウザーが6件を選びます。
ページ自体は全員に同じものを返すので、LiteSpeed Cacheのキャッシュはそのまま効きます。JavaScriptが動かない場合は、関係の深い順に6件を表示します。
同じ分類の記事がない記事には、関連記事の枠を出しません。

## ピン留め

WordPressの「先頭に固定表示」と同じように、記事をトップページの最初に出せます。
管理画面の投稿一覧で、行のピンのボタンを押すと留まり、もう一度押すと外れます。記事の編集画面の「ピン留め」でも切り替えられます。

![投稿一覧の上の「ピン留め中の記事」。番号・持ち手・上下ボタン・ピンのボタンが並ぶ行と、その下の「固定」の印が付いた投稿の行](docs/images/log-pins-admin.jpg)

- いくつでも留められます（30件まで）。留めた記事は、日付にかかわらずトップページの最初に、決めた順番で並びます。
- 順番は、投稿一覧の上の「ピン留め中の記事」で、持ち手のドラッグか上下ボタンで並べ替えます。並べ替えはその場で保存します。新しく留めた記事は最後に入ります。
- 管理画面の投稿一覧でも、ピン留めした記事を最上部に出し、行の左に色の線と「固定」の印を付けます。
- 公開側では、記事（ミニブログ）とタイルに「固定」の印を付けます。タイルでは、新着の印の代わりにピンの印を出します。
- 先頭に並べるのはトップページの一覧だけです。カテゴリ・タグ・日付の一覧、RSS、サイドバーの最新ポスト、前後の投稿は、これまでどおり日付順です。
- 下書きを留めておくこともできます。公開するまで読者には出ません。公開して記事の番号が変わっても、ピン留めは続きます。
- 記事を削除すると、ピン留めからも外れます。ピン留めとその順番は、LOG用のバックアップにも入ります。

## パスワード（鍵）

記事と固定ページに、読者用のパスワードをかけられます。
記事は投稿欄の道具の列の鍵のボタン、固定ページは編集画面の「パスワード（鍵）」で、「パスワードをかける」をオンにして、4〜200文字のパスワードを入れます。
鍵をかけた記事には、投稿欄に「パスワードあり」、投稿一覧に「鍵付き」の印が出ます。持ち主（ログイン中）には、いつも本文を表示します。

![投稿の編集画面。道具の列の鍵のボタン（1）を押すと、その下に「パスワード（鍵）」の欄（2）が開く](docs/images/log-lock-editor.jpg)

読者には、次のように見せます。

| 場所 | 表示 |
| --- | --- |
| 記事・固定ページ | タイトルと、パスワードの入力欄だけ。本文・画像・埋め込みは出しません |
| 一覧（ミニブログ） | タイトルと「パスワードを入れて読む」のリンク |
| タイル・関連記事 | サムネイルの代わりに鍵の絵 |
| 説明文・RSS | 「この記事はパスワードで保護されています。」だけ |
| 共有カード（OGP） | 本文のいちばん上の画像を、色しか分からないほど強くぼかし、鍵の印と「鍵付き」（管理画面を英語にしているときは「Locked」）を重ねたカードにします。R-18などの閲覧注意が付いた記事も同じです。画像のない記事は、サイト共通の画像です |
| 検索 | タイトルとカテゴリ名でだけ見つかります。本文の言葉では見つかりません |
| 画像 | 鍵付きの記事だけで使う画像は、開いた人にしか渡しません（ほかの人には404） |
| 検索エンジン | `noindex` にして、サイトマップにも載せません |

正しいパスワードを入れると、その記事を読める印（記事ごとの署名）をクッキー `nl_keys` に30日間残し、その間はもう一度入れずに読めます。
クッキーに入れるのは印だけで、パスワードもハッシュも入れません。パスワードを変えると印が合わなくなり、開いていた人ももう一度入力が必要です。

パスワードの入力欄は、ブラウザーやパスワード管理ソフトに保存させない作りです。
入力欄はパスワード欄（`type="password"`）ではなく、文字をCSSで伏せた普通の欄にし、`autocomplete="off"` と主なパスワード管理ソフトの「無視する」印を付けています。
そのため「パスワードを保存しますか？」は出ず、入力の履歴にも残りません。「入力した文字を表示」で、伏せ字を外して確かめられます。
送ったあとは記事のページへ戻す（303）ので、再読み込みでパスワードを送り直すこともありません。

続けて間違えた場合は、1つの記事につき15分で5回、同じ接続元から1時間に30回までで、それを超えると15分ほど受け付けません。
パスワードはハッシュで保存します。持ち主が編集画面で今のパスワードを確かめられるよう、秘密鍵で暗号化した写しも保存します（漫画の閲覧パスワードと同じしくみです）。
鍵の設定はLOG用のバックアップにも入り、復元しても鍵はかかったままです。

## いいね

公開中のLOGでは、記事の下の「Share」の左に、ハートのいいねボタンを出します。オフにする場合は「設定 → LOG → 一覧の見せ方・記事の下」で外します。

| 操作 | 増える数 |
| --- | --- |
| タップ・クリック・Enterキー | 1 |
| 長押し | 押している間、70フレーム（60fps換算で約1.17秒）ごとに10。ボタンの中の色の帯で、次の10までの進み具合を表示します |

続けて押した分はまとめて1回で送ります。画面を閉じる直前の分も送ります。
1人が1つの記事に押せるのは、1日（日本時間）100までです。上限に届くと「MAX」と表示し、それ以上は増えません。
「1人」は、同じ回線（IPアドレス）と同じ端末（ブラウザーが送る端末情報、User-Agent）の組み合わせで見分けます。同じ回線の家族でも、スマホとパソコンなど端末が違えば別々に数えます。
IPv6は、家庭の回線ごとに配られる範囲（/64）をひとまとめにします。
端末情報は簡単に書き換えられるため、同じ回線全体でも1つの記事に1日500までにしています。
IPアドレスや端末情報そのものは保存せず、秘密鍵で作った記号だけを、その日のうちだけ残します。

数は投稿の原本とは別の小さなファイル（`log/likes.php`）に保存します。いいねを押されても、投稿やページのキャッシュは作り直しません。
ページを開くと、ブラウザーが `like.php` から最新の数とその日の残り回数を1回だけ受け取ります。
ほかのサイトのフォームやスクリプトからは送れないよう、専用のヘッダーと送信元を確認します。同じIPから1分に60回を超える送信は断ります。

記事の編集画面には「いいね」の枠があります。今の数を確認し、好きな数に変えるか、「いいねを削除」で0に戻せます。
記事を削除すると、その記事のいいねも消えます。

## サイドバーの並び替えとHTML枠

サイドバーの先頭には、枠なしのプロフィール・リンク集を表示します。
LOG設定で選んだアイコンを中央に置き、その下に横長のリンクボタンを並べます。
アイコンを設定していない場合は、表示名の先頭の文字を使います。
アイコンには、既定でテーマの色のフチを付けます。「アイコンにフチを付ける」をオフにすると外せます。
アイコンの下には、LOG設定の「LOGのデザイン・アイコン」で入れた「名前」を表示します。不要なら「アイコンの下に名前を表示する」をオフにします。
リンクの上には、サイトの紹介文とは別のメッセージを300文字まで表示できます。改行は使えますが、HTMLは使えません。空欄なら表示しません。
メッセージは、アイコンへ向かって下から話しかける吹き出しの形です。

「プロフィールとリンクを編集」で、フチ・名前の表示・メッセージと、各リンクの表示名・URL・用途を表すアイコンを編集できます。
リンクの追加・削除・上下の移動もできます。
初期のURLはX、Instagram、Bluesky、GitHub、YouTubeのトップページです。
たとえば、XのURLを自分のプロフィールURLに書き換えて使います。

SVGは、会話・写真・空と通信・コードの分岐・フィルム・封筒（メール）・一般リンクを描いたオリジナルです。
メールは、「URL・メール」欄に`you@example.com`のようにアドレスだけを書き、「メール」のアイコンを選びます。`mailto:`付きでも入力できます。
訪問者がメールのボタンを押すと、アドレスを表示したダイアログが開きます。「アドレスをコピー」か「メールアプリで送信」（いつも使っている既定のメールアプリ）を選べます。
JavaScriptが動かない環境では、そのまま既定のメールアプリを開きます。件名付き（`?subject=`）や複数の宛先は使えません。
公式ロゴや既存のブランド画像は使っていません。
`server/viewer/link-icons/`にSVGとMITライセンスの全文を同梱しています。
既存のサイドバー設定や旧バックアップにも、リンク集を追加します。
ほかの項目の順番は保ちます。リンク集を隠す場合は、表示のスイッチをオフにして保存します。

「設定 → LOG → サイドバー・メニュー」で編集します。
各項目は1行にまとまっており、持ち手をドラッグするか、上下ボタンで移動できます。
スイッチをオフにすると非表示になります。スマホの「MENU」にも同じ順番を使います。
順番と内容は、画面下に固定した「設定を保存」で、ほかの設定と一緒に反映します。
ログインリンクの表示も、この「ログイン・管理ページ」のスイッチだけで切り替えます。以前の「公開範囲・表示件数」にあった設定は、ここへ移しました。

「上級者向け：HTML枠を追加」を開き、テンプレートを選んで追加します。
枠の個数は決めていません。同じテンプレートを繰り返し呼び出せます。
グリッドリンクは2列のリンク集、バナーリンクは枠と背景を付けない画像リンクです。
追加後に、リンク先・画像のURL・文章を自分の内容へ書き換えてください。
見出しを空欄にすると見出しを隠せます。「枠と背景を表示する」も変更できます。

HTML枠では、リンク、画像、見出し、段落、リスト、太字を使えます。
script、iframe、フォーム、イベント属性、style属性は、保存時に取り除きます。
レイアウト用のclassは`log-link-grid`、`log-banner-link`、`log-banner`を使えます。
見出しは100文字、1枠のHTMLは安全化した後も50KB、全体は1MBまでです。
別の画面で先に保存した場合は上書きせず、変更内容を編集欄へ残して開き直すよう案内します。
画面を開き直す前に、未保存のHTMLは別にコピーしてください。

画像のURLは、同じサイトへの相対URLか、HTTPSのURLを指定します。
外部画像は表示時に外部サーバーへ取得しに行くため、訪問者のIPなどがそのサーバーへ伝わります。
同じサイトに置いた画像なら、この外部通信を避けられます。
HTML枠から参照するLOG画像は、元の記事を削除しても残します。
全体公開のLOGでは、表示中のHTML枠から参照するLOG画像も公開します。
非表示の枠が使う画像は削除から保護しますが、その枠だけを理由に公開はしません。
自分専用Memoでは、サイドバーとそのLOG画像もログイン時だけ表示します。

HTML枠を外して保存しても、リンク先や画像そのものは削除しません。
使わなくなったLOG画像は、「画像一覧・差し替え」から削除できます。

## タイトルロゴと紹介文

「設定 → LOG → LOGのデザイン・アイコン」の「タイトルロゴ」に画像を選ぶと、ページ上部のアイコンとサイト名の代わりにロゴを表示します。横長のバナー（例：200×40px）が向いていて、SVGも使えます。高さはPCで64px、スマホで44pxまでに縮めて表示します。「ロゴを外して、アイコンとサイト名に戻す」で元に戻せます。

サイト名（ロゴ）は、トップ・カテゴリ・タグなどの一覧のページで見出し `h1` になります。

```html
<h1 class="log-site-title has-logo">
  <a href="./">
    <img class="log-site-logo" src="./?media=…" width="200" height="40" alt="サイト名">
  </a>
</h1>
```

ロゴの `alt` にはサイト名を入れます。記事のページと固定ページでは、記事や固定ページのタイトルが `h1` なので、サイト名は `p` にして、1ページに `h1` が1つになるようにしています（以前の、画面に出ない `h1` は出しません）。

「紹介文をサイト名の下に表示する」をオフにすると、紹介文を画面に出さず、検索結果や共有したときの説明文（`meta description`・`og:description`）としてだけ使います。

## ファビコンとホーム画面のアイコン

「設定 → LOG → LOGのデザイン・アイコン」の「ファビコン・ホーム画面のアイコン」に画像を1枚選ぶと、次のアイコンを自動で作ります。512×512pxの正方形のPNGがおすすめです。

| 作るもの | 大きさ | 使われる場所 |
| --- | --- | --- |
| `favicon.ico` | 16・32・48px（PNGを3つ入れたICO） | ブラウザーのタブ、ブックマーク |
| iPhone用のアイコン | 180px | iPhone・iPadの「ホーム画面に追加」 |
| Android用のアイコン | 192px・512px | Androidの「ホーム画面に追加」、ウェブアプリの設定（manifest） |

- 縮小は、半分ずつ段階的に行います（512→256→128→64→32→16）。一度に小さくするより、細い線や文字がつぶれにくくなります。
- 保存は画質の落ちないPNGです。JPEGやWebPのような汚い圧縮はしません。
- 正方形でない画像は、切り取らずに透明な余白を足して正方形にします。
- iPhoneは透明な部分を黒で塗るため、iPhone用だけはデザインの背景色を敷きます。デザインの色を変えると、iPhone用も作り直します。
- 元の画像より大きいサイズは、引き伸ばすとぼやけるため作りません。512pxより小さい画像では、作らなかったサイズを設定画面で知らせます。48px未満の画像とSVGは使えません。
- 設定画面では、作ったサイズを実際の大きさで並べて確認できます。管理画面のタブにも同じファビコンを使います。
- 各ファイルは `./?favicon=…&v=版番号` で配信し、版番号の付いたURLはブラウザーに1年保存させます。画像を変えると版番号が変わります。
- 設定していないときは、これまでどおりアイコンの画像を縮小して使います。「ファビコンを外して、アイコンの画像に戻す」で元に戻せます。
- ファビコンの画像ファイルはLOG用のバックアップに入りません。引っ越し先で選び直してください。

## トップメニュー

「設定 → LOG → トップメニュー」で、サイト名の下に並ぶリンクを作れます。項目がないときは表示しません。

- 「項目を追加」で行を増やし、表示名とリンク先を入れます。最大30項目、表示名は40文字までです。
- 表示名に固定ページ・カテゴリ・ハッシュタグの名前の一部を入れると、候補が出ます（ひらがな・カタカナ、全角・半角は区別しません）。選ぶと、表示名とリンク先（`./privacy` `./?category=…` のようなサイト内のURL）が入ります。以前に入れた `./?pg=privacy` のリンクも、そのまま使えます。「ホーム（すべての投稿）」も候補にあります。
- 外部サイトは `https://` から入力します。`javascript:` などのURLは保存しません。
- 並べ替えはサイドバーと同じで、左の持ち手をドラッグするか、矢印のボタンを使います。スイッチをオフにすると、消さずに隠せます。
- 保存は画面の下の「設定を保存」です。

表示名を入力すると、カテゴリやハッシュタグの候補が出ます。下の例では「イラスト」を入力しています。候補を選ぶとリンク先も入り、変更したブロックの左端と目次に印が付きます。画面下に保存していない項目の名前も表示します。

![トップメニューの設定でイラストを入力した例。カテゴリとハッシュタグの候補、未保存の印、設定を保存ボタン](docs/images/log-topmenu-settings.jpg)

公開ページでは、今いるページ（固定ページ・カテゴリ・タグ・トップ）の項目に下線と `aria-current="page"` を付けます。外部サイトのリンクには `rel="noopener noreferrer"` を付けます。

スマホでは、BlueskyやXのタブのように1行に並べ、入りきらないときは指で左右にスワイプして読みます。続きがあることがはっきり分かるように、次の動きを付けています。

- 端を背景色でぼかし、続きのある側に丸い矢印を出します。矢印を押すとその方向へ送ります。
- 初めて表示したとき、メニューが一度だけ左へ少し動いて戻ります（スクロールできることを見せる動き）。
- スワイプするまで、右の矢印が小さく揺れ続けます。一度動かすと止まります。
- 今いるページの項目が見えない位置にあるときは、その項目が中央に来るように送ってから表示します。
- PCでも入りきらないときは同じ表示になり、マウスのホイールで横に送れます。
- 「視差効果を減らす」（`prefers-reduced-motion`）を選んでいる端末では、動きを付けません。

## 固定ページ

プライバシーポリシー、利用規約、プロフィールのような、日付の流れに入らないページです。「LOG・投稿」の「固定ページ」タブで作ります（`admin/index.php?p=log_pages`）。

| 項目 | 内容 |
| --- | --- |
| タイトル | 100文字までの1行。ページの `h1` と `<title>` になります |
| URL名 | 半角の英小文字・数字・ハイフンで40文字まで。公開URLは `./URL名`（例：`./privacy`。`.htaccess` が効かないサーバーでは `./?pg=privacy`）。空欄なら自動で付けます。`admin` などLOGのフォルダー名は使えません |
| パスワード（鍵） | 「このページにパスワードをかける」をオンにすると、読者にはタイトルと入力欄だけを見せます（[パスワード（鍵）](#パスワード鍵)） |
| ページの幅（PC） | サイドバー付き（通常）／幅広1カラム（サイドバーを出さず全幅）／幅狭1カラム（サイドバーを抜き、本文の列だけを中央寄せ） |
| 本文 | Markdownで200KBまで。投稿の本文とは別の入力欄です |
| 公開・下書き | 下書きは読者には404で、ログイン中だけ表示します |

スマホではもともとサイドバーを「MENU」の中に出すので、どの幅を選んでも表示は変わりません。
公開後にURL名を変えると、以前のURLは404になります。リンクを貼ったあとも同じURLで読めるよう、公開後はなるべく変更しないでください。

本文で使えるMarkdownは次のとおりです。改行はそのまま改行になり、空行で段落が分かれます。HTMLのタグは文字として表示し、そのページで動かしません。

| 書き方 | 表示 |
| --- | --- |
| `## 見出し`（`#` も同じ）／`### 小見出し`／`#### さらに小さく` | 見出し（h2／h3／h4）。見出しには `#見出しの文字` で飛べるIDが付きます。4つ以上あると、最初の見出し２の真上に目次が入ります |
| `**太字**` `*斜体*` `~~取り消し線~~` `` `コード` `` | 文字の強調 |
| `\|親文字《おやもじ》`／`漢字《かんじ》` | ルビ（読み仮名。[ルビ（読み仮名）](#ルビ読み仮名)） |
| `- 項目`／`1. 項目`（行頭に空白2つで入れ子） | 箇条書き・番号付きリスト |
| `[文字](https://…)`／`[文字](./?pg=terms)`／`[メール](mailto:…)` | リンク。`javascript:` などはリンクにしません |
| `![説明](./?media=…)` | 画像。LOGの画像はNagiSwipeで拡大でき、差し替えると新しい画像を表示します |
| `> 引用` | 引用 |
| `> [!NOTE]` の次の行から `> 本文` | 注意書きの箱（TIP・IMPORTANT・WARNING・CAUTION も。[注意書きと図](#注意書きと図mermaid)） |
| `\| 項目 \| 内容 \|` の次の行に `\| --- \| :-: \|` | 表（`:-:` で中央、`--:` で右寄せ） |
| `---` | 区切り線 |
| ```` ``` ```` で囲む | 複数行のコード |
| ```` ```mermaid ```` で囲む | 図（フローチャート・シーケンス図。[注意書きと図](#注意書きと図mermaid)） |
| `[ページ埋込]URL[/ページ埋込]` | ほかのページ（ゲームなど）を枠に入れて表示（[ページ埋込](#ページ埋込)） |

編集画面の道具の列は投稿欄と同じアイコンで、「画像を追加」「画像一覧から選ぶ」、太字・斜体・リンク、見出し・箇条書き・番号付きリスト・引用・表・区切り線・取り消し線・コード・ルビを選ぶ「装飾」（投稿欄と同じ画面）、「Markdownの書き方」（？）、右端にプレビュー（目のアイコン）が並びます。
並び方も投稿欄と同じです。PCや横向きのスマホでは、道具の列が本文欄の上に来て、本文欄は「書く」「プレビュー」のタブになります（プレビューは本文欄の高さで、中をスクロールします）。左には「このページ」（本文の画像と枚数）と「画像一覧」（説明で探して選ぶと本文のカーソルの位置に入る）のタブを持つメディア欄が付いてきます。見出しの横の「本文へ」で、プレビューや画像一覧から本文欄へ戻れます。「下書き保存」「公開して保存」は画面の下に残ります。
スマホを縦にしているときは、道具の列は本文欄のすぐ下です。目のアイコンでプレビューを画面いっぱいに開き、公開ページと同じ大きさで表示します。下の「閉じて編集に戻る」（Escでも閉じます）で編集に戻ります。「画像一覧から選ぶ」は画像一覧を小さな画面で開きます。
画像は編集画面のどこへドロップしても、本文へ貼り付けても追加でき、`![説明](./?media=…)` の行が入ります。
本文の画像は、投稿画面のようにサムネイルで並べます（スマホでは本文の下、PCではメディア欄の「このページ」）。押すと本文のその行を選び、×で本文から外します（画像そのものは画像一覧に残ります）。並びの最後の「＋」と画像のボタンからも追加できます。保存は通信で行い、保存できなかったときも書いた本文は画面に残ります。URL名の重複や、別の画面で更新された場合は保存しません。

下の例は、プロフィールの本文に画像を入れ、プレビューを開いた状態です。上でタイトル・URL名・ページの幅を決め、本文の下で画像の並びと表示を確認します。「下書き保存」では読者に公開せず、「公開して保存」で公開します。

![固定ページの編集画面。タイトルとURL名、3種類の幅、Markdownの本文、画像のサムネイルとプレビュー、下書き保存と公開して保存](docs/images/log-fixed-page-edit.jpg)

固定ページの説明文（`meta description`）は、本文の最初の部分からMarkdownの記号を除いて作ります。公開中の固定ページはサイトマップに載り（優先度0.5）、検索エンジンに載せる設定なら `index,follow` です。パンくずリストは「HOME › タイトル」です。トップメニューの候補にも出ます。固定ページで使っている画像は、画像一覧で削除できません。

### トップページとブログ

WordPressの「ホームページの表示」のように、サイトのトップに固定ページを出し、投稿の一覧を「ブログ」として別のURLへ移せます。
「設定」の「LOG」タブにある「トップページとブログ」で、オン・オフを切り替えます。初めはオフで、今までどおりトップに投稿の一覧を出します。

NagiLogをドメインの直下（`https://example.com/`）に置いた場合は、次のようになります。

| ページ | オフ（標準） | オン |
| --- | --- | --- |
| トップ | `https://example.com/`（投稿の一覧） | `https://example.com/`（選んだ固定ページ） |
| 投稿の一覧 | `https://example.com/` | `https://example.com/blog` |
| カテゴリ・タグ・日付・検索・2ページ目以降 | `https://example.com/?category=…` | `https://example.com/blog?category=…` |
| 個別投稿・ほかの固定ページ | `https://example.com/20261004123033`／`https://example.com/privacy` | 変わりません |

| 項目 | 内容 |
| --- | --- |
| トップページに出す固定ページ | 固定ページの中から選びます。選んだページは自分のURL（`./about` など）ではなく、トップのURLで表示し、元のURLを開くとトップへ301で移ります。下書きの間は、ログインしていない人がトップを開くとブログへ移ります（ログイン中は下書きのまま確認できます） |
| ブログのURL名 | 標準は `blog`。半角の英小文字・数字・ハイフンで40文字までです。固定ページと同じURL名や、`admin` などLOGのフォルダー名は使えません。`.htaccess` が効かないサーバーでは `./?pg=blog` です |
| ブログの表示名 | メニューとパンくずリストに出す名前です。空のままだと「ブログ」（英語の画面では Blog） |
| ブログへのリンク | 「トップメニューの先頭に出す」「フッターのリンクに出す（HOMEの次）」を選べます。どちらも標準でオンです。URL名や表示名を変えても、リンクは自動で変わります |

ブログのURLは、固定ページと同じ深さの `./blog` です。末尾に `/` を付けた `./blog/` は `./blog` へ301で移ります（LOGのリンクや画像は相対URLなので、フォルダーの形にしないためです）。
オンにすると、それまでの `./?category=…` や `./?page=2` はブログの同じ一覧へ301で移ります。オフに戻すと、`./blog?…` はトップの一覧へ移るので、貼ってあったリンクはどちらに切り替えても使えます。

パンくずリストは、ブログの一覧で「HOME › ブログ」、カテゴリで「HOME › ブログ › カテゴリ名」、記事で「HOME › ブログ › カテゴリ名 › 記事のタイトル」です。トップの固定ページにはパンくずリストを出さず、`<title>` はサイト名だけにします。
サイトマップには、トップ（優先度1.0）、ブログ（0.8）、カテゴリ（`./blog?category=…`）を載せ、トップにした固定ページは元のURLでは載せません。RSSの `<link>` もブログのURLです。
トップメニューやフッターのリンクの候補にも「ブログ（すべての投稿）」が出ます。好きな位置に置きたいときは、上のチェックを外してから、項目を追加して表示名に「ブログ」と入れ、候補から選びます。この方法で入れたリンクは、あとでURL名を変えたときに手で直してください。
設定はLOG用のバックアップに入ります。

## SEOとOGP

検索エンジンに載せるページは、一覧の見せ方で変わります。
「設定 → LOG → 検索エンジンとサイトマップ」に、今の設定での指定を表で表示します。

**タイル**

| ページ | 検索エンジンへの指定 |
| --- | --- |
| トップ・カテゴリ（2ページ目以降も） | `index,follow` |
| 個別の記事 | `index,follow` |
| ハッシュタグ・日付・月・検索結果 | `noindex,follow` |
| 投稿がない一覧 | `noindex,follow` |

タイルの一覧には記事の中身がないため、個別の記事を検索の入口にします。
2ページ目以降も、それぞれのURLを正規URL（canonical）にして載せます。古い記事へのリンクを検索エンジンがたどり続けられるようにするためです。
ハッシュタグは数が多く、カテゴリと内容が重なりやすいため、載せません。日付・月の一覧と検索結果も、同じ記事を並べ替えただけなので載せません。

**ミニブログ（標準）**

| ページ | 検索エンジンへの指定 |
| --- | --- |
| 全体公開で、投稿があるトップ・カテゴリの1ページ目 | `index,follow` |
| 個別投稿・ハッシュタグ・日付・月・検索結果・2ページ目以降 | `noindex,follow` |
| 投稿がない一覧 | `noindex,follow` |

ミニブログは一覧に記事の全文を並べるため、トップとカテゴリを検索の入口にします。
個別投稿をnoindexにすると、その投稿自体からの検索流入は受けられません。
重複をまとめるだけならcanonicalも使えるため、個別投稿のnoindexは必須ではありません。

**共通**

| ページ | 検索エンジンへの指定 |
| --- | --- |
| 自分専用Memoの全ページ | `noindex,follow`。未ログインには404 |
| R-18の記事 | `noindex,follow`。サイトマップにも載せない |
| ログイン・管理画面・404 | `noindex,nofollow` |
| RSS | `noindex`（RSSリーダー用のため） |

詳しくはGoogleの [noindexの説明](https://developers.google.com/search/docs/crawling-indexing/block-indexing?hl=ja) と
[正規URLの説明](https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls?hl=ja) を参照してください。

### パンくずリスト

トップの1ページ目以外では、本文の上にパンくずリストを出します。家のアイコンと「HOME」から始まり、今のページで終わります。

| ページ | パンくず |
| --- | --- |
| 記事 | HOME › 最初のカテゴリ › 記事のタイトル（カテゴリがない記事はHOME › 記事） |
| カテゴリ・ハッシュタグ・検索結果 | HOME › カテゴリ名・#タグ名・「言葉」の検索結果 |
| 日付・月 | HOME › 2026年10月 › 10月4日 |
| 2ページ目以降 | 上の続きに「2ページ目」 |

先頭の文字は「設定 → LOG → 一覧の見せ方・記事の下 → パンくずリストの先頭」で、`HOME`（標準）・サイト名・任意の文字（30文字まで。空なら`HOME`）から選べます。

同じ階層を、schema.orgの`BreadcrumbList`（JSON-LD）でも出します。検索エンジンがページの位置を理解でき、検索結果にもURLの代わりに階層が表示されることがあります。
アイコンと区切りの記号はSVGで描いています。長い名前は「…」で省略し、今のページの名前を優先して見せます。

### 検索エンジンに載せない

二次創作のサイトや、公式と間違われたくないサイトのために、「すべてのページを載せない（noindex,nofollow）」を選べます。
すべてのページ（ヘッダーと`<meta>`の両方）とLOGの画像に「載せない・リンクをたどらない」と伝え、サイトマップを止めます（404）。
すでに載っているページは、検索エンジンが次に読みに来たときに消えます。指定に従うのは、ルールを守る検索エンジンだけです。
robots.txtで一括拒否はしません。robots.txtで拒否すると、検索エンジンがnoindexを読めなくなり、URLだけが検索結果に残ることがあるためです。

### サイトマップ

`https://設置先/?sitemap=xml` で、検索に載せるページだけのサイトマップを出します。
URLは「設定 → LOG → 検索エンジンとサイトマップ」でコピーできます。Google Search ConsoleやBing Webmaster Toolsに登録してください。

| 載せるページ | 優先度（priority） | 最終更新日（lastmod） |
| --- | --- | --- |
| トップ | 1.0 | 最後に更新した記事・設定の日時 |
| 個別の記事（タイルのときだけ） | 0.7 | その記事を更新した日時 |
| 記事のあるカテゴリ | 0.5 | そのカテゴリで最後に更新した記事の日時 |

2ページ目以降は、各ページのリンクからたどれるので載せません。
Googleはpriorityを使わず、正確なlastmodを参考にすると案内しています。lastmodには実際の更新日時を入れています。
LOGをサブフォルダーに置いた場合、ドメイン直下のrobots.txtには自動で書き込めません。サイトマップは検索エンジンの管理画面から登録してください。
変更がなければ`304 Not Modified`を返すので、何度読みに来られてもサーバーの負担は小さく済みます。

### RSS

`https://設置先/?feed=rss` で、新しい20件のRSS 2.0を出します。
カテゴリだけなら `?feed=rss&category=カテゴリID`、ハッシュタグだけなら `?feed=rss&tag=タグ名` です。
「設定 → LOG → RSS」で範囲を選ぶとURLができ、「コピー」で写せます。
配信するのは、タイトル・URL・投稿日・カテゴリ名・説明文です。本文の全文は配信しません。
LOGのページには、RSSの場所を知らせるタグを入れています。カテゴリやハッシュタグの一覧では、その範囲のRSSも知らせます。
自分専用のMemoでは、RSSを出しません。

### 説明文（description）

個別の記事の説明文は、本文（2行目以降）の文章から自動で作ります。
画像・漫画のタグ、URL（埋め込み・ブログカード・リンク）、ハッシュタグ、太字の記号を除き、文章だけを120文字まで使います。
文章がない記事は、サイトの紹介文を使います。RSSの説明文も同じです。タイトルは今までどおり、本文の1行目です。

OGPは、URLをSNSなどで共有したときに出る紹介カードの情報です。
個別投稿では、本文の先頭から見て、閲覧注意の付いていない最初の画像を使います（SVGは使いません）。
1枚だけセンシティブな画像がある記事も、ほかの画像がカードになります。
画像タグを並べ替えると、選ばれる画像も変わります。
画像がない投稿のOGPは、設定した共通OGP画像です。未設定なら同梱の共通画像を使います。
漫画だけの投稿も、この共通画像を使います。

注意つきの画像しかない記事と、記事全体にセンシティブ・R-18・R-18Gを付けた記事は、カード用の画像（1200×630のWebP）をサーバーで作ります。
本文の最初の注意つき画像を、形が分からないところまでぼかして暗くし、真ん中にガラス風のカードで区分の名前（センシティブ／R-18／R-18G）と注意書き、「閲覧注意」を重ねます。
URLは `./?ogimage=記事の番号&v=…` で、SNSが最初に読みに来たときに作り、`data/log/og/` に保存して使い回します。画像を差し替えたり区分を変えたりすると、別のURLの新しい画像になり、古いものは消えます。記事を削除すると一緒に消えます。WebPを書き出せないサーバーではJPEGで作ります。

区分の名前の部分は、あらかじめSVGで作った絵を、透過PNG（`viewer/og-veil/`）にして同梱しています。サーバーはGDでぼかした画像に重ねるだけなので、フォントやFreeTypeは要りません。文字はオープンソースのフォント M PLUS Rounded 1c（SIL Open Font License）で描いています（`viewer/og-veil/LICENSE-font.txt`）。デザインを変えるときは、`manga/dev/build_og_veil.py` を実行すると、フォントを取得してSVGからPNGを作り直します。
全体公開のLOGは、検索から除外する投稿にも共有カードを残します。
自分専用Memoでは、外部サービスに本文やLOG画像を渡さないため、OGPカードは利用できません。

## 画像収集BOTへの対策

設定の「共通・安全 → 画像収集BOTへの対策」で、収集ツール名と取得回数の上限を調整できます。
既定では、画像収集ツールを示すUser-Agentと、同じIPからの大量取得を404で拒否します。
LOG画像と漫画画像に共通で適用します。文章の閲覧やAIを一律に拒否する設定ではありません。

既定の上限は、10秒区間に120件、1分区間に300件です。
上限を超えたIPからの画像取得は5分間拒否します。
同じ回線を使う人や、画像の多い漫画の閲覧も回数に含まれます。
正当な閲覧に影響があるときは、上限や収集ツール名を調整してください。

User-Agentを普通のブラウザに偽装し、少量ずつ取るBOTや、IPを分散するBOTは完全には見分けられません。
公開された画像の保存をすべて防ぐ仕組みでもありません。
大規模な取得への対策は、必要に応じてサーバーやCDN側にも設けてください。

ほかのサイトのページや掲示板にLOGの画像を貼られても表示しない「直リンク防止」は、v0.12.0 から新しく設置したサイトでは最初からオンです。それより前のサイトは、LOGの管理画面のお知らせで「オンにする」を押すか、設定の「NagiMANGA → 上級者向けの設定 → 直リンク防止」でオンにします。URL を貼ったときのリンクのカード、URL を直接開いたとき、RSS リーダーの取得では表示します。OGP 画像（共通の OGP 画像と、記事のカードに使う最初の画像）は、ほかのサイトのページからも表示します。相互リンクのバナーなどは、画像一覧で画像ごとに「ほかのサイトにも貼れるようにする」を選べます。詳しくは [NagiManga の README](README.md#直リンク防止上級者向けv030-以降) にあります。

## 保存先を守る

保存先はNagiMangaと共通の `data/` です。
公開フォルダの外へ移す方法を推奨します。たとえば、サーバー上の
`/home/you/nagimanga-data` に保存先を移し、`lib/paths.php` を次の内容で作ります。

```php
<?php return '/home/you/nagimanga-data';
```

PHPから書き込めることを確認してください。
公開フォルダ内へ置く場合は、`.htaccess` などで `data/` へのHTTPアクセスを拒否します。
nginxなどで `.htaccess` が使えない場合は、保存先を外へ移すか、サーバー設定で拒否してください。

LOGの内部記録は直接開くと404になるPHP形式ですが、画像ファイルにはPHPの処理がありません。
セキュリティログ（`logs/security.log.php`）と、初回だけ作るセットアップの鍵（`setup-key.php`）も、同じく直接開くと404になるPHP形式です。

> [!CAUTION]
> HTTPで保存先へ入れる状態では、画像の実パスが判明すると認証やBOT対策を迂回できます。
> 秘密鍵から作った保存フォルダ名は、暗号化の代わりにはなりません。
> 管理画面の警告と、外部からの直接アクセス拒否を、公開前に確認してください。
> サーバー設定の詳しい例は [NagiMangaの設置説明](README.md#data-フォルダを守る) にあります。

## 保存構造とバックアップ

| 保存物 | `data/` 内の場所 |
| --- | --- |
| 公開済み投稿の原本 | `log/posts/年/投稿番号.php` |
| 初回公開前の下書き | `log/posts/drafts/仮番号.php` |
| 一覧用の派生情報 | `log/index.php` |
| カテゴリ | `log/taxonomy.php` |
| LOGの表示設定 | `log/settings.php` |
| サイドバーの順番・表示・リンク集・HTML枠 | `log/sidebar.php` |
| トップメニュー | `log/topmenu.php` |
| フッターのリンク | `log/footmenu.php` |
| 固定ページ | `log/pages/ページ番号.php` |
| ピン留めとその順番 | `log/pins.php` |
| ファビコンとホーム画面のアイコン | `log/favicon/版番号/` |
| 追加CSS（使用中と直前の内容、適用のオン・オフ） | `log/custom-css/` |
| いいねの数 | `log/likes.php` |
| その日に押された数（読者ごと。翌日に作り直し） | `log/likes-today.php` |
| 画像と画像情報 | `log/media/秘密鍵から作るフォルダ/` |

一覧用ファイルの内容は、原本から読み直せる派生情報です。
FTPで原本を編集した場合は、`log/index.php` を取り除くと一覧へ反映できます。
通常の投稿・編集では、一覧用ファイルも更新します。

バックアップ画面で、漫画用ZIPとLOG用ZIPをそれぞれ保存します。
LOG用ZIPには、本文、下書き、画像、カテゴリ、デザイン、アイコン、OGP設定を含めます。
公開範囲、ログインリンクの表示、公開側の表示件数、ページ送りの形式、フッター、分類の並び順も保存します。
サイドバーの順番、リンク集、HTML枠も含めます。外部リンク先の画像ファイルは取り込みません。
トップメニュー、フッターのリンク、トップへのリンクの表示、固定ページ、タイトルロゴ、紹介文の表示の設定、SVGの画像も含めます。
復元先に同じURL名の別の固定ページがある場合は、復元するほうのURL名に番号を付けて両方残します。
固定ページ・トップメニュー・フッターのリンクを含まない旧形式のZIPでは、それぞれ復元先のものを維持します。
一覧の見せ方、いいね・関連記事の設定、検索エンジンの設定、記事ごとのいいねの数も含めます。
記事と画像の閲覧注意（区分と注意書き）、記事と固定ページのパスワード（鍵）、ピン留めとその順番も含めます。その日に押された数と、ファビコンの画像は含めません。
追加CSSと適用のオン・オフも含めます。追加CSSを含まない旧形式のZIPでは、復元先の追加CSSを維持します。
上書き復元では、そのZIPに保存された公開範囲も反映します。
公開範囲を持たない旧形式のZIPでは、復元先の公開範囲を維持します。
サイドバーを含まない旧形式のZIPでは、復元先のサイドバーを維持します。
ハッシュタグは本文から読み直します。
管理者のパスワード、秘密鍵、IP制限、BOT対策の設定は含めません。
これらの設定は引っ越し先で確認してください。

漫画を含むLOGの引っ越しでは、先に漫画用ZIP、次にLOG用ZIPを復元します。
LOG用ZIPだけでは、漫画のページ画像は移りません。
同じIDがある投稿・画像は通常は上書きせず、上書き指定時だけ差し替えます。
復元前にも、引っ越し先のバックアップを取ってください。

LOG用ZIPの復元は、1回の通信で全部の画像を変換しません。
ZIPを送ったあと、画像を数秒ずつ変換し、最後に投稿と設定をまとめて書き込みます。
画像の多いZIPでも、サーバーの時間制限（503など）にかかりにくくなります。
復元中は、手順・進み具合・残り時間を波の形のメーターで表示します。
サーバーが一時的に応答しないときは、3回まで待ってから聞き直します。
途中で止まった場合や中止した場合、LOGは書き換えません。送ったZIPと変換途中の画像は消します。
JavaScriptが動かない環境では、これまでどおり1回の通信で復元します。

## 検証と残る確認

2026年10月4日に、別Agentが専用コピーで機能監査と敵対検証を行いました。
機能監査は、データを作り直して繰り返しています。

| 検証 | 結果 |
| --- | --- |
| LOGのHTTP・保存・復元など | 153項目を2回通過 |
| 既存の漫画CMS | 186項目を2回通過 |
| 管理者表示・Memo・表示件数の独立試験 | 93項目を2回通過 |
| フッター・分類順序・記事削除 | 104項目を2回通過 |
| ローカル起動・再起動 | 6項目を2回通過 |
| 削除途中の保存故障 | 4項目を2回通過 |
| サイドバー・HTML枠・共有画像・プロフィール | 120項目通過 |
| 削除・並び順の敵対検証 | 68項目通過。JSON・更新番号の境界50項目も通過 |
| HTML枠の敵対検証 | HTML・URL・ZIP・画像保護など153項目通過 |
| ブラウザ | 390×844とパソコン幅で投稿・プレビュー・保存・浮遊ボタン・設定タブ・Memo・投稿一覧を確認。サイドバーは390×844でドラッグ・上下移動・HTML追加・保存・公開表示を確認 |

同じ日の夜に加えた変更のあと、次を再確認しました。変更は、メールのダイアログ、404、吹き出し、日付表示、「書く」ボタンの位置、ログインの保持です。

| 検証 | 結果 |
| --- | --- |
| LOGのHTTP・保存・復元など | 154項目通過 |
| 漫画CMSとセキュリティ（ログインの保持を含む） | 192項目通過 |
| サイドバー・メールのリンク | 127項目通過 |
| フッター・分類順序・記事削除 | 104項目通過 |
| ブラウザ | パソコン幅と390×844で、メールのダイアログ（コピー・送信・Esc）、404の動き、横はみ出しがないことを確認 |

続けて追加した、SNSや動画の埋め込み、ブログカード、GIFアニメの保存は、次で確認しました。

| 検証 | 結果 |
| --- | --- |
| 埋め込み・カード・GIFアニメ（新しい試験） | 58項目通過。17パターンの自動埋め込み、文中のURLはリンクのままにすること、似たドメインの拒否、CSP、プレビュー、OGPカード（転送・Shift_JIS・分割転送・エスケープ・内部アドレスの拒否・訪問者の表示で取りに行かないこと）、GIFの組み直し・差し替え・復元を含む |
| LiteSpeed Cache（新しい試験） | 18項目通過。LiteSpeedとして動かしたサーバーで、キャッシュする・しないの区別、ログインCookieでの分離、変更時の削除、オン・オフを確認。LiteSpeedでないサーバーには何も送らないことも確認 |
| 既存の試験 | LOG 154項目、セキュリティ192項目、サイドバー127項目、削除など104項目を再び通過 |
| ブラウザ | パソコン幅と390×844で、YouTube・X・Spotify・Steam・マンガの表示、GitHubとphp.netのブログカード、横はみ出しがないこと、トリプルクリックで選んだ行の太字を確認 |

機能側は合計634項目を各2回確認しました。
最後の画像URL判定の修正後は、サイドバー88項目と削除104項目を再確認しています。
ほかの変更がない部分は、その直前の回帰試験を維持しています。

監査で見つかった、数字だけのカテゴリIDの表示・復元の不具合と、
同じ秒の100件目以降の並び順の不具合を修正しました。
タイトル行を本文で繰り返す表示も修正し、回帰試験に追加しています。
今回の監査では、10件表示に合わせて原本復旧の試験を全ページ確認へ変え、
認証済み画像のキャッシュ指定を本文とそろえました。
削除では、数字だけの画像ID、空のフォルダ、JSONの型を追加で確認しました。
HTML枠では、安全化後の長さと、画像URLの表記違いによる削除保護の漏れを修正しています。
詳しい結果は [監査記録](docs/personal-log-audit.md) にまとめています。

実際のiPhone・Android、公開サーバーのApache・nginx設定、共有先のOGP取得は未確認です。
公開前に、設置先でログイン、アップロード、バックアップ、画像の直接アクセス拒否を確認してください。

再実行する場合は、リポジトリのルートで次を実行します。
テストは専用コピーを作り、通常の保存データを変更しません。

```text
python manga/dev/log_test.py
python manga/dev/attack_test.py
python manga/dev/log_management_test.py
python manga/dev/log_sidebar_test.py
python manga/dev/log_embed_test.py
node manga/dev/log_embed_script_test.js
python manga/dev/log_lscache_test.py
python manga/dev/log_av_test.py
python manga/dev/preview_test.py
python manga/dev/log_css_test.py
python manga/dev/log_css_browser_test.py
python manga/dev/hardening_test.py
python manga/dev/css_catalog_check.py
python manga/dev/build_release.py
```

2026年10月7日の追加確認では、埋め込みのHTTPテストは124件、LOGの基本テストは204件とも通りました。
表示調整のJavaScriptも、外部メッセージの確認とFacebookのスマホ幅を検証しています。
ブラウザでは、公式アカウントや公式資料の公開URLを使い、14種類の表示を確認しました。
確認用のURLは [埋め込みサンプル](dev/embed_samples.json) にまとめています。
`dev/seed_embed_gallery.py` は、既に設置したローカルの確認用LOGに、これらのサンプルを作ります。
`log-test-password` を使う開発用のサイトだけで使ってください。

2026年10月14日に追加CSSを加え、次を確認しました。

| 検証 | 結果 |
| --- | --- |
| 追加CSSのHTTP（`dev/log_css_test.py`） | 94項目通過。保存・配信（text/css）・管理画面に出さないこと・構文エラーと警告の区別・256KiB・空・UTF-8・日本語コメント・未ログイン・ゲスト・CSRF・パス風の値・同時編集・書き込み失敗・復元・オンオフ・スクリプトなしの保存・キャッシュのURL・LiteSpeedの削除・バックアップと旧形式ZIP・自動更新・取り消し・FTPでの上書き・配布ZIP・一覧チェックの失敗と通過 |
| 追加CSSのブラウザー（`dev/log_css_browser_test.py`） | 115項目通過。Playwright の Chromium と WebKit で、パソコン幅とスマホ幅（Pixel 7・iPhone 13 の画面サイズ）。画面とサーバーの構文チェック49件の一致、入力・診断への移動・ファイル選択・ドロップ・サイズと文字コードの拒否・保存と再読み込み・公開ページへの反映・同時編集・オンオフ・一覧の絞り込みと複数バージョンの比較、ほかのページで編集用ファイルを読み込まないこと、英語表示 |
| 既存の試験 | LOG 204、セキュリティ 192、サイドバー 133、管理 107、固定ページ 94、機能 74、ピン・鍵 77、閲覧注意 30、LiteSpeed 24、英語 22、プレビュー 7、翻訳 3079 項目を通過 |

WebKitの確認は、このPC上のPlaywrightのWebKitです。実機のiPhone（Safari）での確認はしていません。

2026年10月21日に「トップページとブログ」（v0.9.0）を加え、次を確認しました。

| 検証 | 結果 |
| --- | --- |
| トップページとブログ（`dev/log_front_test.py`） | 70項目通過。`.htaccess` の書き換えがあるサーバーとないサーバーの両方で、トップの固定ページ、`./blog` の一覧・カテゴリ・ページ送り・検索、元のURLや `./?category=…`・`./blog/` の301転送、パンくずリスト、メニューとフッターのリンク、サイトマップ・RSS、下書き・鍵付きのトップ、オフに戻したときの転送、入力の誤りを断ること |
| 既存の試験 | LOG 204、セキュリティ 192、サイドバー 133、管理 107、固定ページ 94、機能 89、ピン・鍵 77、閲覧注意 30、LiteSpeed 24、英語 22、埋め込み 124、追加CSS 94、動画・音声 28、プレビュー 7、翻訳 3209項目すべて通過 |
| ブラウザー | Playwright の Chromium で、パソコン幅（1280px）とスマホ幅（390px）のトップ・ブログ・設定画面を表示し、横にはみ出さないことを確認 |

色のコントラスト（WCAG 2.2 AA）は、次で6つのテーマすべてを確かめます。PlaywrightとGoogle Chromeが必要です。
40件の記事を作ってページ送りを11ページにし、3種類のページ送り、ミニブログとタイル、PCとスマホの幅、開いたメニューやダイアログ、ホバー、キーボードの枠まで測ります。

```text
python manga/dev/contrast_audit.py
```

2026年10月27日に、セキュリティレビュー（v0.11.1）の指摘への対応（v0.12.0）を加え、次を確認しました。2026年10月28日の v0.12.1（OGP 画像を直リンク防止の対象外に、閲覧パスワードの全体上限を「待たせるだけ」に、直リンク防止の画像を共有キャッシュに置かせない）でも、同じ試験を通しています。

| 検証 | 結果 |
| --- | --- |
| 守りの強化（`dev/hardening_test.py`） | 26項目通過。8つのIPから40回失敗させたあとも、持ち主の印のあるブラウザー・許可IP・攻撃者と同じIPの持ち主はログインできること、印のないブラウザーは待たされること、偽造した印・盗んだ印で5回失敗したあとの印は効かないこと。IPv6の同じ/64でアドレスを替えても5回で止まり、別の/64は別に数えること、作品ごとの1時間60回を超えても止めずに1件ずつ確かめ、番が埋まっていれば「混み合っている」と返し、初めての読者も番を待てば開けること、すでに開けた読者は読めること。ログイン中の画面から今のパスワードを当て続けられないこと。ログと更新の確認の記録が `.htaccess` なしでも空の404で、古いログと `check.json` が移ること |
| セキュリティ（`dev/attack_test.py`） | 206項目通過。セットアップの鍵（鍵なし・違う鍵・10回の失敗・`.htaccess` なしで読めないこと）、署名のない更新・差し替えたZIP・別の鍵・古い版の署名・形の崩れた署名を拒否すること |
| パスキー（`dev/passkey_test.py`） | 46項目通過。全体の上限の間もパスキーならログインできること |
| 古い版からの更新 | v0.11.1 を設置し、その更新機能のまま v0.12.0 に更新できること。ログインしたまま印が付き、古いログを引き継ぐこと（7項目） |
| セットアップと入口（`dev/login_entry_test.py`） | 43項目通過。セットアップ画面のお断りと鍵の見つけ方、「おもに使うもの」で選んだ画面がログイン画面と完了の画面に出ること。二段階認証をすすめるダイアログが1回のログインで1度だけ出て、「今後は表示しない」で出なくなること |
| LOGの直リンク防止（`dev/log_test.py`） | LOG 223項目通過。新しく設置したサイトでは最初からオンで、ほかのサイトのページからの画像・サムネイルを404にし、LOGのページ・許可したサイト・URLを直接開いたとき・カードやRSSの取得では表示すること。「ほかのサイトにも貼れる」画像と OGP 画像は対象外になること（OGP 画像でもサムネイルは対象）。対象の画像は共有キャッシュに置かせないこと。漫画のスイッチとは別に動くこと。前からのサイトでは、お知らせの「オンにする」「今はしない」が効くこと |
| 既存の試験 | サイドバー 133、管理 107、固定ページ 94、機能 100、ピン・鍵 77、閲覧注意 30、LiteSpeed 24、英語 22、埋め込み 124、追加CSS 104、追加CSSのブラウザー 119、動画・音声 28、トップとブログ 70、二段階認証 49、プレビュー 7、翻訳 3559 項目を通過 |

2026年10月29日の v0.13.0（アクセス解析のコードを安全に貼れるように、検索エンジンの所有権の確認、ページ埋込の配布ファイル保護）で、次を加えて確認しました。

| 検証 | 結果 |
| --- | --- |
| アクセス解析（`dev/analytics_test.py`） | 34項目通過。計測サービスのコードを `<script>` タグごと保存でき、公開LOGと作品ページに入ること。公開ページの CSP にコードのサイトとハッシュだけを足し、Google アナリティクス・Clarity が続けて使うサイトも許すこと。`<noscript>` を外し、ログイン中の持ち主と管理画面では計測しないこと。検索エンジンの所有権確認の meta タグ（Google・Bing・Yandex・Naver・百度）を保存できること |
| アクセス解析の敵対検証（`dev/analytics_adversarial_test.py`） | 69項目通過。Cookie・保存データ・フォームの読み取り、キー入力の監視、ほかのページへの移動、ページの書き換え、自前の通信、文字列の実行（`eval` など）、難読化、マイニング、`<script>` 以外のタグ・危険な属性・`http://` の読み込み、過大な入力をすべて拒否し、何も保存せず公開ページに出さないこと。設定ファイル（`data/config.php`）を直接書き換えても、描画のたびに同じ確認をして出さないこと |
| ページ埋込の配布ファイル保護（`dev/log_embed_guard_test.py`） | 10項目通過。相手がプログラム・インストーラ・書庫などのダウンロード（メディアの種類・`Content-Disposition`・URL 末尾の拡張子で判定）のときは、ページ内で開くカバーを出さず、「このページは開けません」と外部リンクだけにし、古いページの正しい署名でも `embed.php` が 404 にすること。普通のHTMLページはこれまでどおり枠に入れること |
| 既存の試験 | サイドバー 133、管理 107、固定ページ 94、機能 100、ピン・鍵 77、閲覧注意 30、LiteSpeed 24、英語 22、埋め込み 124、追加CSS 104、追加CSSのブラウザー 119、動画・音声 28、トップとブログ 70、二段階認証 49、プレビュー 7、翻訳 3657 項目を通過 |

## 参照元と文章

NagiLogのプログラムは、作者がClaude Codeに依頼し、NagiMangaの保存と認証の上に新しく書いたものです。
てがろぐ（CGI）本体のプログラムや、機能の作り方は参照していません。

見た目は、作者が作ったてがろぐ用スキン [NagiMemo](https://github.com/Lichiphen/NagiMemo) のCSSの一部をNagiLogに加えています。
てがろぐで使っていた見た目は、このCSSで補っています。
投稿欄、スマホのパネル、画像追加の分け方は、NagiMemoの画面構成を参考にしました（コミット `e2fc9df1af817e9ca2fd09f1c444698c1b90edf9`）。
てがろぐ用の保存処理や記法は移植していません。
NagiMemoとNagiSwipeは、ともにLichiphenのMITライセンスです。

このREADMEはsoft-japanese-writingに沿って作成し、yomiyasuで推敲・検査しています。
実装の判断と追加した仕様は [作業記録](docs/personal-log-plan.md) に残しています。
