mdv-live 0.5.13 → 0.5.14

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,38 @@ 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.14] - 2026-05-09
9
+
10
+ ### Changed — Style PDF dispatch をリファイン
11
+
12
+ `PdfStyleManager` の dispatch 判定を **「PDF options JSON の有無」** に変更
13
+ (これまでは「CSS or JSON のいずれか」で server PDF 経路に切り替わっていた)。
14
+
15
+ | CSS | PDF options | PDF ボタン押下で |
16
+ |---|---|---|
17
+ | 空 | 空 | 印刷ダイアログ |
18
+ | 入れる | 空 | **印刷ダイアログ** (preview CSS が styled DOM で print engine に渡る) |
19
+ | 入れる/空 | 入れる | サーバー md-to-pdf で styled PDF 自動 DL |
20
+
21
+ JSON は margin/format/printBackground 等の細かい制御用。CSS だけ当てて
22
+ PDF にしたい普通のケースは印刷ダイアログで十分なので、md-to-pdf 経路に
23
+ 無闇に流さない。`shouldUseServerPdf()` メソッドに rename。
24
+
25
+ ### UX improvements
26
+
27
+ - **Style パネルの placeholder/tooltip** を rootDir 相対パス前提のヒント
28
+ に変更 (`report.css (rootDir からの相対パス)` 等)。Claude Code 等で
29
+ ファイル生成して入力する人が迷わないように
30
+ - **失敗時のステータスメッセージ詳細化**: 旧「Style failed」→ 新
31
+ 「Style failed: CSS not found: <path>」のように原因を出す。表示時間
32
+ も 2.5s → 4.5s に延長 (読み切る時間)
33
+ - **PDF export 失敗時** もサーバーから返されたエラーメッセージを
34
+ ステータスバーに表示
35
+
36
+ ### Docs
37
+
38
+ - README の `Web UI` 節を全面改訂: dispatch テーブル + Claude Code 連携手順
39
+
8
40
  ## [0.5.13] - 2026-05-09
9
41
 
10
42
  ### Restored
package/README.md CHANGED
@@ -107,12 +107,34 @@ mdv convert \
107
107
 
108
108
  ### Web UI
109
109
 
110
- ビューア上部の `Style` から以下を指定できます。
110
+ ビューア上部の `Style` ボタンを押すとパネルが開き、以下を指定できます。
111
111
 
112
- - CSS ファイルパス
113
- - PDF options JSON ファイルパス
112
+ - **CSS** — サーバー起動時の `rootDir` からの相対パス (例: `report.css`、`subdir/style.css`)
113
+ - **PDF options** `rootDir` からの相対パス (例: `pdf-options.json`)。省略可
114
114
 
115
- CSS は Markdown プレビューにも反映されます。指定を解除する場合は `Clear` を押してください。
115
+ `Apply` を押すと CSS は Markdown プレビューにも反映されます。`Clear` で解除。
116
+
117
+ #### PDF ボタン押下時の挙動 (Markdown ファイル)
118
+
119
+ | CSS | PDF options | PDF ボタン押下で |
120
+ |---|---|---|
121
+ | 空 | 空 | OS の **印刷ダイアログ** (`window.print()`) |
122
+ | 入れる | 空 | OS の印刷ダイアログ。preview の CSS が styled DOM として print engine に渡る |
123
+ | 入れる/空 | **入れる** | サーバー側 `md-to-pdf` で **styled PDF を自動 DL** (`@page` で margin/format を JSON 制御したいときの本格モード) |
124
+
125
+ `PDF options` を入れない限り印刷ダイアログ経由になるので、ふだんは CSS だけ指定すれば OK。
126
+
127
+ #### Claude Code との連携
128
+
129
+ CSS を Claude Code に生成させるとき、**サーバーの `rootDir` 配下** に保存して相対パスを Style パネルに入力してください。例:
130
+
131
+ ```
132
+ $ mdv ~/notes # rootDir = ~/notes
133
+ # Claude Code で ~/notes/report.css を生成
134
+ # Style パネル CSS 欄に "report.css" を入力 → Apply
135
+ ```
136
+
137
+ ファイルが見つからない場合 `Style failed: CSS not found: <path>` がステータスバーに出ます。
116
138
 
117
139
  ### ポート自動増分
118
140
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdv-live",
3
- "version": "0.5.13",
3
+ "version": "0.5.14",
4
4
  "description": "Markdown Viewer - File tree + Live preview + Marp support + Hot reload",
5
5
  "main": "src/server.js",
6
6
  "bin": {
package/src/static/app.js CHANGED
@@ -273,9 +273,12 @@
273
273
  this.loadPreviewCss();
274
274
  },
275
275
 
276
- // Style 設定があるか (PDF dispatch server vs print dialog で切り替えるため)
277
- hasStyle() {
278
- return !!(normalizeUserPath(state.pdfStylePath) || normalizeUserPath(state.pdfOptionsPath));
276
+ // PDF dispatch 切替: PDF options JSON が指定されている時だけサーバー
277
+ // md-to-pdf を使う。CSS のみ (or 何もなし) の場合は印刷ダイアログ経由
278
+ // OS のページ設定を活かしつつ、preview に当たっている CSS が
279
+ // そのまま print engine に渡って styled PDF が出る。
280
+ shouldUseServerPdf() {
281
+ return !!normalizeUserPath(state.pdfOptionsPath);
279
282
  },
280
283
 
281
284
  getExportOptions() {
@@ -317,7 +320,12 @@
317
320
 
318
321
  try {
319
322
  const response = await fetch(`/raw/${state.pdfStylePath}`);
320
- if (!response.ok) throw new Error('CSS file not found');
323
+ if (!response.ok) {
324
+ if (response.status === 404) {
325
+ throw new Error(`CSS not found: ${state.pdfStylePath}`);
326
+ }
327
+ throw new Error(`CSS load error (HTTP ${response.status}): ${state.pdfStylePath}`);
328
+ }
321
329
  const cssText = await response.text();
322
330
  const style = document.createElement('style');
323
331
  style.id = this.scopedCssId;
@@ -327,8 +335,10 @@
327
335
  setTimeout(() => { elements.statusText.textContent = 'Connected'; }, 1600);
328
336
  } catch (error) {
329
337
  console.error('PDF style preview error:', error);
330
- elements.statusText.textContent = 'PDF style failed';
331
- setTimeout(() => { elements.statusText.textContent = 'Connected'; }, 2500);
338
+ // エラー詳細を status に出す (Claude Code 連携時の自己解決を助ける)
339
+ const detail = (error.message || 'unknown error').slice(0, 100);
340
+ elements.statusText.textContent = `Style failed: ${detail}`;
341
+ setTimeout(() => { elements.statusText.textContent = 'Connected'; }, 4500);
332
342
  }
333
343
  },
334
344
 
@@ -1714,10 +1724,10 @@
1714
1724
  await this.exportPdf(tab.path);
1715
1725
  } else if (this.isHtmlPreview()) {
1716
1726
  this.printHtmlPreview(tab.name);
1717
- } else if (tab.fileType === 'markdown' && PdfStyleManager.hasStyle()) {
1718
- // Style パネルで CSS / PDF options が設定されている場合のみ
1719
- // サーバー側 md-to-pdf styled PDF を生成 (Watanabe 設計)。
1720
- // 設定がなければデフォルトの印刷ダイアログ経路に落とす。
1727
+ } else if (tab.fileType === 'markdown' && PdfStyleManager.shouldUseServerPdf()) {
1728
+ // PDF options JSON が指定されている時のみサーバー md-to-pdf。
1729
+ // CSS だけ / 何もなしの場合は printDialog OS にページ制御
1730
+ // を委ね、preview の CSS injection が styled PDF を作る。
1721
1731
  await this.exportPdf(tab.path);
1722
1732
  } else {
1723
1733
  this.browserPrint(tab.name);
@@ -1772,10 +1782,13 @@
1772
1782
  }, 2000);
1773
1783
  } catch (error) {
1774
1784
  console.error('PDF export error:', error);
1775
- statusText.textContent = 'PDF export failed';
1785
+ // サーバーが返したエラーメッセージを status に表示
1786
+ // (Claude Code 連携などで「何が悪いか分からない」を防ぐ)
1787
+ const detail = (error.message || 'unknown error').slice(0, 100);
1788
+ statusText.textContent = `PDF export failed: ${detail}`;
1776
1789
  setTimeout(() => {
1777
1790
  statusText.textContent = originalStatus;
1778
- }, 3000);
1791
+ }, 4500);
1779
1792
  }
1780
1793
  },
1781
1794
 
@@ -120,11 +120,11 @@
120
120
  <div class="pdf-style-panel hidden" id="pdfStylePanel">
121
121
  <label>
122
122
  <span>CSS</span>
123
- <input type="text" id="pdfStylePath" placeholder="src/styles/report.example.css">
123
+ <input type="text" id="pdfStylePath" placeholder="report.css (rootDir からの相対パス)" title="rootDir 配下の .css ファイルパス。例: report.css または subdir/style.css">
124
124
  </label>
125
125
  <label>
126
126
  <span>PDF options</span>
127
- <input type="text" id="pdfOptionsPath" placeholder="src/styles/report.pdf-options.example.json">
127
+ <input type="text" id="pdfOptionsPath" placeholder="pdf-options.json (省略可。空なら印刷ダイアログ)" title="rootDir 配下の .json ファイルパス。指定すると md-to-pdf が margin/format を適用してサーバー PDF 自動 DL。空なら印刷ダイアログ経路。">
128
128
  </label>
129
129
  <button class="toolbar-btn" id="pdfStyleApply">Apply</button>
130
130
  <button class="toolbar-btn" id="pdfStyleClear">Clear</button>
@@ -808,7 +808,7 @@ body {
808
808
  padding: 0 !important;
809
809
  }
810
810
 
811
- .sidebar, .resize-handle, .toolbar, .tab-bar { display: none !important; }
811
+ .sidebar, .resize-handle, .toolbar, .tab-bar, .pdf-style-panel { display: none !important; }
812
812
 
813
813
  body {
814
814
  height: auto !important;