From 1f2999e0e95261067c7ee1364b1827b5f44a494b Mon Sep 17 00:00:00 2001 From: Daiki Ikeda Date: Sat, 6 Jun 2026 13:02:23 +0900 Subject: [PATCH] =?UTF-8?q?=E9=81=B8=E6=8A=9E=E3=82=AD=E3=83=A3=E3=83=A9?= =?UTF-8?q?=E3=81=AE=E3=82=BB=E3=83=AA=E3=83=95=E3=82=92=E3=83=97=E3=83=AC?= =?UTF-8?q?=E3=83=BC=E3=83=B3=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88=E3=81=A7?= =?UTF-8?q?=20txt=20=E6=9B=B8=E3=81=8D=E5=87=BA=E3=81=97=E3=81=99=E3=82=8B?= =?UTF-8?q?=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 元の台本にある「」の中身を変換せずそのまま書き出すため、Dialogue に 全角化前の生テキスト rawText を持たせ、書き出しは isHighlighted を共有する 純粋関数 buildDialogueText に集約。FAB に txt ボタンを追加した。 Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 1 + README.md | 2 + src/App.tsx | 14 ++++++- src/components/FloatingActions.tsx | 14 ++++++- src/lib/dialogue.test.ts | 1 + src/lib/exportDialogue.test.ts | 66 ++++++++++++++++++++++++++++++ src/lib/exportDialogue.ts | 23 +++++++++++ src/lib/parseScript.test.ts | 47 ++++++++++++++++++--- src/lib/parseScript.ts | 7 ++-- src/types.ts | 2 + 10 files changed, 166 insertions(+), 11 deletions(-) create mode 100644 src/lib/exportDialogue.test.ts create mode 100644 src/lib/exportDialogue.ts diff --git a/CLAUDE.md b/CLAUDE.md index bc88a72..b251155 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,3 +25,4 @@ pnpm typecheck # tsc -b のみ - ハイライト条件(キャラ選択 ∧ ボイス不要でない)は `src/lib/dialogue.ts` の `isHighlighted` に集約。件数集計・表示判定・連番付与がすべてこれを共有する - `Dialogue.character === ""` が地の文を表す(null ではなく空文字) - `toggleCharacter` は選んだ名前を部分文字列として含む全キャラを一括トグルする(例 「田中」で「田中A」「田中B」も切り替わる) +- `Dialogue.text` は `toZenKaku` で全角化済みの表示用、`Dialogue.rawText` は元の「」の中身そのまま(変換なし)。txt 書き出し(`src/lib/exportDialogue.ts`)は `rawText` を使う diff --git a/README.md b/README.md index 3d693a1..056da5f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ - 縦書きの日本語台本を表示 - txt ファイルからのデータ読み込み - キャラクター名別にセリフの強調表示 +- 選択キャラのセリフを 1 行 1 セリフのプレーンテキスト txt で書き出し(元の「」の中身を変換せずそのまま出力) - 印刷用のスタイル設定(背景色、フォントサイズなど) - ブラウザ上での直接印刷サポート @@ -25,6 +26,7 @@ 2. txt ファイルを選択してアップロードします。 3. キャラクター名のチェックボックスを使用してセリフの表示をトグルします。 4. ブラウザから印刷します。 +5. 右下の「txt」ボタンで、選択中キャラのセリフをプレーンテキストの txt として書き出せます。 ## ローカルでのセットアップ diff --git a/src/App.tsx b/src/App.tsx index 3b2ce08..af3a89c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { ScriptSummary } from "./components/ScriptSummary"; import { ScriptView } from "./components/ScriptView"; import { toggleCharactersByMatch } from "./lib/characterToggle"; import { isHighlighted } from "./lib/dialogue"; +import { buildDialogueText, exportFileName } from "./lib/exportDialogue"; import { parseScript, type ParseWarning } from "./lib/parseScript"; import { toggleInSet } from "./lib/setOps"; import type { Dialogue } from "./types"; @@ -72,6 +73,17 @@ export function App() { setNoVoice((prev) => toggleInSet(prev, id)); }; + const exportText = () => { + const text = buildDialogueText(dialogues, selected, noVoice); + const blob = new Blob([text], { type: "text/plain;charset=utf-8" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = exportFileName(title); + a.click(); + URL.revokeObjectURL(url); + }; + return ( <> - + ); } diff --git a/src/components/FloatingActions.tsx b/src/components/FloatingActions.tsx index 3140edf..487e10b 100644 --- a/src/components/FloatingActions.tsx +++ b/src/components/FloatingActions.tsx @@ -1,4 +1,8 @@ -export function FloatingActions() { +type Props = { + onExportText: () => void; +}; + +export function FloatingActions({ onExportText }: Props) { const scrollToStart = () => window.scrollTo({ left: 0, top: 0, behavior: "smooth" }); const scrollToEnd = () => @@ -27,6 +31,14 @@ export function FloatingActions() { > ← +