vimd 0.1.0

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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +270 -0
  3. package/dist/cli/commands/build.d.ts +7 -0
  4. package/dist/cli/commands/build.d.ts.map +1 -0
  5. package/dist/cli/commands/build.js +54 -0
  6. package/dist/cli/commands/config.d.ts +6 -0
  7. package/dist/cli/commands/config.d.ts.map +1 -0
  8. package/dist/cli/commands/config.js +117 -0
  9. package/dist/cli/commands/dev.d.ts +8 -0
  10. package/dist/cli/commands/dev.d.ts.map +1 -0
  11. package/dist/cli/commands/dev.js +95 -0
  12. package/dist/cli/commands/theme.d.ts +2 -0
  13. package/dist/cli/commands/theme.d.ts.map +1 -0
  14. package/dist/cli/commands/theme.js +46 -0
  15. package/dist/cli/index.d.ts +3 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +38 -0
  18. package/dist/cli/setup.d.ts +2 -0
  19. package/dist/cli/setup.d.ts.map +1 -0
  20. package/dist/cli/setup.js +50 -0
  21. package/dist/config/defaults.d.ts +3 -0
  22. package/dist/config/defaults.d.ts.map +1 -0
  23. package/dist/config/defaults.js +19 -0
  24. package/dist/config/loader.d.ts +9 -0
  25. package/dist/config/loader.d.ts.map +1 -0
  26. package/dist/config/loader.js +78 -0
  27. package/dist/config/types.d.ts +47 -0
  28. package/dist/config/types.d.ts.map +1 -0
  29. package/dist/config/types.js +4 -0
  30. package/dist/config/validator.d.ts +11 -0
  31. package/dist/config/validator.d.ts.map +1 -0
  32. package/dist/config/validator.js +38 -0
  33. package/dist/core/converter.d.ts +10 -0
  34. package/dist/core/converter.d.ts.map +1 -0
  35. package/dist/core/converter.js +81 -0
  36. package/dist/core/pandoc-detector.d.ts +8 -0
  37. package/dist/core/pandoc-detector.d.ts.map +1 -0
  38. package/dist/core/pandoc-detector.js +70 -0
  39. package/dist/core/server.d.ts +11 -0
  40. package/dist/core/server.d.ts.map +1 -0
  41. package/dist/core/server.js +57 -0
  42. package/dist/core/watcher.d.ts +16 -0
  43. package/dist/core/watcher.d.ts.map +1 -0
  44. package/dist/core/watcher.js +44 -0
  45. package/dist/index.d.ts +14 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +18 -0
  48. package/dist/templates/.gitkeep +0 -0
  49. package/dist/templates/default.html +22 -0
  50. package/dist/templates/standalone.html +31 -0
  51. package/dist/themes/index.d.ts +7 -0
  52. package/dist/themes/index.d.ts.map +1 -0
  53. package/dist/themes/index.js +29 -0
  54. package/dist/themes/registry.d.ts +4 -0
  55. package/dist/themes/registry.d.ts.map +1 -0
  56. package/dist/themes/registry.js +40 -0
  57. package/dist/themes/styles/.gitkeep +0 -0
  58. package/dist/themes/styles/academic.css +68 -0
  59. package/dist/themes/styles/dark.css +54 -0
  60. package/dist/themes/styles/github.css +1 -0
  61. package/dist/themes/styles/minimal.css +35 -0
  62. package/dist/themes/styles/technical.css +84 -0
  63. package/dist/types/index.d.ts +2 -0
  64. package/dist/types/index.d.ts.map +1 -0
  65. package/dist/types/index.js +2 -0
  66. package/dist/utils/logger.d.ts +7 -0
  67. package/dist/utils/logger.d.ts.map +1 -0
  68. package/dist/utils/logger.js +16 -0
  69. package/dist/utils/os-detector.d.ts +8 -0
  70. package/dist/utils/os-detector.d.ts.map +1 -0
  71. package/dist/utils/os-detector.js +34 -0
  72. package/dist/utils/path-resolver.d.ts +7 -0
  73. package/dist/utils/path-resolver.d.ts.map +1 -0
  74. package/dist/utils/path-resolver.js +26 -0
  75. package/dist/utils/process-manager.d.ts +12 -0
  76. package/dist/utils/process-manager.d.ts.map +1 -0
  77. package/dist/utils/process-manager.js +35 -0
  78. package/package.json +75 -0
  79. package/templates/.gitkeep +0 -0
  80. package/templates/default.html +22 -0
  81. package/templates/standalone.html +31 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 notokeishou
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,270 @@
1
+ # vimd
2
+
3
+ 🌐 [English](README-en.md) | 日本語
4
+
5
+ > pandocを使ったリアルタイムMarkdownプレビューツール (view markdown)
6
+
7
+ [![npm version](https://img.shields.io/npm/v/vimd.svg)](https://www.npmjs.com/package/vimd)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ **vimd** は、pandocを使用した高速でシンプルなMarkdownプレビューツールです。複数のテーマに対応したリアルタイムHTMLプレビューを提供します。
11
+
12
+ ## 特徴
13
+
14
+ - **リアルタイムプレビュー**: ファイル保存時にブラウザが即座に更新 (live-server)
15
+ - **複数テーマ**: 5つの組み込みテーマ (GitHub, Minimal, Dark, Academic, Technical)
16
+ - **pandoc連携**: pandocによる高品質なMarkdown変換
17
+ - **グローバル設定**: プロジェクトディレクトリを汚さない `~/.vimd/config.js`
18
+ - **対話的セットアップ**: 初回起動時にテーマ選択をガイド
19
+ - **クロスプラットフォーム**: macOS, Linux, Windows で動作
20
+
21
+ ## インストール
22
+
23
+ ```bash
24
+ npm install -g vimd
25
+ ```
26
+
27
+ インストール後、対話的なセットアップで初期設定を行います。
28
+
29
+ ### 必要要件
30
+
31
+ - **Node.js** >= 18.0.0 (ESMサポートが必要)
32
+ - **pandoc** >= 2.0 (別途インストールが必要)
33
+
34
+ pandocのインストール方法:
35
+
36
+ ```bash
37
+ # macOS
38
+ brew install pandoc
39
+
40
+ # Ubuntu/Debian
41
+ sudo apt install pandoc
42
+
43
+ # Windows
44
+ choco install pandoc
45
+ ```
46
+
47
+ ## クイックスタート
48
+
49
+ ```bash
50
+ # ライブプレビューを開始
51
+ vimd dev README.md
52
+
53
+ # 静的HTMLを生成
54
+ vimd build README.md
55
+
56
+ # テーマを変更
57
+ vimd theme
58
+
59
+ # 設定を編集
60
+ vimd config
61
+ ```
62
+
63
+ ## コマンド
64
+
65
+ ### `vimd dev <file>`
66
+
67
+ ホットリロード対応のライブプレビューサーバーを起動します。ブラウザを自動で開き、ファイルの変更を監視します。
68
+
69
+ ```bash
70
+ vimd dev README.md
71
+ vimd dev docs/guide.md --port 3000
72
+ vimd dev spec.md --theme dark --no-open
73
+ ```
74
+
75
+ **オプション:**
76
+
77
+ - `-p, --port <port>`: ポート番号 (デフォルト: 8080)
78
+ - `-t, --theme <theme>`: テーマ名 (グローバル設定を上書き)
79
+ - `--no-open`: ブラウザを自動で開かない
80
+
81
+ ### `vimd build <file>`
82
+
83
+ 静的HTMLファイルを生成します。スタイルが埋め込まれたスタンドアロンHTMLを出力します。
84
+
85
+ ```bash
86
+ vimd build README.md
87
+ vimd build docs/guide.md -o dist/guide.html
88
+ vimd build spec.md --theme academic
89
+ ```
90
+
91
+ **オプション:**
92
+
93
+ - `-o, --output <path>`: 出力ファイルパス (デフォルト: 同名で拡張子.html)
94
+ - `-t, --theme <theme>`: テーマ名 (グローバル設定を上書き)
95
+
96
+ ### `vimd theme`
97
+
98
+ 対話的にテーマを変更します。5つの組み込みテーマから選択できます。
99
+
100
+ ```bash
101
+ vimd theme
102
+ ```
103
+
104
+ ### `vimd config`
105
+
106
+ 対話的に設定を編集します。テーマ、ポート、その他の設定を変更できます。
107
+
108
+ ```bash
109
+ # 対話的な設定エディタ
110
+ vimd config
111
+
112
+ # 現在の設定を表示
113
+ vimd config --list
114
+ ```
115
+
116
+ ## テーマ
117
+
118
+ vimdには5つの組み込みテーマがあります:
119
+
120
+ | テーマ | 説明 | 用途 |
121
+ | ------------- | --------------------------------- | -------------------- |
122
+ | **GitHub** | GitHub Markdownスタイル (推奨) | 一般的なドキュメント |
123
+ | **Minimal** | シンプルな白背景 | 集中して書きたいとき |
124
+ | **Dark** | VS Codeインスパイアのダークモード | 夜間の作業 |
125
+ | **Academic** | 論文スタイルのレイアウト | 学術論文、研究文書 |
126
+ | **Technical** | APIドキュメントスタイル | 技術仕様書、API文書 |
127
+
128
+ ## 設定
129
+
130
+ グローバル設定は `~/.vimd/config.js` に保存されます。
131
+
132
+ ```javascript
133
+ export default {
134
+ theme: 'github',
135
+ port: 8080,
136
+ host: 'localhost',
137
+ open: true,
138
+ pandoc: {
139
+ standalone: true,
140
+ toc: false,
141
+ highlightStyle: 'github',
142
+ },
143
+ watch: {
144
+ ignored: ['node_modules', '.git'],
145
+ },
146
+ };
147
+ ```
148
+
149
+ ### 設定オプション
150
+
151
+ - `theme`: デフォルトテーマ名 (文字列)
152
+ - `port`: 開発サーバーのポート (数値、デフォルト: 8080)
153
+ - `host`: 開発サーバーのホスト (文字列、デフォルト: 'localhost')
154
+ - `open`: ブラウザを自動で開く (真偽値、デフォルト: true)
155
+ - `pandoc.standalone`: スタンドアロンHTMLを生成 (真偽値)
156
+ - `pandoc.toc`: 目次を生成 (真偽値)
157
+ - `pandoc.highlightStyle`: コードハイライトスタイル (文字列)
158
+ - `watch.ignored`: ファイル監視で無視するパターン (配列)
159
+
160
+ ## API使用
161
+
162
+ vimdはNode.jsライブラリとしても使用できます:
163
+
164
+ ```javascript
165
+ import { MarkdownConverter, ConfigLoader, ThemeManager } from 'vimd';
166
+
167
+ // 設定を読み込む
168
+ const config = await ConfigLoader.loadGlobal();
169
+
170
+ // コンバーターを作成
171
+ const converter = new MarkdownConverter({
172
+ theme: 'github',
173
+ pandocOptions: config.pandoc,
174
+ });
175
+
176
+ // MarkdownをHTMLに変換
177
+ const html = await converter.convertWithTemplate('README.md');
178
+
179
+ // 利用可能なテーマを一覧表示
180
+ const themes = ThemeManager.list();
181
+ console.log(themes); // [{ name: 'github', displayName: 'GitHub' }, ...]
182
+ ```
183
+
184
+ ## 開発
185
+
186
+ ```bash
187
+ # リポジトリをクローン
188
+ git clone https://github.com/notokeishou/vimd.git
189
+ cd vimd
190
+
191
+ # 依存関係をインストール
192
+ npm install
193
+
194
+ # ビルド
195
+ npm run build
196
+
197
+ # テストを実行
198
+ npm test
199
+
200
+ # カバレッジ付きでテスト
201
+ npm run test:coverage
202
+
203
+ # 開発モード
204
+ npm run dev -- dev test.md
205
+ ```
206
+
207
+ ### プロジェクト構造
208
+
209
+ ```
210
+ vimd/
211
+ ├── src/
212
+ │ ├── cli/ # CLIコマンド
213
+ │ ├── config/ # 設定管理
214
+ │ ├── core/ # コア機能 (converter, watcher, server)
215
+ │ ├── themes/ # テーマシステム
216
+ │ └── utils/ # ユーティリティ関数
217
+ ├── tests/
218
+ │ ├── unit/ # ユニットテスト
219
+ │ └── integration/ # 統合テスト
220
+ ├── templates/ # HTMLテンプレート
221
+ └── dist/ # ビルド済みファイル
222
+ ```
223
+
224
+ ## トラブルシューティング
225
+
226
+ ### pandocが見つからない
227
+
228
+ 「pandoc not found」エラーが出る場合:
229
+
230
+ 1. パッケージマネージャーでpandocをインストール
231
+ 2. インストールを確認: `pandoc --version`
232
+ 3. ターミナルを再起動
233
+
234
+ ### ポートが使用中
235
+
236
+ ポート8080が既に使用中の場合:
237
+
238
+ ```bash
239
+ vimd dev README.md --port 3000
240
+ ```
241
+
242
+ または `~/.vimd/config.js` でデフォルトポートを変更してください。
243
+
244
+ ### テーマが適用されない
245
+
246
+ 以下を確認してください:
247
+
248
+ 1. 利用可能なテーマを確認: `vimd theme`
249
+ 2. 設定を確認: `vimd config --list`
250
+ 3. ソースからの場合は再ビルド: `npm run build`
251
+
252
+ ## ライセンス
253
+
254
+ MIT © notokeishou
255
+
256
+ ## コントリビューション
257
+
258
+ コントリビューションを歓迎します! プルリクエストの提出方法については [CONTRIBUTING.md](CONTRIBUTING.md) をお読みください。
259
+
260
+ ## 変更履歴
261
+
262
+ リリース履歴は [CHANGELOG.md](CHANGELOG.md) を参照してください。
263
+
264
+ ## リンク
265
+
266
+ - [GitHubリポジトリ](https://github.com/notokeishou/vimd)
267
+ - [npmパッケージ](https://www.npmjs.com/package/vimd)
268
+ - [Issue Tracker](https://github.com/notokeishou/vimd/issues)
269
+
270
+ ---
@@ -0,0 +1,7 @@
1
+ interface BuildOptions {
2
+ output?: string;
3
+ theme?: string;
4
+ }
5
+ export declare function buildCommand(filePath: string, options: BuildOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAQA,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CA0Df"}
@@ -0,0 +1,54 @@
1
+ // src/cli/commands/build.ts
2
+ import { ConfigLoader } from '../../config/loader.js';
3
+ import { MarkdownConverter } from '../../core/converter.js';
4
+ import { PandocDetector } from '../../core/pandoc-detector.js';
5
+ import { Logger } from '../../utils/logger.js';
6
+ import * as path from 'path';
7
+ import fs from 'fs-extra';
8
+ export async function buildCommand(filePath, options) {
9
+ try {
10
+ Logger.info('Building HTML...');
11
+ // 1. Load configuration
12
+ const config = await ConfigLoader.loadGlobal();
13
+ // Override with command line options
14
+ if (options.theme) {
15
+ config.theme = options.theme;
16
+ }
17
+ Logger.info(`Theme: ${config.theme}`);
18
+ // 2. Check pandoc installation
19
+ PandocDetector.ensureInstalled();
20
+ // 3. Check file exists
21
+ const absolutePath = path.resolve(filePath);
22
+ if (!(await fs.pathExists(absolutePath))) {
23
+ Logger.error(`File not found: ${filePath}`);
24
+ process.exit(1);
25
+ }
26
+ // 4. Determine output path
27
+ const outputPath = options.output
28
+ ? path.resolve(options.output)
29
+ : path.join(path.dirname(absolutePath), path.basename(filePath, path.extname(filePath)) + '.html');
30
+ Logger.info(`Output: ${outputPath}`);
31
+ // 5. Prepare converter
32
+ const converter = new MarkdownConverter({
33
+ theme: config.theme,
34
+ pandocOptions: {
35
+ ...config.pandoc,
36
+ standalone: true, // build always uses standalone
37
+ },
38
+ customCSS: config.css,
39
+ template: config.template || undefined,
40
+ });
41
+ // 6. Execute conversion
42
+ Logger.info('Converting...');
43
+ const html = await converter.convertWithTemplate(absolutePath);
44
+ await converter.writeHTML(html, outputPath);
45
+ Logger.success(`Build complete: ${outputPath}`);
46
+ }
47
+ catch (error) {
48
+ Logger.error('Build failed');
49
+ if (error instanceof Error) {
50
+ Logger.error(error.message);
51
+ }
52
+ process.exit(1);
53
+ }
54
+ }
@@ -0,0 +1,6 @@
1
+ interface ConfigOptions {
2
+ list?: boolean;
3
+ }
4
+ export declare function configCommand(options: ConfigOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AAQA,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBzE"}
@@ -0,0 +1,117 @@
1
+ // src/cli/commands/config.ts
2
+ import inquirer from 'inquirer';
3
+ import { ConfigLoader } from '../../config/loader.js';
4
+ import { ThemeManager } from '../../themes/index.js';
5
+ import { Logger } from '../../utils/logger.js';
6
+ import { PathResolver } from '../../utils/path-resolver.js';
7
+ export async function configCommand(options) {
8
+ try {
9
+ // --list オプション: 現在の設定を表示
10
+ if (options.list) {
11
+ await showCurrentConfig();
12
+ return;
13
+ }
14
+ // 対話的設定変更
15
+ await interactiveConfig();
16
+ }
17
+ catch (error) {
18
+ Logger.error('Failed to update configuration');
19
+ if (error instanceof Error) {
20
+ Logger.error(error.message);
21
+ }
22
+ process.exit(1);
23
+ }
24
+ }
25
+ async function showCurrentConfig() {
26
+ const config = await ConfigLoader.loadGlobal();
27
+ const configPath = PathResolver.getConfigPath();
28
+ console.log('\nCurrent configuration:');
29
+ console.log(` Theme: ${config.theme}`);
30
+ console.log(` Port: ${config.port}`);
31
+ console.log(` Host: ${config.host}`);
32
+ console.log(` Open Browser: ${config.open}`);
33
+ console.log(` Config File: ${configPath}\n`);
34
+ }
35
+ async function interactiveConfig() {
36
+ const config = await ConfigLoader.loadGlobal();
37
+ // 変更したい項目を選択
38
+ const { item } = await inquirer.prompt([
39
+ {
40
+ type: 'list',
41
+ name: 'item',
42
+ message: 'What would you like to change?',
43
+ choices: [
44
+ { name: 'Theme', value: 'theme' },
45
+ { name: 'Port number', value: 'port' },
46
+ { name: 'Auto-open browser', value: 'open' },
47
+ { name: 'Cancel', value: 'cancel' },
48
+ ],
49
+ },
50
+ ]);
51
+ if (item === 'cancel') {
52
+ Logger.info('Configuration unchanged');
53
+ return;
54
+ }
55
+ // 項目別の変更処理
56
+ switch (item) {
57
+ case 'theme':
58
+ await changeTheme(config);
59
+ break;
60
+ case 'port':
61
+ await changePort(config);
62
+ break;
63
+ case 'open':
64
+ await changeOpen(config);
65
+ break;
66
+ }
67
+ // 設定保存
68
+ await ConfigLoader.save(config);
69
+ Logger.success('Configuration updated');
70
+ }
71
+ async function changeTheme(config) {
72
+ const themes = ThemeManager.list();
73
+ const { theme } = await inquirer.prompt([
74
+ {
75
+ type: 'list',
76
+ name: 'theme',
77
+ message: 'Select a theme:',
78
+ choices: themes.map((t) => ({
79
+ name: t.name === config.theme
80
+ ? `${t.displayName} (current)`
81
+ : t.displayName,
82
+ value: t.name,
83
+ })),
84
+ default: config.theme,
85
+ },
86
+ ]);
87
+ config.theme = theme;
88
+ }
89
+ async function changePort(config) {
90
+ const { port } = await inquirer.prompt([
91
+ {
92
+ type: 'input',
93
+ name: 'port',
94
+ message: 'Enter port number:',
95
+ default: config.port.toString(),
96
+ validate: (input) => {
97
+ const num = parseInt(input, 10);
98
+ if (isNaN(num) || num < 1 || num > 65535) {
99
+ return 'Port must be between 1 and 65535';
100
+ }
101
+ return true;
102
+ },
103
+ },
104
+ ]);
105
+ config.port = parseInt(port, 10);
106
+ }
107
+ async function changeOpen(config) {
108
+ const { open } = await inquirer.prompt([
109
+ {
110
+ type: 'confirm',
111
+ name: 'open',
112
+ message: 'Auto-open browser in preview?',
113
+ default: config.open,
114
+ },
115
+ ]);
116
+ config.open = open;
117
+ }
@@ -0,0 +1,8 @@
1
+ interface DevOptions {
2
+ port?: string;
3
+ theme?: string;
4
+ open?: boolean;
5
+ }
6
+ export declare function devCommand(filePath: string, options: DevOptions): Promise<void>;
7
+ export {};
8
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dev.ts"],"names":[],"mappings":"AAWA,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CAoGf"}
@@ -0,0 +1,95 @@
1
+ // src/cli/commands/dev.ts
2
+ import { ConfigLoader } from '../../config/loader.js';
3
+ import { FileWatcher } from '../../core/watcher.js';
4
+ import { MarkdownConverter } from '../../core/converter.js';
5
+ import { LiveServer } from '../../core/server.js';
6
+ import { PandocDetector } from '../../core/pandoc-detector.js';
7
+ import { Logger } from '../../utils/logger.js';
8
+ import { ProcessManager } from '../../utils/process-manager.js';
9
+ import * as path from 'path';
10
+ import fs from 'fs-extra';
11
+ export async function devCommand(filePath, options) {
12
+ try {
13
+ Logger.info('Starting vimd dev...');
14
+ // 1. Load configuration
15
+ const config = await ConfigLoader.loadGlobal();
16
+ // Override with command line options
17
+ if (options.port) {
18
+ config.port = parseInt(options.port, 10);
19
+ }
20
+ if (options.theme) {
21
+ config.theme = options.theme;
22
+ }
23
+ if (options.open !== undefined) {
24
+ config.open = options.open;
25
+ }
26
+ Logger.info(`Theme: ${config.theme}`);
27
+ Logger.info(`Port: ${config.port}`);
28
+ // 2. Check pandoc installation
29
+ PandocDetector.ensureInstalled();
30
+ // 3. Check file exists
31
+ const absolutePath = path.resolve(filePath);
32
+ if (!(await fs.pathExists(absolutePath))) {
33
+ Logger.error(`File not found: ${filePath}`);
34
+ process.exit(1);
35
+ }
36
+ // 4. Prepare output directory
37
+ const outputDir = path.join(process.cwd(), '.vimd-tmp');
38
+ await fs.ensureDir(outputDir);
39
+ const htmlPath = path.join(outputDir, path.basename(filePath, path.extname(filePath)) + '.html');
40
+ // 5. Prepare converter
41
+ const converter = new MarkdownConverter({
42
+ theme: config.theme,
43
+ pandocOptions: config.pandoc,
44
+ customCSS: config.css,
45
+ template: config.template,
46
+ });
47
+ // 6. Initial conversion
48
+ Logger.info('Converting markdown...');
49
+ const html = await converter.convertWithTemplate(absolutePath);
50
+ await converter.writeHTML(html, htmlPath);
51
+ Logger.success('Conversion complete');
52
+ // 7. Start live server
53
+ const server = new LiveServer({
54
+ port: config.port,
55
+ host: config.host,
56
+ open: config.open,
57
+ root: outputDir,
58
+ });
59
+ await server.start(htmlPath);
60
+ Logger.info(`Watching: ${filePath}`);
61
+ Logger.info('Press Ctrl+C to stop');
62
+ // 8. Start file watching
63
+ const watcher = new FileWatcher(absolutePath, config.watch);
64
+ watcher.onChange(async (changedPath) => {
65
+ Logger.info('File changed, reconverting...');
66
+ try {
67
+ const newHtml = await converter.convertWithTemplate(changedPath);
68
+ await converter.writeHTML(newHtml, htmlPath);
69
+ Logger.success('Reconversion complete');
70
+ }
71
+ catch (error) {
72
+ Logger.error('Reconversion failed');
73
+ if (error instanceof Error) {
74
+ Logger.error(error.message);
75
+ }
76
+ }
77
+ });
78
+ watcher.start();
79
+ // 9. Register cleanup
80
+ ProcessManager.onExit(async () => {
81
+ Logger.info('Shutting down...');
82
+ await watcher.stop();
83
+ await server.stop();
84
+ await fs.remove(outputDir);
85
+ Logger.info('Cleanup complete');
86
+ });
87
+ }
88
+ catch (error) {
89
+ Logger.error('Failed to start dev server');
90
+ if (error instanceof Error) {
91
+ Logger.error(error.message);
92
+ }
93
+ process.exit(1);
94
+ }
95
+ }
@@ -0,0 +1,2 @@
1
+ export declare function themeCommand(): Promise<void>;
2
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/theme.ts"],"names":[],"mappings":"AAMA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA6ClD"}
@@ -0,0 +1,46 @@
1
+ // src/cli/commands/theme.ts
2
+ import inquirer from 'inquirer';
3
+ import { ConfigLoader } from '../../config/loader.js';
4
+ import { ThemeManager } from '../../themes/index.js';
5
+ import { Logger } from '../../utils/logger.js';
6
+ export async function themeCommand() {
7
+ try {
8
+ // 1. 現在の設定読み込み
9
+ const config = await ConfigLoader.loadGlobal();
10
+ const currentTheme = config.theme;
11
+ // 2. テーマ一覧取得
12
+ const themes = ThemeManager.list();
13
+ // 3. 対話的選択
14
+ const answers = await inquirer.prompt([
15
+ {
16
+ type: 'list',
17
+ name: 'theme',
18
+ message: 'Select a theme:',
19
+ choices: themes.map((t) => ({
20
+ name: t.name === currentTheme
21
+ ? `${t.displayName} (current)`
22
+ : t.displayName,
23
+ value: t.name,
24
+ })),
25
+ default: currentTheme,
26
+ },
27
+ ]);
28
+ // 変更がない場合
29
+ if (answers.theme === currentTheme) {
30
+ Logger.info('Theme unchanged');
31
+ return;
32
+ }
33
+ // 4. 設定更新
34
+ config.theme = answers.theme;
35
+ await ConfigLoader.save(config);
36
+ Logger.success(`Theme updated to '${answers.theme}'`);
37
+ Logger.info('All projects will use this theme.');
38
+ }
39
+ catch (error) {
40
+ Logger.error('Failed to change theme');
41
+ if (error instanceof Error) {
42
+ Logger.error(error.message);
43
+ }
44
+ process.exit(1);
45
+ }
46
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}