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 +110 -193
- package/dist/cli/commands/build.d.ts +1 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +19 -10
- package/dist/cli/commands/dev.d.ts +1 -0
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +18 -10
- package/dist/cli/index.js +2 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +2 -0
- package/dist/config/types.d.ts +7 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/core/converter.d.ts +18 -0
- package/dist/core/converter.d.ts.map +1 -1
- package/dist/core/converter.js +30 -1
- package/dist/core/pandoc-detector.d.ts.map +1 -1
- package/dist/core/pandoc-detector.js +7 -2
- package/dist/core/parser/index.d.ts +5 -0
- package/dist/core/parser/index.d.ts.map +1 -0
- package/dist/core/parser/index.js +4 -0
- package/dist/core/parser/markdown-it-parser.d.ts +23 -0
- package/dist/core/parser/markdown-it-parser.d.ts.map +1 -0
- package/dist/core/parser/markdown-it-parser.js +49 -0
- package/dist/core/parser/pandoc-parser.d.ts +27 -0
- package/dist/core/parser/pandoc-parser.d.ts.map +1 -0
- package/dist/core/parser/pandoc-parser.js +83 -0
- package/dist/core/parser/parser-factory.d.ts +36 -0
- package/dist/core/parser/parser-factory.d.ts.map +1 -0
- package/dist/core/parser/parser-factory.js +63 -0
- package/dist/core/parser/types.d.ts +26 -0
- package/dist/core/parser/types.d.ts.map +1 -0
- package/dist/core/parser/types.js +2 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -2,128 +2,128 @@
|
|
|
2
2
|
|
|
3
3
|
🌐 [English](README-en.md) | 日本語
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> 書きながら見る。Markdownプレビュー
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/vimd)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://nodejs.org/)
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
---
|
|
11
12
|
|
|
12
|
-
##
|
|
13
|
+
## デモ
|
|
13
14
|
|
|
14
|
-
|
|
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
|
+

|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
---
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
npm install -g vimd
|
|
25
|
-
```
|
|
19
|
+
## テーマ
|
|
26
20
|
|
|
27
|
-
|
|
21
|
+
<details open>
|
|
22
|
+
<summary><strong>GitHub</strong> (デフォルト)</summary>
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+

|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
- **pandoc** >= 2.0 (別途インストールが必要)
|
|
26
|
+
</details>
|
|
33
27
|
|
|
34
|
-
|
|
28
|
+
<details>
|
|
29
|
+
<summary><strong>Dark</strong></summary>
|
|
35
30
|
|
|
36
|
-
|
|
37
|
-
# macOS
|
|
38
|
-
brew install pandoc
|
|
31
|
+

|
|
39
32
|
|
|
40
|
-
|
|
41
|
-
sudo apt install pandoc
|
|
33
|
+
</details>
|
|
42
34
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
```
|
|
35
|
+
<details>
|
|
36
|
+
<summary><strong>Academic</strong></summary>
|
|
46
37
|
|
|
47
|
-
|
|
38
|
+

|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
# ライブプレビューを開始
|
|
51
|
-
vimd dev draft.md
|
|
40
|
+
</details>
|
|
52
41
|
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
<details>
|
|
43
|
+
<summary><strong>Minimal</strong></summary>
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
vimd theme
|
|
45
|
+

|
|
58
46
|
|
|
59
|
-
|
|
60
|
-
vimd config
|
|
61
|
-
```
|
|
47
|
+
</details>
|
|
62
48
|
|
|
63
|
-
|
|
49
|
+
<details>
|
|
50
|
+
<summary><strong>Technical</strong></summary>
|
|
64
51
|
|
|
65
|
-
|
|
52
|
+

|
|
66
53
|
|
|
67
|
-
|
|
54
|
+
</details>
|
|
68
55
|
|
|
69
|
-
|
|
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
|
-
|
|
78
|
-
- `-t, --theme <theme>`: テーマ名 (グローバル設定を上書き)
|
|
79
|
-
- `--no-open`: ブラウザを自動で開かない
|
|
60
|
+
### 必要要件
|
|
80
61
|
|
|
81
|
-
|
|
62
|
+
- **Node.js** >= 18.0.0
|
|
63
|
+
- **pandoc** >= 2.0(オプション、高品質ビルド時のみ)
|
|
82
64
|
|
|
83
|
-
|
|
65
|
+
### インストール
|
|
84
66
|
|
|
85
67
|
```bash
|
|
86
|
-
|
|
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
|
-
|
|
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
|
-
|
|
81
|
+
### 使い方
|
|
99
82
|
|
|
100
83
|
```bash
|
|
101
|
-
|
|
102
|
-
|
|
84
|
+
# ライブプレビューを開始(pandoc不要、高速)
|
|
85
|
+
vimd dev draft.md
|
|
103
86
|
|
|
104
|
-
|
|
87
|
+
# 静的HTMLを生成(pandoc使用、高品質)
|
|
88
|
+
vimd build draft.md
|
|
105
89
|
|
|
106
|
-
|
|
90
|
+
# 高速ビルド(pandoc不要)
|
|
91
|
+
vimd build draft.md --fast
|
|
107
92
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
vimd config
|
|
93
|
+
# テーマを変更
|
|
94
|
+
vimd theme
|
|
111
95
|
|
|
112
|
-
#
|
|
113
|
-
vimd config
|
|
96
|
+
# 設定を編集
|
|
97
|
+
vimd config
|
|
114
98
|
```
|
|
115
99
|
|
|
116
|
-
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## コマンド
|
|
117
103
|
|
|
118
|
-
|
|
104
|
+
| コマンド | 説明 |
|
|
105
|
+
|---------|------|
|
|
106
|
+
| `vimd dev <file>` | ライブプレビューサーバーを起動 |
|
|
107
|
+
| `vimd build <file>` | 静的HTMLを生成 |
|
|
108
|
+
| `vimd theme` | テーマを対話的に変更 |
|
|
109
|
+
| `vimd config` | 設定を対話的に編集 |
|
|
119
110
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
139
|
-
|
|
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
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
|
|
151
|
+
---
|
|
227
152
|
|
|
228
|
-
|
|
153
|
+
## Why vimd?
|
|
229
154
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
166
|
+
## ドキュメント
|
|
237
167
|
|
|
238
|
-
|
|
239
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"
|
|
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.
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
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);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dev.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/cli/commands/dev.js
CHANGED
|
@@ -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.
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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,
|
|
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"}
|
package/dist/config/defaults.js
CHANGED
package/dist/config/types.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/core/converter.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/core/converter.js
CHANGED
|
@@ -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(`--
|
|
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;
|
|
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('
|
|
30
|
-
console.error('
|
|
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 @@
|
|
|
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,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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vimd",
|
|
3
|
-
"version": "0.
|
|
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
|
}
|