memd-cli 2.0.0 → 2.0.1

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/svgplan.md DELETED
@@ -1,805 +0,0 @@
1
- memd-cli v2.0.0 HTML (SVG) 出力機能 + テーマ統合 実装計画
2
- ==========================================================
3
-
4
- ## 概要
5
-
6
- Markdown + Mermaid を HTML ファイルとして出力する機能を追加する。
7
- Mermaid ダイアグラムは beautiful-mermaid の `renderMermaidSVG()` でインライン SVG 化し、
8
- スタンドアロンな HTML を stdout に出力する。保存は `> file.html` リダイレクトに委ねる。
9
- 併せて `--theme` を beautiful-mermaid テーマに一本化し、v2.0.0 としてリリースする。
10
-
11
- ## 検証済み事項
12
-
13
- - `renderMermaidSVG(text, options?: RenderOptions)` は同期関数。Puppeteer/DOM 不要 (ELK.js ベース)
14
- - `RenderOptions` は `DiagramColors` のフィールド (`bg`, `fg`, `line`, `accent`, `muted`, `surface`, `border`) + レイアウト設定 (`font`, `padding`, `nodeSpacing`, `layerSpacing`, `componentSpacing`, `transparent`, `interactive`) を含む
15
- - `THEMES` の値は `DiagramColors` 型だが、`RenderOptions` と互換 (`buildColors()` が同じフィールドを destructure するため)
16
- - 対応図種: flowchart/state, sequence, class, ER, xychart (state は flowchart パイプラインで処理される)
17
- - `marked.parse()` は生の SVG タグをエスケープせずそのまま通す (後述「marked の HTML パススルー」参照)
18
- - 複数 Mermaid ブロックの同時変換も問題なし (PoC で検証済み: flowchart x3 + sequence + class + state の6ブロックで marker ID ユニーク化を確認)
19
- - 外部フォント (`@import url(...)`) は除去可能。`system-ui` フォールバックで問題なし
20
- - `color-mix()` を CSS 内で使用 (Chrome 111+, Firefox 113+, Safari 16.2+)
21
- - `marked` ライブラリは `new Marked()` で独立インスタンスを作成可能 (`marked/lib/marked.d.ts:629`)
22
- - `markedTerminal` 適用済みのグローバル `marked` とは別に、HTML 用の素の `Marked` インスタンスを使う
23
- - `renderMermaidASCII()` は `AsciiRenderOptions` を受け取り、`theme?: Partial<AsciiTheme>` と `colorMode?: ColorMode | 'auto'` をサポートする
24
- - `ColorMode`: `'none'` | `'ansi16'` | `'ansi256'` | `'truecolor'` | `'html'`
25
- - `colorMode` 省略時は `'auto'` (ターミナル capabilities を自動検出)
26
- - `diagramColorsToAsciiTheme()` は beautiful-mermaid 内部に存在するが **メインエクスポートに含まれない** (`src/ascii/ansi.ts:53` で定義・export されているが `src/index.ts` で re-export されていない)。サブパスインポートも `package.json` の `exports` フィールドでブロックされる。memd 側で同等の変換関数を実装する
27
- - `chalk.level = 0` を設定すると、`markedTerminal` を含む全ての chalk ベースの出力が ANSI コードなしのプレーンテキストになる。`marked-terminal/index.js:591` で `chalk.level === 0` 時に `cli-highlight` をスキップする処理が確認済み
28
- - 追加依存: なし (beautiful-mermaid, marked は既存依存)
29
-
30
- ## アーキテクチャ
31
-
32
- ### 2つの独立パイプライン
33
-
34
- HTML パスとターミナルパスは明確に分離し、共有するのはテーマ解決と入力読み込みのみ。
35
-
36
- ```mermaid
37
- flowchart TD
38
- A[Markdown input] --> B[Resolve theme<br>from MERMAID_THEMES]
39
- B --> C{--html flag?}
40
- C -->|Yes| D[convertMermaidToSVG<br>renderMermaidSVG + ID prefix]
41
- C -->|No| E[convertMermaidToAscii<br>renderMermaidASCII + AsciiTheme]
42
- D --> F[new Marked.parse<br>plain HTML]
43
- F --> G[Wrap in HTML template<br>with theme CSS]
44
- G --> J[stdout]
45
- E --> K[marked + markedTerminal<br>ANSI output]
46
- K --> L{Pager needed?}
47
- L -->|Yes| M[Pager]
48
- L -->|No| J
49
- ```
50
-
51
- ### 共有レイヤー
52
-
53
- | レイヤー | 責務 | HTML パス | ターミナルパス |
54
- |---------|------|----------|--------------|
55
- | テーマ解決 | `MERMAID_THEMES[name]` -> `DiagramColors` | 共通 | 共通 |
56
- | テーマ色補完 | optional フィールドの fallback 算出 | `resolveThemeColors()` | `diagramColorsToAsciiTheme()` |
57
- | Mermaid 変換 | コードブロック -> 図 | `convertMermaidToSVG()` | `convertMermaidToAscii()` |
58
- | Markdown 変換 | Markdown -> 出力形式 | `new Marked().parse()` | `marked.parse()` (+ markedTerminal) |
59
- | 出力 | 結果の書き出し | stdout | pager or stdout |
60
-
61
- ### 依存関係
62
-
63
- - HTML パスが触れるもの: `renderMermaidSVG`, `MERMAID_THEMES`, `Marked`
64
- - ターミナルパスが触れるもの: `renderMermaidASCII`, `MERMAID_THEMES`, `marked`, `markedTerminal`, `chalk`, pager
65
- - 両パスが触れるもの: `MERMAID_THEMES` (テーマ解決), 入力読み込み (`readMarkdownFile`, `readStdin`)
66
-
67
- ## CLI オプション
68
-
69
- ### 追加するオプション
70
-
71
- ```
72
- --html Markdown+Mermaid を HTML として stdout に出力
73
- ```
74
-
75
- ファイル保存はシェルリダイレクト (`memd foo.md --html > out.html`) に委ねる。
76
- `-o` / `--output` オプションは設けない。UNIX 慣例 (stdout + リダイレクト) に従い、
77
- オプションの増加と関連するバリデーション・エラー処理の複雑さを回避する。
78
-
79
- ### 動作仕様
80
-
81
- | 入力 | 出力先 |
82
- |------|--------|
83
- | `memd foo.md --html` | stdout |
84
- | `memd a.md b.md --html` | stdout (結合) |
85
- | `cat foo.md \| memd --html` | stdout |
86
- | `memd foo.md --html > out.html` | `out.html` (リダイレクト) |
87
-
88
- 複数ファイル入力時は現行のターミナルモードと同様に結合して単一出力とする。
89
-
90
- ### 複数ファイルの結合タイミング
91
-
92
- **HTML パス**: Markdown を先に結合してから `convertMermaidToSVG()` を1回実行する。
93
- これにより `svgIndex` がファイル間で連続し、marker ID の重複を防止する。
94
-
95
- ```javascript
96
- // HTML パス: Markdown を結合 → SVG 変換 (svgIndex が連続)
97
- const combinedMarkdown = markdownParts.join('\n\n');
98
- const html = renderToHTML(combinedMarkdown, diagramColors);
99
- ```
100
-
101
- **ターミナルパス**: 既存と同様に、各ファイルを個別に `convertMermaidToAscii` + `marked.parse` した結果を結合する。
102
- ターミナルパスでは ASCII 描画に ID の概念がないため、個別変換で問題ない。
103
-
104
- ```javascript
105
- // ターミナルパス: 個別変換 → 結合 (renderToString は廃止、ロジックをインライン化)
106
- for (const markdown of markdownParts) {
107
- const processed = convertMermaidToAscii(markdown, { useAscii: options.ascii, colorMode, theme: asciiTheme });
108
- parts.push(marked.parse(processed));
109
- }
110
- const fullText = parts.join('\n\n') + '\n';
111
- ```
112
-
113
- ### --html 使用時の動作
114
-
115
- `action` 内でテーマ解決 (共通処理) の直後に `--html` で大きく分岐する。
116
- HTML パスではターミナル系の処理 (`markedTerminal`, `renderMermaidASCII`, pager) に一切触れない。
117
-
118
- ```javascript
119
- action(files, options) {
120
- // 1. テーマ解決 (共通)
121
- const diagramColors = resolveDiagramTheme(options.theme);
122
-
123
- // 2. 入力読み込み (共通): files or stdin → markdownParts[]
124
- const markdownParts = [];
125
- if (files.length === 0) {
126
- // stdin: TTY の場合はヘルプを表示して終了 (既存動作を維持)
127
- if (process.stdin.isTTY) {
128
- program.help();
129
- }
130
- const stdinData = await readStdin();
131
- if (stdinData.trim()) {
132
- markdownParts.push(stdinData);
133
- } else {
134
- program.help();
135
- }
136
- } else {
137
- let exitCode = 0;
138
- for (const filePath of files) {
139
- try {
140
- markdownParts.push(readMarkdownFile(filePath));
141
- } catch (error) {
142
- const errorMessage = error instanceof Error ? error.message : String(error);
143
- console.error(`Error reading file ${filePath}: ${errorMessage}`);
144
- exitCode = 1;
145
- }
146
- }
147
- if (exitCode !== 0) {
148
- process.exit(exitCode);
149
- }
150
- }
151
-
152
- if (options.html) {
153
- // 3a. HTML パス
154
- // - Markdown を結合してから convertMermaidToSVG (svgIndex 連続)
155
- // - new Marked().parse(processed)
156
- // - renderToHTML() で HTML テンプレート生成
157
- // - 常に process.stdout.write (保存はリダイレクトに委ねる)
158
- // - markedTerminal, chalk, pager に一切触れない
159
- // - ターミナル系オプション (--no-pager, --no-mouse, --width, --ascii, --no-color) は黙って無視
160
- const combined = markdownParts.join('\n\n');
161
- const html = renderToHTML(combined, diagramColors);
162
- process.stdout.write(html);
163
- } else {
164
- // 3b. ターミナルパス (既存ロジック、renderToString は廃止しインライン化)
165
- // - --no-color 時は chalk.level = 0 で ANSI 出力を根元から無効化
166
- // - resolveTerminalTheme(themeName) でターミナル用テーマを取得
167
- // - marked.use(markedTerminal(...))
168
- // - marked.use({ renderer: { link() } }) (OSC 8 回避)
169
- // - !shouldHighlight 時の code renderer override
170
- // - diagramColorsToAsciiTheme(diagramColors) で AsciiTheme に変換
171
- // - 各ファイルを個別に convertMermaidToAscii + marked.parse
172
- // - pager 判定 → 出力
173
- }
174
- }
175
- ```
176
-
177
- - **ターミナル系オプションは黙って無視**: `--no-pager`, `--no-mouse`, `--width`, `--no-color` はエラーにせず無視する。HTML は常にテーマの色を含むフルカラー出力とする
178
- - **`--ascii` は HTML パスでは無効**: `--ascii` は ASCII ダイアグラムの Unicode/ASCII 切り替えオプションであり、HTML パスでは SVG を使用するため効果がない。エラーにせず黙って無視する
179
- - **pager は到達しない**: HTML パスには pager ロジックが存在しない
180
-
181
- ## テーマ統合
182
-
183
- ### 現状の問題
184
-
185
- memd-cli 独自テーマ (6種: default, monokai, dracula, github-dark, solarized, nord) と
186
- beautiful-mermaid テーマ (15種) が分離しており、ダイアグラムに色が反映されていない。
187
- (`main.js:187` で三項演算子の両辺が `'none'` になっており、実質ハードコード状態)
188
-
189
- ### 方針: beautiful-mermaid テーマに一本化 (Breaking Change)
190
-
191
- `--theme` は beautiful-mermaid の `THEMES` キー名のみを受け付ける。
192
- memd 独自のエイリアス (`default`, `monokai`, `solarized`) は**廃止**する。
193
-
194
- - ダイアグラム (SVG/ASCII): `MERMAID_THEMES[themeName]` の `DiagramColors` をそのまま使用
195
- - ターミナル Markdown 着色: beautiful-mermaid テーマ名から `TERMINAL_THEMES` を参照。マッピングがないテーマはハイライトなし (`{ highlight: null, markdown: {} }`)
196
- - HTML 出力: `DiagramColors` の色をページ全体の CSS に適用
197
-
198
- ### テーマ名の変更 (Breaking Change)
199
-
200
- | 旧 --theme 値 | 新 --theme 値 | 備考 |
201
- |---------------|-------------|------|
202
- | `default` | `zinc-light` | 新デフォルト |
203
- | `monokai` | (廃止) | one-dark に独自パレットを新設 |
204
- | `dracula` | `dracula` | 変更なし |
205
- | `github-dark` | `github-dark` | 変更なし |
206
- | `solarized` | `solarized-dark` | 名前変更 |
207
- | `nord` | `nord` | 変更なし |
208
-
209
- 新たに使用可能になるテーマ (10種):
210
- `zinc-dark`, `tokyo-night`, `tokyo-night-storm`, `tokyo-night-light`,
211
- `catppuccin-mocha`, `catppuccin-latte`, `nord-light`,
212
- `github-light`, `solarized-light`, `one-dark`
213
-
214
- ### ターミナルシンタックスハイライトの対応状況
215
-
216
- 15テーマのうち、カスタムシンタックスハイライト (`buildTheme()`) を持つのは5テーマのみ。
217
- 残り10テーマはデフォルト (cli-highlight のデフォルトカラー) にフォールバックする。
218
-
219
- | beautiful-mermaid テーマ | ターミナルハイライト | 備考 |
220
- |------------------------|-------------------|------|
221
- | `one-dark` | `buildTheme(oneDarkColors)` | One Dark (Atom) 準拠パレットを新設 |
222
- | `dracula` | `buildTheme(draculaColors)` | 既存パレット維持 |
223
- | `github-dark` | `buildTheme(githubDarkColors)` | 既存パレット維持 |
224
- | `solarized-dark` | `buildTheme(solarizedColors)` | 既存パレット維持 |
225
- | `nord` | `buildTheme(nordColors)` | 既存パレット維持 |
226
- | その他 10 テーマ | `{ highlight: null, markdown: {} }` | ハイライトなし |
227
-
228
- #### one-dark カラーパレット (新規)
229
-
230
- 旧 monokai パレットを破棄し、Atom One Dark Syntax Theme 準拠のカラーパレットを新設する。
231
- SVG ダイアグラム (accent: `#c678dd`) とターミナルハイライトの色の方向性を統一する。
232
-
233
- ```javascript
234
- 'one-dark': buildTheme({
235
- keyword: '#e06c75', func: '#61afef', string: '#98c379',
236
- type: '#e5c07b', number: '#d19a66', literal: '#c678dd',
237
- param: '#d19a66', comment: '#5c6370', fg: '#abb2bf',
238
- heading1: '#e06c75', heading2:'#61afef',
239
- added: '#98c379', deleted: '#e06c75',
240
- }),
241
- ```
242
-
243
- 出典: Atom One Dark Syntax Theme (https://github.com/atom/one-dark-syntax)
244
-
245
- 将来的にターミナルハイライトの対応テーマを増やすことは可能だが、本リリースのスコープ外。
246
-
247
- ### 互換性への影響まとめ
248
-
249
- 1. **テーマ名の変更**: `default` -> `zinc-light`, `monokai` -> (廃止、`one-dark` に置換), `solarized` -> `solarized-dark`。旧名は受け付けない (エラー)
250
- 2. **ASCII ダイアグラムの着色**: 現在は常に無着色 (`colorMode: 'none'`)。本変更後は `--theme` に応じた色が付く。`--no-color` 指定時は従来通り `colorMode: 'none'`
251
- 3. **デフォルトテーマの変更**: `default` (ハイライトなし) -> `zinc-light` (ハイライトなし)。ターミナル表示上の実質的な差異はない (どちらも cli-highlight デフォルト)
252
- 4. **バージョン**: `1.5.1` -> `2.0.0` (semver major bump)
253
- 5. CHANGELOG にて breaking change として記載する
254
-
255
- ### --no-color の実装方針
256
-
257
- 現在の `--no-color` は `marked.parse()` 後に ANSI コードを正規表現で除去する後処理方式
258
- (`main.js:203-207`) だが、これを **chalk.level による根元からの無効化**に改善する。
259
-
260
- ```javascript
261
- // Before: 後処理で ANSI を除去 (非効率・漏れのリスク)
262
- result = result.replace(/\x1b\[[0-9;]*m/g, '');
263
-
264
- // After: chalk.level = 0 で全ての ANSI 出力を根元から無効化
265
- if (!useColor) {
266
- chalk.level = 0; // markedTerminal, cli-highlight, buildTheme 内の chalk.hex() 全てに効く
267
- }
268
- ```
269
-
270
- `chalk.level = 0` を設定すると:
271
- - `markedTerminal` が使用する chalk スタイリングが全て無効化される
272
- - `cli-highlight` のシンタックスハイライトが無効化される (`marked-terminal/index.js:591` で `chalk.level === 0` 時にスキップ)
273
- - `buildTheme()` 内の `chalk.hex()` も ANSI コードを出力しなくなる
274
- - `renderMermaidASCII()` の `colorMode` は別途 `'none'` に設定する (chalk とは独立)
275
-
276
- これにより既存の ANSI ストリッピング正規表現 (`main.js:203-207`) は不要になり、削除する。
277
- `--no-color` 時はユーザーの意図通り、出力全体が ANSI コードなしのプレーンテキストとなる。
278
-
279
- **注**: `chalk.level` はグローバル状態だが、ターミナルパスの分岐内でのみ設定するため、
280
- HTML パスに影響しない。HTML パスでは chalk を一切使用しない。
281
-
282
- ### DiagramColors -> AsciiTheme 変換 (memd 側で実装)
283
-
284
- beautiful-mermaid の `diagramColorsToAsciiTheme()` はメインエクスポートに含まれない
285
- (`src/ascii/ansi.ts:53` で定義されているが `src/index.ts` で re-export されていない。
286
- `package.json` の `exports` フィールドによりサブパスインポートもブロックされる)。
287
-
288
- memd 側で同等の変換関数を実装する。beautiful-mermaid 内部と同じ MIX 比率を使用:
289
-
290
- ```javascript
291
- // Color mixing: blend hex1 into hex2 at pct%
292
- // Equivalent to CSS color-mix(in srgb, hex1 pct%, hex2)
293
- function mixHex(hex1, hex2, pct) {
294
- const p = pct / 100;
295
- const parse = (h, o) => parseInt(h.slice(o, o + 2), 16);
296
- const mix = (c1, c2) => Math.round(c1 * p + c2 * (1 - p));
297
- const toHex = x => x.toString(16).padStart(2, '0');
298
- const r = mix(parse(hex1, 1), parse(hex2, 1));
299
- const g = mix(parse(hex1, 3), parse(hex2, 3));
300
- const b = mix(parse(hex1, 5), parse(hex2, 5));
301
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
302
- }
303
-
304
- // Match beautiful-mermaid's internal MIX ratios (theme.ts:64-87)
305
- const MIX = { line: 50, arrow: 85, nodeStroke: 20 };
306
-
307
- function diagramColorsToAsciiTheme(colors) {
308
- const line = colors.line ?? mixHex(colors.fg, colors.bg, MIX.line);
309
- const border = colors.border ?? mixHex(colors.fg, colors.bg, MIX.nodeStroke);
310
- return {
311
- fg: colors.fg,
312
- bg: colors.bg,
313
- line,
314
- border,
315
- arrow: colors.accent ?? mixHex(colors.fg, colors.bg, MIX.arrow),
316
- accent: colors.accent,
317
- corner: line,
318
- junction: border,
319
- };
320
- }
321
- ```
322
-
323
- **DiagramColors -> AsciiTheme フィールドマッピング:**
324
-
325
- | DiagramColors | AsciiTheme | 変換ロジック |
326
- |--------------|-----------|-------------|
327
- | `fg` (required) | `fg` | そのまま |
328
- | `bg` (required) | `bg` | そのまま |
329
- | `line` (optional) | `line` | `line ?? mixHex(fg, bg, 50)` |
330
- | `accent` (optional) | `arrow` | `accent ?? mixHex(fg, bg, 85)` |
331
- | `accent` (optional) | `accent` | そのまま |
332
- | `border` (optional) | `border` | `border ?? mixHex(fg, bg, 20)` |
333
- | - | `corner` | = line (上記で算出済みの値) |
334
- | - | `junction` | = border (上記で算出済みの値) |
335
-
336
- **注**: `mixHex()` は CSS `color-mix(in srgb, ...)` と同等の sRGB 線形補間。
337
- beautiful-mermaid 内部の `mixColors()` も同じ算術 (`theme.ts:77-87`) を使用する。
338
- zinc-dark (`bg: #18181B`, `fg: #FAFAFA`) でのフォールバック算出結果:
339
- line=#89898b, accent=#d8d8d9, border=#454548 -- ダークテーマとして妥当な値を確認済み。
340
-
341
- ### HTML テンプレート用テーマ色補完
342
-
343
- HTML テンプレートの CSS では `line`, `accent`, `muted`, `border` を使用する。
344
- `DiagramColors` の optional フィールドが未定義の場合のフォールバック:
345
-
346
- ```javascript
347
- // MIX ratios from beautiful-mermaid theme.ts:64-87
348
- // line: 50 (MIX.line), accent: 85 (MIX.arrow), muted: 60 (MIX.textSec), border: 20 (MIX.nodeStroke)
349
- function resolveThemeColors(colors) {
350
- return {
351
- bg: colors.bg,
352
- fg: colors.fg,
353
- line: colors.line ?? mixHex(colors.fg, colors.bg, 50), // MIX.line
354
- accent: colors.accent ?? mixHex(colors.fg, colors.bg, 85), // MIX.arrow
355
- muted: colors.muted ?? mixHex(colors.fg, colors.bg, 60), // MIX.textSec
356
- border: colors.border ?? mixHex(colors.fg, colors.bg, 20), // MIX.nodeStroke
357
- };
358
- }
359
- ```
360
-
361
- `diagramColorsToAsciiTheme()` と `resolveThemeColors()` は `mixHex()` を共有するが、
362
- 目的・出力型が異なるため別関数として実装する。
363
-
364
- ### テーマバリデーション
365
-
366
- ```javascript
367
- function resolveDiagramTheme(themeName) {
368
- if (themeName in MERMAID_THEMES) return MERMAID_THEMES[themeName];
369
- const names = Object.keys(MERMAID_THEMES).join(', ');
370
- console.error(`Unknown theme: ${themeName}\nAvailable themes: ${names}`);
371
- process.exit(1);
372
- }
373
- ```
374
-
375
- エイリアスが廃止されたため、単純な1段階ルックアップになる。
376
-
377
- ### --theme ヘルプテキスト
378
-
379
- ```
380
- --theme <name> color theme (default: "zinc-light")
381
- zinc-light, zinc-dark, tokyo-night, tokyo-night-storm,
382
- tokyo-night-light, catppuccin-mocha, catppuccin-latte,
383
- nord, nord-light, dracula, github-light, github-dark,
384
- solarized-light, solarized-dark, one-dark
385
- ```
386
-
387
- commander の `.option()` で改行入りの description を渡すことで実現する。
388
-
389
- ### 各テーマの DiagramColors フィールド一覧 (実測値)
390
-
391
- | テーマ | bg | fg | line | accent | muted | border | surface |
392
- |-------|----|----|------|--------|-------|--------|---------|
393
- | zinc-light | #FFFFFF | #27272A | - | - | - | - | - |
394
- | zinc-dark | #18181B | #FAFAFA | - | - | - | - | - |
395
- | tokyo-night | #1a1b26 | #a9b1d6 | #3d59a1 | #7aa2f7 | #565f89 | - | - |
396
- | tokyo-night-storm | #24283b | #a9b1d6 | #3d59a1 | #7aa2f7 | #565f89 | - | - |
397
- | tokyo-night-light | #d5d6db | #343b58 | #34548a | #34548a | #9699a3 | - | - |
398
- | catppuccin-mocha | #1e1e2e | #cdd6f4 | #585b70 | #cba6f7 | #6c7086 | - | - |
399
- | catppuccin-latte | #eff1f5 | #4c4f69 | #9ca0b0 | #8839ef | #9ca0b0 | - | - |
400
- | nord | #2e3440 | #d8dee9 | #4c566a | #88c0d0 | #616e88 | - | - |
401
- | nord-light | #eceff4 | #2e3440 | #aab1c0 | #5e81ac | #7b88a1 | - | - |
402
- | dracula | #282a36 | #f8f8f2 | #6272a4 | #bd93f9 | #6272a4 | - | - |
403
- | github-light | #ffffff | #1f2328 | #d1d9e0 | #0969da | #59636e | - | - |
404
- | github-dark | #0d1117 | #e6edf3 | #3d444d | #4493f8 | #9198a1 | - | - |
405
- | solarized-light | #fdf6e3 | #657b83 | #93a1a1 | #268bd2 | #93a1a1 | - | - |
406
- | solarized-dark | #002b36 | #839496 | #586e75 | #268bd2 | #586e75 | - | - |
407
- | one-dark | #282c34 | #abb2bf | #4b5263 | #c678dd | #5c6370 | - | - |
408
-
409
- 全15テーマで `border` と `surface` は未定義。13/15テーマが `line`, `accent`, `muted` を提供。
410
- zinc-light と zinc-dark のみ `bg`, `fg` のみ -> `mixHex()` によるフォールバック算出が必須。
411
-
412
- ## 変更対象
413
-
414
- **main.js** (機能実装) + **test/memd.test.js** (テスト追加・更新) + **README.md** (テーマ名・オプション更新) + **package.json** (バージョン 2.0.0)
415
-
416
- ### main.js 変更内容
417
-
418
- 1. **import 追加**: `renderMermaidSVG`, `THEMES as MERMAID_THEMES` を beautiful-mermaid から追加インポート。`Marked` クラスを marked から追加インポート
419
- 2. **既存 `THEMES` を `TERMINAL_THEMES` にリネーム**: `main.js:119` の memd 独自テーマオブジェクトを beautiful-mermaid テーマ名をキーとする `TERMINAL_THEMES` に変更。`default` エントリを削除し、`DEFAULT_TERMINAL_THEME` 定数に分離。旧 `monokai` エントリを破棄し、`'one-dark'` キーで Atom One Dark 準拠パレットを新設
420
- 3. **`escapeHtml()` ユーティリティ関数追加**: `&`, `<`, `>`, `"`, `'` をエスケープ (Mermaid 変換エラー表示用)
421
- 4. **`mixHex()` + `diagramColorsToAsciiTheme()` 追加**: DiagramColors -> AsciiTheme 変換。beautiful-mermaid 内部と同じ MIX 比率 (`theme.ts:64-87`) を使用
422
- 5. **`resolveThemeColors()` 追加**: DiagramColors の optional フィールドをフォールバック算出 (HTML テンプレートの CSS 用)。MIX 比率: line=50 (`MIX.line`), accent=85 (`MIX.arrow`), muted=60 (`MIX.textSec`), border=20 (`MIX.nodeStroke`)
423
- 6. **`resolveDiagramTheme()` 追加**: `MERMAID_THEMES` から DiagramColors を取得。不明テーマ名はエラー
424
- 7. **`resolveTerminalTheme()` 追加**: `TERMINAL_THEMES` からターミナル用テーマを取得。マッピングがない場合は `DEFAULT_TERMINAL_THEME` (ハイライトなし)
425
- 8. **`convertMermaidToSVG()` 関数追加**: Mermaid ブロックを SVG に変換 (`@import` 除去 + marker ID ユニーク化を含む)
426
- 9. **`renderToHTML()` 関数追加**: `new Marked()` インスタンスで Markdown -> HTML 変換 + HTML テンプレート生成
427
- 10. **commander に `--html` オプション追加**
428
- 11. **`--theme` のデフォルト値を `zinc-light` に変更**: commander の `.option()` デフォルト値とヘルプテキストを更新。action 内の `const themeName = options.theme || 'default'` も `options.theme` に簡略化 (commander のデフォルト値に委譲)
429
- 12a. **`THEME_NAMES` を `MERMAID_THEMES` ベースに再定義**: `const THEME_NAMES = Object.keys(MERMAID_THEMES)` に変更。ヘルプテキスト生成とテーマバリデーションの両方で使用
430
- 12b. **CLI `.description()` を更新**: `'Render markdown with mermaid diagrams to terminal output'` -> `'Render markdown with mermaid diagrams'`
431
- 13. **action 内を早期分岐**: テーマ解決後に `--html` で HTML パス / ターミナルパスに分岐。HTML パスでは Markdown を結合後に `convertMermaidToSVG` を1回実行 (svgIndex 連続)。ターミナルパスでは既存の全 `marked.use()` 呼び出しをすべて分岐内に移動
432
- 14. **`--no-color` の改善**: `chalk.level = 0` による根元からの ANSI 無効化。既存の ANSI ストリッピング正規表現 (`main.js:203-207`) を削除
433
- 15. **`renderToString()` を廃止**: `convertMermaidToAscii` + `marked.parse` のロジックをターミナルパス分岐内にインライン化。外部呼び出し元は action 内のみで外部 API ではないため、リスクなし
434
- 16. **`convertMermaidToAscii()` のリファクタ**: CLI options オブジェクトの直接参照をやめ、必要なパラメータを明示的に受け取る新シグネチャに変更
435
- 17. **ASCII 描画にテーマ色を適用**: `renderMermaidASCII()` 呼び出し時に `theme` (AsciiTheme) と `colorMode` を渡す。`--no-color` 時は `colorMode: 'none'`、それ以外は `colorMode` を省略 (`'auto'`)
436
-
437
- ### `convertMermaidToAscii()` のリファクタ
438
-
439
- 現在のシグネチャは CLI の `options` オブジェクトを直接受け取っている (`main.js:177`)。
440
- リファクタ後は必要なパラメータのみを明示的に受け取る:
441
-
442
- ```javascript
443
- // Before: CLI options を直接参照 (暗黙の依存)
444
- function convertMermaidToAscii(markdown, options = {}) {
445
- // options.ascii, options.color を参照
446
- mermaidOptions.colorMode = options.color === false ? 'none' : 'none'; // バグ: 常に 'none'
447
- }
448
-
449
- // After: 必要なパラメータを明示的に受け取る
450
- function convertMermaidToAscii(markdown, { useAscii = false, colorMode, theme } = {}) {
451
- const mermaidOptions = {};
452
- if (useAscii) mermaidOptions.useAscii = true;
453
- if (colorMode) mermaidOptions.colorMode = colorMode;
454
- if (theme) mermaidOptions.theme = theme;
455
- const asciiArt = renderMermaidASCII(code.trim(), mermaidOptions);
456
- // ...
457
- }
458
- ```
459
-
460
- 呼び出し側:
461
-
462
- ```javascript
463
- const asciiTheme = diagramColorsToAsciiTheme(diagramColors);
464
- const colorMode = useColor ? undefined : 'none'; // undefined = 'auto' (ターミナル自動検出)
465
- const processed = convertMermaidToAscii(markdown, {
466
- useAscii: options.ascii,
467
- colorMode,
468
- theme: asciiTheme,
469
- });
470
- ```
471
-
472
- ### import の変更
473
-
474
- ```javascript
475
- // Before
476
- import { marked } from 'marked';
477
- import { renderMermaidASCII } from 'beautiful-mermaid';
478
-
479
- // After
480
- import { marked, Marked } from 'marked';
481
- import { renderMermaidASCII, renderMermaidSVG, THEMES as MERMAID_THEMES } from 'beautiful-mermaid';
482
- ```
483
-
484
- ### TERMINAL_THEMES の定義 (旧 THEMES のリキー)
485
-
486
- ```javascript
487
- // Before: memd 独自テーマ名をキーに使用
488
- const THEMES = {
489
- default: { highlight: null, markdown: {} },
490
- monokai: buildTheme({
491
- keyword: '#F92672', func: '#A6E22E', string: '#E6DB74', ...
492
- }),
493
- dracula: buildTheme({ ... }),
494
- 'github-dark': buildTheme({ ... }),
495
- solarized: buildTheme({ ... }),
496
- nord: buildTheme({ ... }),
497
- };
498
-
499
- // After: beautiful-mermaid テーマ名をキーに使用
500
- const TERMINAL_THEMES = {
501
- 'one-dark': buildTheme({
502
- // Atom One Dark Syntax Theme 準拠 (https://github.com/atom/one-dark-syntax)
503
- keyword: '#e06c75', func: '#61afef', string: '#98c379',
504
- type: '#e5c07b', number: '#d19a66', literal: '#c678dd',
505
- param: '#d19a66', comment: '#5c6370', fg: '#abb2bf',
506
- heading1: '#e06c75', heading2:'#61afef',
507
- added: '#98c379', deleted: '#e06c75',
508
- }),
509
- 'dracula': buildTheme({ ... }), // 既存パレット維持
510
- 'github-dark': buildTheme({ ... }), // 既存パレット維持
511
- 'solarized-dark': buildTheme({ ... }),// 旧 solarized、パレット維持
512
- 'nord': buildTheme({ ... }), // 既存パレット維持
513
- };
514
-
515
- const DEFAULT_TERMINAL_THEME = { highlight: null, markdown: {} };
516
-
517
- function resolveTerminalTheme(themeName) {
518
- return TERMINAL_THEMES[themeName] ?? DEFAULT_TERMINAL_THEME;
519
- }
520
- ```
521
-
522
- ### marked インスタンスの分離 (重要)
523
-
524
- 現状 (`main.js:303-307`) ではグローバルな `marked` に `markedTerminal` を適用しており、
525
- 出力は ANSI エスケープコード付きのターミナル文字列になる。
526
- HTML モードで同じ `marked` を使うと ANSI コードが HTML に混入するため、分離が必須。
527
-
528
- 早期分岐により、HTML パスでは `marked.use(markedTerminal(...))` 自体を実行しない。
529
- これにより、グローバル `marked` を汚す問題が根本的に解消される。
530
-
531
- ```javascript
532
- // Terminal path (existing) -- 分岐内でのみ設定
533
- marked.use(markedTerminal({ ... })); // Global instance, ANSI output
534
- marked.parse(processed);
535
-
536
- // HTML path (new) -- グローバル marked に触れない
537
- const htmlMarked = new Marked(); // Separate instance, plain HTML output
538
- htmlMarked.parse(processed);
539
- ```
540
-
541
- ### marked の HTML パススルーについて
542
-
543
- marked v17.0.3 では HTML タグはデフォルトでエスケープされず、そのまま出力に含まれる。
544
- これは marked の設計方針 (README: "Marked does not sanitize the output HTML") による。
545
- `sanitize` オプション等の制御は存在しない。
546
-
547
- `new Marked().parse()` で SVG タグ入りの Markdown をパースすると、SVG はそのまま HTML に含まれる:
548
- ```javascript
549
- new Marked().parse('text <svg>...</svg> more')
550
- // -> '<p>text <svg>...</svg> more</p>'
551
- ```
552
-
553
- **リスク**: marked のメジャーバージョンアップでこの挙動が変わる可能性はゼロではない。
554
- `package.json` で marked のバージョンをメジャー固定 (`^17`) しているため、
555
- v18 への更新時にはこの点を確認すること。
556
-
557
- **注**: `new Marked().parse()` はデフォルト構成 (async extension なし) では同期的に `string` を返す。
558
- async extension を `.use()` した場合のみ `Promise<string>` を返す。本実装では素の `new Marked()` を
559
- 使うため同期呼び出しで問題ないが、将来 extension を追加する場合は `await` が必要になる点に留意。
560
- <!-- TypeScript 型定義上は戻り値が string | Promise<string> のため、@ts-nocheck 解除時はキャストが必要 -->
561
-
562
- ### SVG 内 `<style>` のスコーピングについて
563
-
564
- 各 SVG 内の `<style>` ブロックは `svg { ... }` セレクタで CSS カスタムプロパティを定義している。
565
- HTML5 仕様上、インライン SVG 内の `<style>` は当該 SVG にスコープされるが、
566
- 一部ブラウザ (特に古いもの) でスタイルがリークする既知の問題がある。
567
-
568
- **本実装では問題にならない理由:**
569
- - 全 SVG が同一テーマを使用するため、仮にスタイルがリークしても値は同一
570
- - CSS カスタムプロパティ (`--_text`, `--_line` 等) は `var(--fg)`, `var(--bg)` を参照しており、
571
- これらは各 `<svg>` 要素の `style` 属性 (インラインスタイル) で設定される
572
- - インラインスタイルは `<style>` ブロックより高い specificity を持つため、
573
- 各 SVG の `--fg`, `--bg` は常にその SVG 固有の値に解決される
574
- - `text { font-family: ... }` もリークしうるが、全 SVG で同じフォントのため無害
575
-
576
- 将来的に SVG ごとに異なるテーマを使う場合はスコーピング対策が必要になるが、
577
- 現在の設計ではその予定はない。
578
-
579
- ### SVG marker ID のユニーク化 (重要・PoC 検証済み)
580
-
581
- beautiful-mermaid は SVG 内の `<marker>` に固定 ID を使用しており、
582
- namespace/prefix オプションは提供していない。
583
-
584
- **全 marker ID の一覧** (ソースコード調査済み):
585
-
586
- | レンダラー | marker ID | 用途 |
587
- |-----------|-----------|------|
588
- | flowchart | `arrowhead` | 順方向矢印 |
589
- | flowchart | `arrowhead-start` | 逆方向矢印 |
590
- | flowchart | `arrowhead-{suffix}` | linkStyle で色指定した矢印 |
591
- | flowchart | `arrowhead-start-{suffix}` | 同上 (逆方向) |
592
- | sequence | `seq-arrow` | filled 矢印 |
593
- | sequence | `seq-arrow-open` | open 矢印 |
594
- | class | `cls-inherit` | 継承 (hollow triangle) |
595
- | class | `cls-composition` | コンポジション (filled diamond) |
596
- | class | `cls-aggregation` | 集約 (hollow diamond) |
597
- | class | `cls-arrow` | 関連 (open arrow) |
598
-
599
- 注: `{suffix}` は `markerSuffix()` 関数により非英数字をhex エンコードした文字列
600
- (例: `var(--_arrow)` -> `var28--5farrow29`)。
601
-
602
- **beautiful-mermaid が `id` 属性を使うのは `<marker>` 要素のみ**。
603
- ノード等には `data-id` 属性を使用し、`<clipPath>`, `<filter>`, `<linearGradient>` 等の
604
- ID 付き要素は生成しない (ソースコード全件調査済み: `renderer.ts`, `sequence/renderer.ts`,
605
- `class/renderer.ts`, `er/renderer.ts`, `xychart/renderer.ts`)。
606
-
607
- したがって、` id="..."` と `url(#...)` の一括置換は現時点で安全:
608
-
609
- ```javascript
610
- function escapeHtml(str) {
611
- return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
612
- }
613
-
614
- function convertMermaidToSVG(markdown, diagramTheme) {
615
- const mermaidRegex = /```mermaid\s+([\s\S]+?)```/g;
616
- let svgIndex = 0;
617
- return markdown.replace(mermaidRegex, (_, code) => {
618
- try {
619
- const prefix = `m${svgIndex++}`;
620
- let svg = renderMermaidSVG(code.trim(), diagramTheme);
621
- svg = svg.replace(/@import url\([^)]+\);\s*/g, '');
622
- // Prefix all id="..." and url(#...) to avoid cross-SVG collisions
623
- // Note: regex uses ` id=` (with leading space) to avoid matching `data-id`
624
- svg = svg.replace(/ id="([^"]+)"/g, ` id="${prefix}-$1"`);
625
- svg = svg.replace(/url\(#([^)]+)\)/g, `url(#${prefix}-$1)`);
626
- return svg;
627
- } catch (e) {
628
- return `<pre class="mermaid-error">${escapeHtml(e.message)}\n\n${escapeHtml(code.trim())}</pre>`;
629
- }
630
- });
631
- }
632
- ```
633
-
634
- **PoC 検証結果** (`poc-html.mjs` で test/test3.md を変換):
635
- - 6つの Mermaid ブロック (flowchart x3, sequence, class, state) から14個の marker ID を生成
636
- - 全 marker ID がユニーク (m0-arrowhead, m1-arrowhead, m2-seq-arrow, m3-cls-inherit 等)
637
- - 重複ゼロを確認
638
-
639
- 将来 beautiful-mermaid が `<clipPath id="...">` 等を追加した場合にも
640
- この一括置換で正しく動作する (むしろ限定的な置換よりも安全)。
641
-
642
- **注**: 現時点で beautiful-mermaid は `href="#..."` や `xlink:href="#..."` を生成しないが、
643
- 将来 `<use href="#...">` 等が追加された場合は `href` 参照のプレフィックス化も必要になる。
644
- その際は `href="#` の置換を追加すること。
645
-
646
- ### HTML テンプレート仕様
647
-
648
- - スタンドアロン (外部リソース依存なし)
649
- - コードブロックのシンタックスハイライトは**スコープ外** (将来的に highlight.js / shiki 等で対応可能だが、初回リリースでは無着色)
650
- - `.mermaid-error` のスタイルはテーマの色を使って動的に生成する (後述)
651
- - **POSIX 準拠**: テンプレート末尾に改行 (`\n`) を含める。`</html>` の後に改行1つ
652
-
653
- #### レイアウト
654
-
655
- | プロパティ | 値 |
656
- |-----------|-----|
657
- | `max-width` | `800px` |
658
- | `margin` | `2rem auto` (中央寄せ) |
659
- | `padding` | `0 1rem` |
660
- | `font-family` | `system-ui, -apple-system, sans-serif` |
661
- | `line-height` | `1.6` |
662
-
663
- #### テーマ色の要素別適用
664
-
665
- | CSS セレクタ | プロパティ | テーマ色 |
666
- |-------------|-----------|---------|
667
- | `body` | `background` | `bg` |
668
- | `body` | `color` | `fg` |
669
- | `a` | `color` | `accent` |
670
- | `hr` | `border-color` | `line` |
671
- | `blockquote` | `border-left: 3px solid` | `line` |
672
- | `blockquote` | `color` | `muted` |
673
- | `blockquote` | `padding-left` | `1rem` |
674
- | `svg` | `max-width: 100%; height: auto` | (レスポンシブ) |
675
- | `pre` | `background` | `color-mix(in srgb, fg 8%, bg)` |
676
- | `pre` | `padding` | `1rem` |
677
- | `pre` | `border-radius` | `6px` |
678
- | `pre` | `overflow-x` | `auto` |
679
- | `code` | `font-size` | `0.9em` |
680
- | `code` | `color` | `accent` |
681
- | `pre code` | `color` | `inherit` (pre 内のコードは accent を上書きしない) |
682
- | `table` | `border-collapse` | `collapse` |
683
- | `th, td` | `border` | `1px solid line` |
684
- | `th, td` | `padding` | `0.4rem 0.8rem` |
685
- | `th` | `background` | `color-mix(in srgb, fg 5%, bg)` |
686
-
687
- ### .mermaid-error のテーマ対応
688
-
689
- ハードコードの明るい背景色 (`#fff3cd` 等) はダークテーマで視認性が低い。
690
- テーマの色から動的に生成する:
691
-
692
- ```css
693
- .mermaid-error {
694
- background: color-mix(in srgb, ${t.accent} 10%, ${t.bg});
695
- border: 1px solid color-mix(in srgb, ${t.accent} 40%, ${t.bg});
696
- color: ${t.fg};
697
- padding: 1rem;
698
- border-radius: 6px;
699
- overflow-x: auto;
700
- white-space: pre-wrap;
701
- }
702
- ```
703
-
704
- ## 追加依存
705
-
706
- なし。
707
-
708
- ## フォールバック / エラー処理
709
-
710
- - Mermaid ブロックの SVG 変換失敗時: `<pre class="mermaid-error">` でソースコードとエラーメッセージを表示 (HTML エスケープ済み)
711
- - 未対応の図種 (beautiful-mermaid がサポートしないもの): 同上
712
- - `--html` + 複数ファイル入力: Markdown を先に結合してから変換し、単一 HTML を生成
713
-
714
- ## テスト計画
715
-
716
- ### 既存テストへの影響
717
-
718
- 既存テストはすべて `--no-color` 付きで実行されている。`--no-color` の実装が後処理 ANSI ストリッピングから `chalk.level = 0` に変更されるが、出力結果は同等であるため既存テストへの影響は最小限。
719
-
720
- ただし以下の更新が必要:
721
-
722
- | テスト | 変更理由 |
723
- |-------|---------|
724
- | `--version` テスト | バージョン番号を `1.5.1` -> `2.0.0` に更新 |
725
- | `--help` テスト | 新オプション (`--html`) がヘルプ出力に含まれる。テーマ名一覧が変更される |
726
-
727
- ### 追加テスト (test/memd.test.js)
728
-
729
- #### --html 出力テスト
730
-
731
- | テストケース | 入力ファイル | 検証内容 |
732
- |-------------|------------|---------|
733
- | `--html` + ファイル -> stdout | test/test1.md | `<!DOCTYPE html>`, `<svg`, テーマ CSS 色が含まれること。末尾が `\n` で終わること |
734
- | `--html` + stdin -> stdout | `echo '# hello'` | パイプ入力で HTML が stdout に出力されること |
735
- | `--html` + Mermaid エラー | (gantt 記法を含む文字列) | `<pre class="mermaid-error">` が出力され、エラーメッセージが HTML エスケープされていること |
736
- | `--html` + 複数 Mermaid ブロック | test/test3.md | marker ID が衝突しないこと (`m0-`, `m1-` prefix)。SVG が複数含まれること |
737
- | `--html` + 複数ファイル | test/test1.md test/test2.md | 結合された単一 HTML が stdout に出力されること。marker ID がファイル間で連続すること |
738
-
739
- #### テーマ関連テスト (HTML パス)
740
-
741
- | テストケース | 検証内容 |
742
- |-------------|---------|
743
- | `--html --theme dracula` | HTML 出力に dracula の CSS 色 (`bg: #282a36`, `fg: #f8f8f2` 等) が含まれること |
744
- | `--html --theme tokyo-night` | HTML 出力に tokyo-night の CSS 色が含まれること |
745
- | `--html --theme nonexistent` | エラー終了し、利用可能テーマ一覧が表示されること |
746
- | `--html --no-color` | エラーにならず、HTML がフルカラーで出力されること (黙って無視) |
747
-
748
- #### テーマ関連テスト (ターミナルパス)
749
-
750
- | テストケース | 検証内容 |
751
- |-------------|---------|
752
- | `--theme dracula --no-pager --no-color` + ファイル | dracula テーマでターミナル出力が正常に生成されること |
753
- | `--theme tokyo-night --no-pager --no-color` + ファイル | ハイライトなしテーマでターミナル出力が正常に生成されること (フォールバック動作) |
754
- | `--theme one-dark --no-pager --no-color` + ファイル | one-dark テーマでターミナル出力が正常に生成されること |
755
- | `--theme nonexistent --no-pager --no-color` + ファイル | エラー終了し、利用可能テーマ一覧が表示されること |
756
- | デフォルト (--theme なし) + `--no-pager --no-color` + ファイル | zinc-light がデフォルトとして使用されること |
757
-
758
- #### chalk.level = 0 と buildTheme() の組み合わせテスト
759
-
760
- `buildTheme()` で事前構築された chalk チェインが `chalk.level = 0` 設定後に
761
- ANSI コードを出力しないことを検証する。5つの `TERMINAL_THEMES` エントリ
762
- (one-dark, dracula, github-dark, solarized-dark, nord) が対象。
763
-
764
- | テストケース | 検証内容 |
765
- |-------------|---------|
766
- | `--theme dracula --no-pager --no-color` + test/test-highlight.md | ANSI エスケープコード (`\x1b[`) が出力に含まれないこと |
767
- | `--theme one-dark --no-pager --no-color` + test/test-highlight.md | 同上 |
768
- | `--theme github-dark --no-pager --no-color` + test/test-highlight.md | 同上 |
769
- | `--theme solarized-dark --no-pager --no-color` + test/test-highlight.md | 同上 |
770
- | `--theme nord --no-pager --no-color` + test/test-highlight.md | 同上 |
771
-
772
- test/test-highlight.md にはコードブロック (シンタックスハイライト対象) と
773
- 通常の Markdown 要素 (heading, bold, link 等) の両方が含まれるため、
774
- `buildTheme()` の highlight パレットと markdown パレット両方の無効化を検証できる。
775
-
776
- **背景**: `buildTheme()` はモジュールロード時に `chalk.hex()` チェインを構築する。
777
- `chalk.level = 0` は action 内で設定される。chalk 5.x では子チェインが
778
- 親インスタンスの `level` を動的参照するため理論上は問題ないが、
779
- chalk のメジャーバージョンアップでこの挙動が変わる可能性があるため、
780
- テストで挙動を保証する。
781
-
782
- #### 既存テスト更新
783
-
784
- | テストケース | 変更内容 |
785
- |-------------|---------|
786
- | `--version` | バージョン番号の期待値を `1.5.1` -> `2.0.0` に更新 |
787
- | `--help` | `--html`, 新テーマ名一覧 (`zinc-light` 等) が出力に含まれることを検証 |
788
-
789
- ### README.md 更新内容
790
-
791
- 1. **Usage セクションのヘルプテキスト**: 新オプション (`--html`) を追加。テーマ名一覧を beautiful-mermaid テーマに更新。デフォルト値を `zinc-light` に変更
792
- 2. **description**: "Render markdown with mermaid diagrams to terminal output" -> "Render markdown with mermaid diagrams" (HTML 出力にも対応するため)
793
- 3. **Example セクション**: HTML 出力例を追加 (`memd doc.md --html > out.html`)
794
-
795
- ### package.json 更新内容
796
-
797
- 1. **version**: `1.5.1` -> `2.0.0`
798
- 2. **description**: `"A CLI tool to render Markdown with Mermaid diagrams directly in the terminal"` -> `"A CLI tool to render Markdown with Mermaid diagrams"` (HTML 出力にも対応するため)
799
-
800
- ## スコープ外 (将来対応)
801
-
802
- - xychart の `interactive` オプション (ホバーツールチップ): beautiful-mermaid の `RenderOptions` でサポートされているが、初回リリースでは対応しない
803
- - コードブロックのシンタックスハイライト (highlight.js / shiki)
804
- - `--html` + stdin + ファイル引数の同時指定: 現在のコードは `files.length === 0` で stdin に分岐する (`main.js:338`)。この動作を維持し、明示的な対応は行わない
805
- - ターミナルハイライトの対応テーマ追加 (現在5テーマのみ: one-dark, dracula, github-dark, solarized-dark, nord)