vimd 0.1.12 → 0.2.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.
package/README.md CHANGED
@@ -2,128 +2,128 @@
2
2
 
3
3
  🌐 [English](README-en.md) | 日本語
4
4
 
5
- > pandocを使ったリアルタイムMarkdownプレビューツール (view markdown)
5
+ > 書きながら見る。Markdownプレビュー
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/vimd.svg)](https://www.npmjs.com/package/vimd)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+ [![Node.js](https://img.shields.io/badge/Node.js-≥18-green.svg)](https://nodejs.org/)
9
10
 
10
- **vimd** は、pandocを使用した高速でシンプルなMarkdownプレビューツールです。複数のテーマに対応したリアルタイムHTMLプレビューを提供します。
11
+ ---
11
12
 
12
- ## 特徴
13
+ ## デモ
13
14
 
14
- - **リアルタイムプレビュー**: ファイル保存時にブラウザが即座に更新 (live-server)
15
- - **複数テーマ**: 5つの組み込みテーマ (GitHub, Minimal, Dark, Academic, Technical)
16
- - **pandoc連携**: pandocによる高品質なMarkdown変換
17
- - **グローバル設定**: プロジェクトディレクトリを汚さない `~/.vimd/config.js`
18
- - **対話的設定**: `vimd theme` や `vimd config` で簡単に設定変更
19
- - **クロスプラットフォーム**: macOS, Linux, Windows で動作
15
+ ![vimd demo](assets/demo.gif)
20
16
 
21
- ## インストール
17
+ ---
22
18
 
23
- ```bash
24
- npm install -g vimd
25
- ```
19
+ ## テーマ
26
20
 
27
- 初回起動時に `vimd theme` で好みのテーマを選択できます。
21
+ <details open>
22
+ <summary><strong>GitHub</strong> (デフォルト)</summary>
28
23
 
29
- ### 必要要件
24
+ ![GitHub Theme](assets/theme-github.png)
30
25
 
31
- - **Node.js** >= 18.0.0 (ESMサポートが必要)
32
- - **pandoc** >= 2.0 (別途インストールが必要)
26
+ </details>
33
27
 
34
- pandocのインストール方法:
28
+ <details>
29
+ <summary><strong>Dark</strong></summary>
35
30
 
36
- ```bash
37
- # macOS
38
- brew install pandoc
31
+ ![Dark Theme](assets/theme-dark.png)
39
32
 
40
- # Ubuntu/Debian
41
- sudo apt install pandoc
33
+ </details>
42
34
 
43
- # Windows
44
- choco install pandoc
45
- ```
35
+ <details>
36
+ <summary><strong>Academic</strong></summary>
46
37
 
47
- ## クイックスタート
38
+ ![Academic Theme](assets/theme-academic.png)
48
39
 
49
- ```bash
50
- # ライブプレビューを開始
51
- vimd dev draft.md
40
+ </details>
52
41
 
53
- # 静的HTMLを生成
54
- vimd build draft.md
42
+ <details>
43
+ <summary><strong>Minimal</strong></summary>
55
44
 
56
- # テーマを変更
57
- vimd theme
45
+ ![Minimal Theme](assets/theme-minimal.png)
58
46
 
59
- # 設定を編集
60
- vimd config
61
- ```
47
+ </details>
62
48
 
63
- ## コマンド
49
+ <details>
50
+ <summary><strong>Technical</strong></summary>
64
51
 
65
- ### `vimd dev <file>`
52
+ ![Technical Theme](assets/theme-technical.png)
66
53
 
67
- ホットリロード対応のライブプレビューサーバーを起動します。ブラウザを自動で開き、ファイルの変更を監視します。
54
+ </details>
68
55
 
69
- ```bash
70
- vimd dev draft.md
71
- vimd dev docs/guide.md --port 3000
72
- vimd dev article.md --theme dark --no-open
73
- ```
56
+ ---
74
57
 
75
- **オプション:**
58
+ ## クイックスタート
76
59
 
77
- - `-p, --port <port>`: ポート番号 (デフォルト: 8080)
78
- - `-t, --theme <theme>`: テーマ名 (グローバル設定を上書き)
79
- - `--no-open`: ブラウザを自動で開かない
60
+ ### 必要要件
80
61
 
81
- ### `vimd build <file>`
62
+ - **Node.js** >= 18.0.0
63
+ - **pandoc** >= 2.0(オプション、高品質ビルド時のみ)
82
64
 
83
- 静的HTMLファイルを生成します。スタイルが埋め込まれたスタンドアロンHTMLを出力します。
65
+ ### インストール
84
66
 
85
67
  ```bash
86
- vimd build draft.md
87
- vimd build docs/guide.md -o dist/guide.html
88
- vimd build article.md --theme academic
68
+ npm install -g vimd
89
69
  ```
90
70
 
91
- **オプション:**
92
-
93
- - `-o, --output <path>`: 出力ファイルパス (デフォルト: 同名で拡張子.html)
94
- - `-t, --theme <theme>`: テーマ名 (グローバル設定を上書き)
71
+ v0.2.0 からは **pandoc なしで利用可能** になりました。
72
+ 高品質な出力が必要な場合のみ pandoc をインストールしてください。
95
73
 
96
- ### `vimd theme`
74
+ ```bash
75
+ # pandocのインストール(オプション)
76
+ brew install pandoc # macOS
77
+ sudo apt install pandoc # Ubuntu/Debian
78
+ choco install pandoc # Windows
79
+ ```
97
80
 
98
- 対話的にテーマを変更します。5つの組み込みテーマから選択できます。
81
+ ### 使い方
99
82
 
100
83
  ```bash
101
- vimd theme
102
- ```
84
+ # ライブプレビューを開始(pandoc不要、高速)
85
+ vimd dev draft.md
103
86
 
104
- ### `vimd config`
87
+ # 静的HTMLを生成(pandoc使用、高品質)
88
+ vimd build draft.md
105
89
 
106
- 対話的に設定を編集します。テーマ、ポート、その他の設定を変更できます。
90
+ # 高速ビルド(pandoc不要)
91
+ vimd build draft.md --fast
107
92
 
108
- ```bash
109
- # 対話的な設定エディタ
110
- vimd config
93
+ # テーマを変更
94
+ vimd theme
111
95
 
112
- # 現在の設定を表示
113
- vimd config --list
96
+ # 設定を編集
97
+ vimd config
114
98
  ```
115
99
 
116
- ## テーマ
100
+ ---
101
+
102
+ ## コマンド
117
103
 
118
- vimdには5つの組み込みテーマがあります:
104
+ | コマンド | 説明 |
105
+ |---------|------|
106
+ | `vimd dev <file>` | ライブプレビューサーバーを起動 |
107
+ | `vimd build <file>` | 静的HTMLを生成 |
108
+ | `vimd theme` | テーマを対話的に変更 |
109
+ | `vimd config` | 設定を対話的に編集 |
119
110
 
120
- | テーマ | 説明 | 用途 |
121
- | ------------- | --------------------------------- | -------------------- |
122
- | **GitHub** | GitHub Markdownスタイル (推奨) | 一般的なドキュメント |
123
- | **Minimal** | シンプルな白背景 | 集中して書きたいとき |
124
- | **Dark** | VS Codeインスパイアのダークモード | 夜間の作業 |
125
- | **Academic** | 論文スタイルのレイアウト | 学術論文、研究文書 |
126
- | **Technical** | APIドキュメントスタイル | 技術仕様書、API文書 |
111
+ ### オプション
112
+
113
+ ```bash
114
+ # dev コマンド
115
+ vimd dev draft.md --port 3000 # ポート指定
116
+ vimd dev draft.md --theme dark # テーマ指定
117
+ vimd dev draft.md --no-open # ブラウザを開かない
118
+ vimd dev draft.md --pandoc # pandocパーサーを使用
119
+
120
+ # build コマンド
121
+ vimd build draft.md -o output.html # 出力先指定
122
+ vimd build draft.md --fast # markdown-itで高速ビルド
123
+ vimd build draft.md --theme dark # テーマ指定
124
+ ```
125
+
126
+ ---
127
127
 
128
128
  ## 設定
129
129
 
@@ -133,138 +133,55 @@ vimdには5つの組み込みテーマがあります:
133
133
  export default {
134
134
  theme: 'github',
135
135
  port: 8080,
136
- host: 'localhost',
137
136
  open: true,
138
- pandoc: {
139
- standalone: true,
140
- toc: false,
141
- highlightStyle: 'github',
142
- },
143
- watch: {
144
- ignored: ['node_modules', '.git'],
145
- },
137
+ devParser: 'markdown-it', // dev用パーサー(デフォルト: markdown-it)
138
+ buildParser: 'pandoc', // build用パーサー(デフォルト: pandoc)
146
139
  };
147
140
  ```
148
141
 
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('draft.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
- ### プロジェクト構造
142
+ ### パーサー設定
208
143
 
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
- ```
144
+ | パーサー | 特徴 | 用途 |
145
+ |----------|------|------|
146
+ | `markdown-it` | 高速、pandoc不要 | 開発時のプレビュー |
147
+ | `pandoc` | 高品質、多機能 | 最終出力の生成 |
223
148
 
224
- ## トラブルシューティング
149
+ 詳細な設定オプションは [docs/api.md](docs/api.md) を参照してください。
225
150
 
226
- ### pandocが見つからない
151
+ ---
227
152
 
228
- 「pandoc not found」エラーが出る場合:
153
+ ## Why vimd?
229
154
 
230
- 1. パッケージマネージャーでpandocをインストール
231
- 2. インストールを確認: `pandoc --version`
232
- 3. ターミナルを再起動
155
+ | 特徴 | vimd | 他のツール |
156
+ |------|------|-----------|
157
+ | セットアップ | `npm i -g vimd` | 複雑な設定が必要な場合も |
158
+ | 外部依存 | なし(pandocはオプション) | pandoc必須が多い |
159
+ | 変換品質 | markdown-it / pandoc 選択可 | 固定 |
160
+ | テーマ | 5種類組み込み | 別途設定が必要 |
161
+ | 設定ファイル | プロジェクト外 (`~/.vimd/`) | プロジェクト内が多い |
162
+ | ライブリロード | 自動 | 手動リロードが必要な場合も |
233
163
 
234
- ### ポートが使用中
164
+ ---
235
165
 
236
- ポート8080が既に使用中の場合:
166
+ ## ドキュメント
237
167
 
238
- ```bash
239
- vimd dev draft.md --port 3000
240
- ```
168
+ - [開発ガイド](docs/development.md) - 開発環境構築
169
+ - [アーキテクチャ](docs/architecture.md) - プロジェクト構造
170
+ - [APIリファレンス](docs/api.md) - 詳細なオプション
171
+ - [テスト](docs/testing.md) - テスト構成
172
+ - [トラブルシューティング](docs/troubleshooting.md) - よくある問題
241
173
 
242
- または `~/.vimd/config.js` でデフォルトポートを変更してください。
174
+ ---
243
175
 
244
- ### テーマが適用されない
176
+ ## リンク
245
177
 
246
- 以下を確認してください:
178
+ - [CONTRIBUTING.md](CONTRIBUTING.md) - コントリビューションガイド
179
+ - [CHANGELOG.md](CHANGELOG.md) - 変更履歴
180
+ - [GitHub](https://github.com/notokeishou/vimd)
181
+ - [npm](https://www.npmjs.com/package/vimd)
247
182
 
248
- 1. 利用可能なテーマを確認: `vimd theme`
249
- 2. 設定を確認: `vimd config --list`
250
- 3. ソースからの場合は再ビルド: `npm run build`
183
+ ---
251
184
 
252
185
  ## ライセンス
253
186
 
254
187
  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
- ---
@@ -1,6 +1,7 @@
1
1
  interface BuildOptions {
2
2
  output?: string;
3
3
  theme?: string;
4
+ fast?: boolean;
4
5
  }
5
6
  export declare function buildCommand(filePath: string, options: BuildOptions): Promise<void>;
6
7
  export {};
@@ -1 +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"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AASA,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAmEf"}
@@ -2,6 +2,7 @@
2
2
  import { ConfigLoader } from '../../config/loader.js';
3
3
  import { MarkdownConverter } from '../../core/converter.js';
4
4
  import { PandocDetector } from '../../core/pandoc-detector.js';
5
+ import { ParserFactory } from '../../core/parser/index.js';
5
6
  import { Logger } from '../../utils/logger.js';
6
7
  import * as path from 'path';
7
8
  import fs from 'fs-extra';
@@ -15,30 +16,38 @@ export async function buildCommand(filePath, options) {
15
16
  config.theme = options.theme;
16
17
  }
17
18
  Logger.info(`Theme: ${config.theme}`);
18
- // 2. Check pandoc installation
19
- PandocDetector.ensureInstalled();
20
- // 3. Check file exists
19
+ // 2. Determine parser type
20
+ const parserType = options.fast ? 'markdown-it' : config.buildParser;
21
+ Logger.info(`Parser: ${parserType}`);
22
+ // 3. Check pandoc installation only if pandoc parser is selected
23
+ if (parserType === 'pandoc') {
24
+ PandocDetector.ensureInstalled();
25
+ }
26
+ // 4. Check file exists
21
27
  const absolutePath = path.resolve(filePath);
22
28
  if (!(await fs.pathExists(absolutePath))) {
23
29
  Logger.error(`File not found: ${filePath}`);
24
30
  process.exit(1);
25
31
  }
26
- // 4. Determine output path
32
+ // 5. Determine output path
27
33
  const outputPath = options.output
28
34
  ? path.resolve(options.output)
29
35
  : path.join(path.dirname(absolutePath), path.basename(filePath, path.extname(filePath)) + '.html');
30
36
  Logger.info(`Output: ${outputPath}`);
31
- // 5. Prepare converter
37
+ // 6. Prepare converter with selected parser
38
+ const pandocOptions = {
39
+ ...config.pandoc,
40
+ standalone: true, // build always uses standalone
41
+ };
42
+ const parser = ParserFactory.create(parserType, pandocOptions);
32
43
  const converter = new MarkdownConverter({
33
44
  theme: config.theme,
34
- pandocOptions: {
35
- ...config.pandoc,
36
- standalone: true, // build always uses standalone
37
- },
45
+ pandocOptions: pandocOptions,
38
46
  customCSS: config.css,
39
47
  template: config.template || undefined,
40
48
  });
41
- // 6. Execute conversion
49
+ converter.setParser(parser);
50
+ // 7. Execute conversion
42
51
  Logger.info('Converting...');
43
52
  const html = await converter.convertWithTemplate(absolutePath);
44
53
  await converter.writeHTML(html, outputPath);
@@ -2,6 +2,7 @@ interface DevOptions {
2
2
  port?: string;
3
3
  theme?: string;
4
4
  open?: boolean;
5
+ pandoc?: boolean;
5
6
  }
6
7
  export declare function devCommand(filePath: string, options: DevOptions): Promise<void>;
7
8
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dev.ts"],"names":[],"mappings":"AAYA,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,CA+If"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dev.ts"],"names":[],"mappings":"AAaA,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CAuJf"}
@@ -4,6 +4,7 @@ import { FileWatcher } from '../../core/watcher.js';
4
4
  import { MarkdownConverter } from '../../core/converter.js';
5
5
  import { LiveServer } from '../../core/server.js';
6
6
  import { PandocDetector } from '../../core/pandoc-detector.js';
7
+ import { ParserFactory } from '../../core/parser/index.js';
7
8
  import { Logger } from '../../utils/logger.js';
8
9
  import { ProcessManager } from '../../utils/process-manager.js';
9
10
  import { SessionManager } from '../../utils/session-manager.js';
@@ -47,32 +48,39 @@ export async function devCommand(filePath, options) {
47
48
  }
48
49
  Logger.info(`Theme: ${config.theme}`);
49
50
  Logger.info(`Port: ${port}`);
50
- // 5. Check pandoc installation
51
- PandocDetector.ensureInstalled();
52
- // 6. Check file exists
51
+ // 5. Determine parser type
52
+ const parserType = options.pandoc ? 'pandoc' : config.devParser;
53
+ Logger.info(`Parser: ${parserType}`);
54
+ // 6. Check pandoc installation only if pandoc parser is selected
55
+ if (parserType === 'pandoc') {
56
+ PandocDetector.ensureInstalled();
57
+ }
58
+ // 7. Check file exists
53
59
  const absolutePath = path.resolve(filePath);
54
60
  if (!(await fs.pathExists(absolutePath))) {
55
61
  Logger.error(`File not found: ${filePath}`);
56
62
  process.exit(1);
57
63
  }
58
- // 7. Prepare output HTML in source directory
64
+ // 8. Prepare output HTML in source directory
59
65
  const sourceDir = path.dirname(absolutePath);
60
66
  const basename = path.basename(filePath, path.extname(filePath));
61
67
  const htmlFileName = `vimd-preview-${basename}.html`;
62
68
  const htmlPath = path.join(sourceDir, htmlFileName);
63
- // 8. Prepare converter
69
+ // 9. Prepare converter with selected parser
70
+ const parser = ParserFactory.create(parserType, config.pandoc);
64
71
  const converter = new MarkdownConverter({
65
72
  theme: config.theme,
66
73
  pandocOptions: config.pandoc,
67
74
  customCSS: config.css,
68
75
  template: config.template,
69
76
  });
70
- // 9. Initial conversion
77
+ converter.setParser(parser);
78
+ // 10. Initial conversion
71
79
  Logger.info('Converting markdown...');
72
80
  const html = await converter.convertWithTemplate(absolutePath);
73
81
  await converter.writeHTML(html, htmlPath);
74
82
  Logger.success('Conversion complete');
75
- // 10. Start live server from source directory
83
+ // 11. Start live server from source directory
76
84
  const server = new LiveServer({
77
85
  port: port,
78
86
  host: config.host,
@@ -80,7 +88,7 @@ export async function devCommand(filePath, options) {
80
88
  root: sourceDir,
81
89
  });
82
90
  await server.start(htmlPath);
83
- // 11. Save session
91
+ // 12. Save session
84
92
  await SessionManager.saveSession({
85
93
  pid: process.pid,
86
94
  port: port,
@@ -90,7 +98,7 @@ export async function devCommand(filePath, options) {
90
98
  });
91
99
  Logger.info(`Watching: ${filePath}`);
92
100
  Logger.info('Press Ctrl+C to stop');
93
- // 12. Start file watching
101
+ // 13. Start file watching
94
102
  const watcher = new FileWatcher(absolutePath, config.watch);
95
103
  watcher.onChange(async (changedPath) => {
96
104
  Logger.info('File changed, reconverting...');
@@ -107,7 +115,7 @@ export async function devCommand(filePath, options) {
107
115
  }
108
116
  });
109
117
  watcher.start();
110
- // 13. Register cleanup - remove generated HTML file and session
118
+ // 14. Register cleanup - remove generated HTML file and session
111
119
  ProcessManager.onExit(async () => {
112
120
  Logger.info('Shutting down...');
113
121
  await watcher.stop();
package/dist/cli/index.js CHANGED
@@ -19,6 +19,7 @@ program
19
19
  .option('-p, --port <port>', 'Port number', '8080')
20
20
  .option('-t, --theme <theme>', 'Theme name')
21
21
  .option('--no-open', 'Do not open browser automatically')
22
+ .option('--pandoc', 'Use pandoc parser instead of markdown-it')
22
23
  .action(devCommand);
23
24
  // vimd build <file>
24
25
  program
@@ -26,6 +27,7 @@ program
26
27
  .description('Build static HTML file')
27
28
  .option('-o, --output <path>', 'Output file path')
28
29
  .option('-t, --theme <theme>', 'Theme name')
30
+ .option('--fast', 'Use markdown-it parser for faster build')
29
31
  .action(buildCommand);
30
32
  // vimd theme
31
33
  program
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,eAAO,MAAM,cAAc,EAAE,UAkB5B,CAAC"}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,eAAO,MAAM,cAAc,EAAE,UAoB5B,CAAC"}
@@ -16,4 +16,6 @@ export const DEFAULT_CONFIG = {
16
16
  inlineCSS: false,
17
17
  standalone: true,
18
18
  },
19
+ devParser: 'markdown-it',
20
+ buildParser: 'pandoc',
19
21
  };
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Available parser types.
3
+ * Duplicated here to avoid circular dependency with core/parser/types.ts
4
+ */
5
+ export type ConfigParserType = 'markdown-it' | 'pandoc';
1
6
  export interface VimdConfig {
2
7
  theme: 'github' | 'minimal' | 'dark' | 'academic' | 'technical';
3
8
  port: number;
@@ -8,6 +13,8 @@ export interface VimdConfig {
8
13
  pandoc: PandocConfig;
9
14
  watch: WatchConfig;
10
15
  build?: BuildConfig;
16
+ devParser: ConfigParserType;
17
+ buildParser: ConfigParserType;
11
18
  }
12
19
  export interface PandocConfig {
13
20
  standalone: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,CAAC;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAEpE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,CAAC;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAEpE"}
@@ -1,8 +1,26 @@
1
1
  import { ConverterConfig } from '../config/types.js';
2
+ import { Parser } from './parser/index.js';
2
3
  export declare class MarkdownConverter {
3
4
  private config;
5
+ private parser;
4
6
  constructor(config: ConverterConfig);
7
+ /**
8
+ * Set the parser to use for conversion.
9
+ * If not set, falls back to legacy pandoc conversion.
10
+ * @param parser - The parser instance to use
11
+ */
12
+ setParser(parser: Parser): void;
13
+ /**
14
+ * Get the currently set parser.
15
+ * @returns The parser instance or null if not set
16
+ */
17
+ getParser(): Parser | null;
5
18
  convert(markdownPath: string): Promise<string>;
19
+ /**
20
+ * Legacy pandoc conversion method.
21
+ * Used when no parser is explicitly set (backward compatibility).
22
+ */
23
+ private convertWithPandocLegacy;
6
24
  convertWithTemplate(markdownPath: string): Promise<string>;
7
25
  writeHTML(html: string, outputPath: string): Promise<void>;
8
26
  private buildPandocArgs;
@@ -1 +1 @@
1
- {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/core/converter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AASrD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,eAAe;IAErC,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiB9C,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8B1D,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhE,OAAO,CAAC,eAAe;CA+BxB"}
1
+ {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/core/converter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAQ3C,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,MAAM,CAAuB;gBAEjB,MAAM,EAAE,eAAe;IAE3C;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B;;;OAGG;IACH,SAAS,IAAI,MAAM,GAAG,IAAI;IAIpB,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWpD;;;OAGG;YACW,uBAAuB;IAiB/B,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8B1D,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhE,OAAO,CAAC,eAAe;CA+BxB"}
@@ -9,8 +9,37 @@ const __dirname = path.dirname(__filename);
9
9
  export class MarkdownConverter {
10
10
  constructor(config) {
11
11
  this.config = config;
12
+ this.parser = null;
13
+ }
14
+ /**
15
+ * Set the parser to use for conversion.
16
+ * If not set, falls back to legacy pandoc conversion.
17
+ * @param parser - The parser instance to use
18
+ */
19
+ setParser(parser) {
20
+ this.parser = parser;
21
+ }
22
+ /**
23
+ * Get the currently set parser.
24
+ * @returns The parser instance or null if not set
25
+ */
26
+ getParser() {
27
+ return this.parser;
12
28
  }
13
29
  async convert(markdownPath) {
30
+ // If a parser is set, use it
31
+ if (this.parser) {
32
+ const content = await fs.readFile(markdownPath, 'utf-8');
33
+ return this.parser.parse(content);
34
+ }
35
+ // Legacy: use direct pandoc execution for backward compatibility
36
+ return this.convertWithPandocLegacy(markdownPath);
37
+ }
38
+ /**
39
+ * Legacy pandoc conversion method.
40
+ * Used when no parser is explicitly set (backward compatibility).
41
+ */
42
+ async convertWithPandocLegacy(markdownPath) {
14
43
  const pandocArgs = this.buildPandocArgs();
15
44
  const command = `pandoc ${pandocArgs.join(' ')} "${markdownPath}"`;
16
45
  try {
@@ -68,7 +97,7 @@ export class MarkdownConverter {
68
97
  }
69
98
  }
70
99
  if (this.config.pandocOptions.highlightStyle) {
71
- args.push(`--highlight-style=${this.config.pandocOptions.highlightStyle}`);
100
+ args.push(`--syntax-highlighting=${this.config.pandocOptions.highlightStyle}`);
72
101
  }
73
102
  // Metadata
74
103
  if (this.config.pandocOptions.metadata) {
@@ -1 +1 @@
1
- {"version":3,"file":"pandoc-detector.d.ts","sourceRoot":"","sources":["../../src/core/pandoc-detector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEjD,qBAAa,cAAc;IACzB,MAAM,CAAC,KAAK,IAAI,OAAO;IASvB,MAAM,CAAC,QAAQ,IAAI,MAAM;IAczB,MAAM,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IA4CzC,MAAM,CAAC,eAAe,IAAI,IAAI;CAQ/B"}
1
+ {"version":3,"file":"pandoc-detector.d.ts","sourceRoot":"","sources":["../../src/core/pandoc-detector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEjD,qBAAa,cAAc;IACzB,MAAM,CAAC,KAAK,IAAI,OAAO;IASvB,MAAM,CAAC,QAAQ,IAAI,MAAM;IAczB,MAAM,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAiDzC,MAAM,CAAC,eAAe,IAAI,IAAI;CAQ/B"}
@@ -26,8 +26,13 @@ export class PandocDetector {
26
26
  static showInstallGuide(os) {
27
27
  console.error('⚠️ pandoc not found');
28
28
  console.error('');
29
- console.error('vimd requires pandoc to convert Markdown to HTML.');
30
- console.error('Please install pandoc manually:');
29
+ console.error('pandoc is required for the selected parser mode.');
30
+ console.error('');
31
+ console.error('Option 1: Use markdown-it mode (no pandoc needed)');
32
+ console.error(' vimd dev document.md (default, fast preview)');
33
+ console.error(' vimd build document.md --fast');
34
+ console.error('');
35
+ console.error('Option 2: Install pandoc for high-quality output');
31
36
  console.error('');
32
37
  switch (os) {
33
38
  case 'macos':
@@ -0,0 +1,5 @@
1
+ export type { Parser, ParserType } from './types.js';
2
+ export { MarkdownItParser } from './markdown-it-parser.js';
3
+ export { PandocParser } from './pandoc-parser.js';
4
+ export { ParserFactory } from './parser-factory.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/parser/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ // src/core/parser/index.ts
2
+ export { MarkdownItParser } from './markdown-it-parser.js';
3
+ export { PandocParser } from './pandoc-parser.js';
4
+ export { ParserFactory } from './parser-factory.js';
@@ -0,0 +1,23 @@
1
+ import { Parser } from './types.js';
2
+ /**
3
+ * Markdown parser using markdown-it library.
4
+ * Provides fast markdown to HTML conversion with GFM support.
5
+ */
6
+ export declare class MarkdownItParser implements Parser {
7
+ readonly name = "markdown-it";
8
+ private md;
9
+ constructor();
10
+ /**
11
+ * Convert markdown to HTML.
12
+ * @param markdown - The markdown content to convert
13
+ * @returns The converted HTML string
14
+ */
15
+ parse(markdown: string): Promise<string>;
16
+ /**
17
+ * Check if the parser is available.
18
+ * markdown-it is always available as it's an npm package.
19
+ * @returns Always returns true
20
+ */
21
+ isAvailable(): Promise<boolean>;
22
+ }
23
+ //# sourceMappingURL=markdown-it-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-it-parser.d.ts","sourceRoot":"","sources":["../../../src/core/parser/markdown-it-parser.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC;;;GAGG;AACH,qBAAa,gBAAiB,YAAW,MAAM;IAC7C,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,OAAO,CAAC,EAAE,CAAa;;IAwBvB;;;;OAIG;IACG,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI9C;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAGtC"}
@@ -0,0 +1,49 @@
1
+ // src/core/parser/markdown-it-parser.ts
2
+ import MarkdownIt from 'markdown-it';
3
+ import hljs from 'highlight.js';
4
+ import strikethrough from 'markdown-it-strikethrough-alt';
5
+ import taskLists from 'markdown-it-task-lists';
6
+ /**
7
+ * Markdown parser using markdown-it library.
8
+ * Provides fast markdown to HTML conversion with GFM support.
9
+ */
10
+ export class MarkdownItParser {
11
+ constructor() {
12
+ this.name = 'markdown-it';
13
+ this.md = new MarkdownIt({
14
+ html: true,
15
+ linkify: true,
16
+ typographer: true,
17
+ highlight: (str, lang) => {
18
+ if (lang && hljs.getLanguage(lang)) {
19
+ try {
20
+ return hljs.highlight(str, { language: lang }).value;
21
+ }
22
+ catch {
23
+ // Ignore highlight errors
24
+ }
25
+ }
26
+ return ''; // Use external default escaping
27
+ },
28
+ });
29
+ // Enable GFM plugins
30
+ this.md.use(strikethrough); // ~~strikethrough~~
31
+ this.md.use(taskLists); // - [ ] task list
32
+ }
33
+ /**
34
+ * Convert markdown to HTML.
35
+ * @param markdown - The markdown content to convert
36
+ * @returns The converted HTML string
37
+ */
38
+ async parse(markdown) {
39
+ return this.md.render(markdown);
40
+ }
41
+ /**
42
+ * Check if the parser is available.
43
+ * markdown-it is always available as it's an npm package.
44
+ * @returns Always returns true
45
+ */
46
+ async isAvailable() {
47
+ return true;
48
+ }
49
+ }
@@ -0,0 +1,27 @@
1
+ import { Parser } from './types.js';
2
+ import { PandocConfig } from '../../config/types.js';
3
+ /**
4
+ * Markdown parser using pandoc.
5
+ * Provides high-quality markdown to HTML conversion with extensive features.
6
+ */
7
+ export declare class PandocParser implements Parser {
8
+ readonly name = "pandoc";
9
+ private config;
10
+ constructor(config?: Partial<PandocConfig>);
11
+ /**
12
+ * Convert markdown to HTML using pandoc.
13
+ * @param markdown - The markdown content to convert
14
+ * @returns The converted HTML string
15
+ */
16
+ parse(markdown: string): Promise<string>;
17
+ /**
18
+ * Check if pandoc is available.
19
+ * @returns true if pandoc is installed and accessible
20
+ */
21
+ isAvailable(): Promise<boolean>;
22
+ /**
23
+ * Build pandoc command arguments from config.
24
+ */
25
+ private buildPandocArgs;
26
+ }
27
+ //# sourceMappingURL=pandoc-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pandoc-parser.d.ts","sourceRoot":"","sources":["../../../src/core/parser/pandoc-parser.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAYrD;;;GAGG;AACH,qBAAa,YAAa,YAAW,MAAM;IACzC,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAI9C;;;;OAIG;IACG,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkB9C;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IASrC;;OAEG;IACH,OAAO,CAAC,eAAe;CA+BxB"}
@@ -0,0 +1,83 @@
1
+ // src/core/parser/pandoc-parser.ts
2
+ import { execSync } from 'child_process';
3
+ /**
4
+ * Default pandoc configuration for high-quality HTML output.
5
+ */
6
+ const DEFAULT_PANDOC_CONFIG = {
7
+ standalone: false,
8
+ toc: false,
9
+ tocDepth: 3,
10
+ highlightStyle: 'pygments',
11
+ };
12
+ /**
13
+ * Markdown parser using pandoc.
14
+ * Provides high-quality markdown to HTML conversion with extensive features.
15
+ */
16
+ export class PandocParser {
17
+ constructor(config = {}) {
18
+ this.name = 'pandoc';
19
+ this.config = { ...DEFAULT_PANDOC_CONFIG, ...config };
20
+ }
21
+ /**
22
+ * Convert markdown to HTML using pandoc.
23
+ * @param markdown - The markdown content to convert
24
+ * @returns The converted HTML string
25
+ */
26
+ async parse(markdown) {
27
+ const pandocArgs = this.buildPandocArgs();
28
+ const command = `pandoc ${pandocArgs.join(' ')}`;
29
+ try {
30
+ const html = execSync(command, {
31
+ encoding: 'utf-8',
32
+ input: markdown,
33
+ maxBuffer: 10 * 1024 * 1024, // 10MB
34
+ });
35
+ return html;
36
+ }
37
+ catch (error) {
38
+ const errorMessage = error instanceof Error ? error.message : String(error);
39
+ throw new Error(`Failed to convert markdown with pandoc: ${errorMessage}`);
40
+ }
41
+ }
42
+ /**
43
+ * Check if pandoc is available.
44
+ * @returns true if pandoc is installed and accessible
45
+ */
46
+ async isAvailable() {
47
+ try {
48
+ execSync('pandoc --version', { stdio: 'pipe' });
49
+ return true;
50
+ }
51
+ catch {
52
+ return false;
53
+ }
54
+ }
55
+ /**
56
+ * Build pandoc command arguments from config.
57
+ */
58
+ buildPandocArgs() {
59
+ const args = [];
60
+ // Basic options
61
+ args.push('--from=markdown');
62
+ args.push('--to=html');
63
+ if (this.config.standalone) {
64
+ args.push('--standalone');
65
+ }
66
+ if (this.config.toc) {
67
+ args.push('--toc');
68
+ if (this.config.tocDepth) {
69
+ args.push(`--toc-depth=${this.config.tocDepth}`);
70
+ }
71
+ }
72
+ if (this.config.highlightStyle) {
73
+ args.push(`--syntax-highlighting=${this.config.highlightStyle}`);
74
+ }
75
+ // Metadata
76
+ if (this.config.metadata) {
77
+ Object.entries(this.config.metadata).forEach(([key, value]) => {
78
+ args.push(`--metadata=${key}:"${value}"`);
79
+ });
80
+ }
81
+ return args;
82
+ }
83
+ }
@@ -0,0 +1,36 @@
1
+ import { Parser, ParserType } from './types.js';
2
+ import { PandocConfig } from '../../config/types.js';
3
+ /**
4
+ * Factory for creating parser instances.
5
+ * Provides methods to create parsers by type and with fallback support.
6
+ */
7
+ export declare class ParserFactory {
8
+ /**
9
+ * Create a parser instance by type.
10
+ * @param type - The type of parser to create
11
+ * @param pandocConfig - Optional configuration for pandoc parser
12
+ * @returns A parser instance
13
+ * @throws Error if the parser type is unknown
14
+ */
15
+ static create(type: ParserType, pandocConfig?: Partial<PandocConfig>): Parser;
16
+ /**
17
+ * Create a parser with fallback support.
18
+ * If the preferred parser is not available, falls back to markdown-it.
19
+ * @param preferred - The preferred parser type
20
+ * @param pandocConfig - Optional configuration for pandoc parser
21
+ * @returns A parser instance that is guaranteed to be available
22
+ * @throws Error if pandoc is preferred but not installed (no silent fallback)
23
+ */
24
+ static createWithFallback(preferred: ParserType, pandocConfig?: Partial<PandocConfig>): Promise<Parser>;
25
+ /**
26
+ * Get the default parser type for dev mode.
27
+ * @returns 'markdown-it' as the default for fast preview
28
+ */
29
+ static getDefaultDevParser(): ParserType;
30
+ /**
31
+ * Get the default parser type for build mode.
32
+ * @returns 'pandoc' as the default for high-quality output
33
+ */
34
+ static getDefaultBuildParser(): ParserType;
35
+ }
36
+ //# sourceMappingURL=parser-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser-factory.d.ts","sourceRoot":"","sources":["../../../src/core/parser/parser-factory.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD;;;GAGG;AACH,qBAAa,aAAa;IACxB;;;;;;OAMG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM;IAa7E;;;;;;;OAOG;WACU,kBAAkB,CAC7B,SAAS,EAAE,UAAU,EACrB,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GACnC,OAAO,CAAC,MAAM,CAAC;IAmBlB;;;OAGG;IACH,MAAM,CAAC,mBAAmB,IAAI,UAAU;IAIxC;;;OAGG;IACH,MAAM,CAAC,qBAAqB,IAAI,UAAU;CAG3C"}
@@ -0,0 +1,63 @@
1
+ // src/core/parser/parser-factory.ts
2
+ import { MarkdownItParser } from './markdown-it-parser.js';
3
+ import { PandocParser } from './pandoc-parser.js';
4
+ /**
5
+ * Factory for creating parser instances.
6
+ * Provides methods to create parsers by type and with fallback support.
7
+ */
8
+ export class ParserFactory {
9
+ /**
10
+ * Create a parser instance by type.
11
+ * @param type - The type of parser to create
12
+ * @param pandocConfig - Optional configuration for pandoc parser
13
+ * @returns A parser instance
14
+ * @throws Error if the parser type is unknown
15
+ */
16
+ static create(type, pandocConfig) {
17
+ switch (type) {
18
+ case 'markdown-it':
19
+ return new MarkdownItParser();
20
+ case 'pandoc':
21
+ return new PandocParser(pandocConfig);
22
+ default:
23
+ // TypeScript exhaustive check
24
+ const _exhaustive = type;
25
+ throw new Error(`Unknown parser type: ${_exhaustive}`);
26
+ }
27
+ }
28
+ /**
29
+ * Create a parser with fallback support.
30
+ * If the preferred parser is not available, falls back to markdown-it.
31
+ * @param preferred - The preferred parser type
32
+ * @param pandocConfig - Optional configuration for pandoc parser
33
+ * @returns A parser instance that is guaranteed to be available
34
+ * @throws Error if pandoc is preferred but not installed (no silent fallback)
35
+ */
36
+ static async createWithFallback(preferred, pandocConfig) {
37
+ const parser = this.create(preferred, pandocConfig);
38
+ if (await parser.isAvailable()) {
39
+ return parser;
40
+ }
41
+ // If pandoc was requested but not available, throw an error
42
+ // (we don't silently fall back to markdown-it for explicit pandoc requests)
43
+ if (preferred === 'pandoc') {
44
+ throw new Error('pandoc is not installed. Please install pandoc or use markdown-it parser.');
45
+ }
46
+ // For markdown-it, it's always available
47
+ return parser;
48
+ }
49
+ /**
50
+ * Get the default parser type for dev mode.
51
+ * @returns 'markdown-it' as the default for fast preview
52
+ */
53
+ static getDefaultDevParser() {
54
+ return 'markdown-it';
55
+ }
56
+ /**
57
+ * Get the default parser type for build mode.
58
+ * @returns 'pandoc' as the default for high-quality output
59
+ */
60
+ static getDefaultBuildParser() {
61
+ return 'pandoc';
62
+ }
63
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Parser interface for markdown to HTML conversion.
3
+ * Both markdown-it and pandoc parsers implement this interface.
4
+ */
5
+ export interface Parser {
6
+ /**
7
+ * Convert markdown content to HTML.
8
+ * @param markdown - The markdown content to convert
9
+ * @returns The converted HTML string
10
+ */
11
+ parse(markdown: string): Promise<string>;
12
+ /**
13
+ * Check if the parser is available for use.
14
+ * @returns true if the parser can be used
15
+ */
16
+ isAvailable(): Promise<boolean>;
17
+ /**
18
+ * The name of the parser.
19
+ */
20
+ readonly name: string;
21
+ }
22
+ /**
23
+ * Available parser types.
24
+ */
25
+ export type ParserType = 'markdown-it' | 'pandoc';
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/parser/types.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzC;;;OAGG;IACH,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ // src/core/parser/types.ts
2
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vimd",
3
- "version": "0.1.12",
3
+ "version": "0.2.0",
4
4
  "description": "Real-time Markdown preview tool with pandoc (view markdown)",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -51,6 +51,7 @@
51
51
  "devDependencies": {
52
52
  "@types/fs-extra": "^11.0.4",
53
53
  "@types/inquirer": "^9.0.9",
54
+ "@types/markdown-it": "^14.1.2",
54
55
  "@types/node": "^20.19.25",
55
56
  "@typescript-eslint/eslint-plugin": "^6.21.0",
56
57
  "@typescript-eslint/parser": "^6.21.0",
@@ -67,8 +68,12 @@
67
68
  "commander": "^12.1.0",
68
69
  "fs-extra": "^11.3.2",
69
70
  "github-markdown-css": "^5.8.1",
71
+ "highlight.js": "^11.11.1",
70
72
  "inquirer": "^9.3.8",
71
73
  "live-server": "^1.2.2",
74
+ "markdown-it": "^14.1.0",
75
+ "markdown-it-strikethrough-alt": "^1.0.0",
76
+ "markdown-it-task-lists": "^2.1.1",
72
77
  "open": "^9.1.0"
73
78
  }
74
79
  }