mdv-live 0.5.15 → 0.5.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,108 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.17] - 2026-05-10
9
+
10
+ ### Added — Edit-mode Autosave
11
+
12
+ Markdown エディタを **入力 → 1500ms debounce で自動保存** に。これまで Cmd+S を
13
+ 押し忘れると未保存で View に戻すと内容が消える挙動だった。
14
+
15
+ - `input` で 1500ms debounce → `EditorManager.save()` が `/api/file` に POST
16
+ - toolbar status の遷移: `Modified → Saving... → Saved! → (2s 後) Ready`
17
+ - **Cmd+S** は引き続き使えて、押すと pending な debounce を即 flush
18
+ - View 切替 / タブ切替 / 別ファイル open 時に **flush + await** で未保存破棄事故を防止
19
+ - save 中の連続 input は serialize(chain)。古い save が後着して新しい save を
20
+ 上書きしないよう、各 save 自身の Promise を chain tail にして flush は末尾まで drain
21
+ - save 失敗時は `hide()` / `switch()` / `open()` がすべて navigation を中止して
22
+ Edit mode を維持。toolbar に `Error: ...` を表示してリトライ余地を残す
23
+ - discard-on-close ダイアログ: AbortController で in-flight POST も abort。
24
+ ただしサーバーが既に request 受信済みの race window は残るため、ダイアログ
25
+ メッセージで「自動保存処理中の場合、その時点までの内容がファイルに残る可能性が
26
+ あります」と明示
27
+
28
+ ### Changed
29
+
30
+ - `MDVApi.saveFile(path, content, signal?)` に AbortSignal 引数追加(既存
31
+ caller は signal 省略で動作継続)
32
+ - `TabManager.switch()` を `async` 化(path で target を pin → flush await →
33
+ index 再 lookup で navigation race 回避)
34
+ - save 成功時に `MDVApi.fetchFile(path)` を chain 内で await して
35
+ `tab.{content,css,notes,notesMultiplicity,etag,isMarp}` を更新(古い fetch
36
+ が新しい fetch の後に到着して content を上書きする race を排除)
37
+
38
+ ### Fixed (codex review round 1〜14 で潰した issues)
39
+
40
+ - 保存中に typing 続いた場合の dirty フラグ誤クリア(live editor とのテキスト一致
41
+ を確認してから "Saved!" 表示)
42
+ - 連続 autosave で古い ETag の POST が新しい save の後に到着して overwrite
43
+ - BroadcastChannel 経由じゃない、HTTP 経路独自の serialize chain
44
+ - 編集中のタブを close したときに edit mode flag が残る regression
45
+ - discard-on-close で saveTimer / inFlight 両方 abort + lastAutosaveError も clear
46
+ - open() で fetch 中の typing をブロック(textarea.readOnly)+ error 時に restore
47
+ - debounce-fired save が silent fail したまま flushAutosave が成功扱いする問題
48
+ (`lastAutosaveError` を保持し、navigation 時に再 throw)
49
+
50
+ ## [0.5.16] - 2026-05-09
51
+
52
+ ### Added — Inline Speaker Notes (PowerPoint-style)
53
+
54
+ メインプレビューに **PowerPoint 風の上下分割レイアウト** を追加。
55
+
56
+ - 上 = スライドステージ、下 = スピーカーノート編集領域、間に**ドラッグ可能な
57
+ 仕切り**。ノート領域を広げるとスライドが連動して縮む(CSS Grid: `1fr` /
58
+ ハンドル / `--marp-notes-row`)。
59
+ - 仕切りは:
60
+ - ドラッグでリサイズ → `localStorage` (`mdv-notes-row-px`) に永続化
61
+ - ダブルクリックでデフォルト 240px にリセット(短いビューポートでは clamp)
62
+ - ビューポートに対して `SLIDE_ROW_MIN_PX` を超えないよう attach 時 / drag 中に clamp
63
+ - 0px (完全閉じ) も有効値として保存され、リロードしても復元
64
+ - ノート編集は `contenteditable`、**800ms debounce で自動保存**。Presenter View
65
+ と同じ `/api/marp/decks/:path/slides/:N/note` API、ETag 楽観的ロック、STALE
66
+ 時はバックアップを `localStorage` に退避。
67
+ - 多コメントスライド (`notesMultiplicity > 1`) と etag 不在のデッキは編集不可化、
68
+ banner で警告。
69
+ - スライドナビ (← / → / Space / N / F / P) はノート編集中に **無効化** (keydown
70
+ stopPropagation)。
71
+ - スライド切替 → アクティブな panel のみ表示 (JS 駆動の `.active` クラス)。
72
+
73
+ ### Changed — saveQueue contract
74
+
75
+ - `enqueue()` が **`Promise<{ok, etag, reason, code}>`** を返すように変更
76
+ (既存 caller は戻り値を無視して動作継続)。
77
+ - `enqueue()` / `saveFn` に **`origin`** 引数 (`'presenter'` / `'inline'` / undef)
78
+ を追加。coalesce / rebase / `lastSavedEtag` を **per-origin** で管理し、
79
+ Presenter ↔ Inline の同時編集で互いの ETag を踏まないようにした。
80
+ - COALESCED / DROPPED の場合、superseded な enqueue() は対応する sentinel で
81
+ resolve する (caller が `await` で永遠に止まらない)。
82
+
83
+ ### Changed — Marp viewer
84
+
85
+ - `position: fixed` の `.marp-nav` を半透明 backdrop で右下に floating(広い
86
+ notes panel と被ってもスライド/ノートが透けて見える)。
87
+ - `body.marp-fullscreen` 時はノート領域・ハンドルを 0 行にして全画面プレゼン。
88
+ - 印刷 (`@media print`): split・ハンドル・ノート領域を hide、`.marpit` を
89
+ `display: block` に戻して 1 ページ 1 スライドに復帰(multi-slide PDF が 1 枚に
90
+ collapse する regression を fix)。
91
+
92
+ ### Fixed (codex review round 1〜10 で潰した issues)
93
+
94
+ - file_update が編集中に来た場合の deferred render(focus blur 後に再描画)
95
+ - tab 切替中の status 誤配信 / 誤った deck の STALE backup 上書き
96
+ - drag 中に detach されたとき body cursor / userSelect の残留
97
+ - BroadcastChannel 不在環境での `queue 未初期化` regression(saveQueue を channel
98
+ から独立させた)
99
+ - Presenter editing 中に inline 由来の `note-saved` で status / backup が汚染
100
+ - 古い save が完了した時点で `保存済み` と表示する誤報(live editor とのテキスト
101
+ 一致 + pending timer 不在を確認)
102
+
103
+ ### Tests
104
+
105
+ - 251 → **257 件 (+6)**:
106
+ - saveQueue の Promise 返却 / COALESCED / DROPPED / origin forwarding /
107
+ per-origin coalesce 5 件
108
+ - 既存 saveQueue regression の vm sandbox 互換 fix 1 件
109
+
8
110
  ## [0.5.15] - 2026-05-09
9
111
 
10
112
  ### Refactored
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdv-live",
3
- "version": "0.5.15",
3
+ "version": "0.5.17",
4
4
  "description": "Markdown Viewer - File tree + Live preview + Marp support + Hot reload",
5
5
  "main": "src/server.js",
6
6
  "bin": {