md-review 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -0
- package/bin/md-review.js +170 -0
- package/dist/assets/index-BIHwAaLg.js +87 -0
- package/dist/assets/index-D1IQM189.css +10 -0
- package/dist/index.html +13 -0
- package/package.json +58 -0
- package/server/index.js +135 -0
package/README.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# md-preview
|
|
2
|
+
|
|
3
|
+
ローカルのMarkdownファイルをブラウザで見やすくプレビューするCLIツール
|
|
4
|
+
|
|
5
|
+
## 特徴
|
|
6
|
+
|
|
7
|
+
- 🎨 GitHub風の見やすいデザイン
|
|
8
|
+
- 🌈 シンタックスハイライト対応(highlight.js)
|
|
9
|
+
- ✅ GitHub Flavored Markdown (GFM) サポート
|
|
10
|
+
- テーブル
|
|
11
|
+
- タスクリスト
|
|
12
|
+
- 取り消し線
|
|
13
|
+
- 📁 **ファイルツリー表示** - カレントディレクトリ内の全Markdownファイルを一覧表示
|
|
14
|
+
- 🗂️ **2カラムレイアウト** - 左側にツリー、右側にプレビュー
|
|
15
|
+
- ⚡ 高速な起動(Vite)
|
|
16
|
+
- 🚀 軽量なAPIサーバー(Hono)
|
|
17
|
+
- 📦 TypeScript + React 19
|
|
18
|
+
|
|
19
|
+
## インストール
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# 依存パッケージのインストール
|
|
23
|
+
pnpm install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 使い方
|
|
27
|
+
|
|
28
|
+
md-previewには**2つのモード**があります:
|
|
29
|
+
|
|
30
|
+
### 1. 開発モード(推奨)
|
|
31
|
+
|
|
32
|
+
カレントディレクトリ内の全Markdownファイルをツリー表示し、選択してプレビューできます。
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# APIサーバーを起動
|
|
36
|
+
node server/index.js &
|
|
37
|
+
|
|
38
|
+
# 開発サーバーを起動
|
|
39
|
+
pnpm run dev
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
または、両方同時に起動:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# APIサーバーをバックグラウンドで起動
|
|
46
|
+
node server/index.js &
|
|
47
|
+
|
|
48
|
+
# Viteサーバーを起動(http://localhost:6060 が自動で開きます)
|
|
49
|
+
pnpm run dev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
ブラウザで `http://localhost:6060` を開くと、以下のようなUIが表示されます:
|
|
53
|
+
- **左側**: ファイルツリー(カレントディレクトリ内の全Markdownファイル:.md、.markdown)
|
|
54
|
+
- **右側**: 選択されたMarkdownファイルのプレビュー
|
|
55
|
+
|
|
56
|
+
### 2. CLI モード
|
|
57
|
+
|
|
58
|
+
特定のMarkdownファイルのみをプレビューします。
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
node bin/md-preview.js <markdown-file-path>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### 例
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# サンプルファイルをプレビュー
|
|
68
|
+
node bin/md-preview.js test-samples/sample.md
|
|
69
|
+
|
|
70
|
+
# 任意のMarkdownファイルをプレビュー
|
|
71
|
+
node bin/md-preview.js ./docs/README.md
|
|
72
|
+
node bin/md-preview.js ~/Documents/notes.md
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### オプション
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# ポート番号を指定
|
|
79
|
+
node bin/md-preview.js --port 8080 --api-port 3000 file.md
|
|
80
|
+
|
|
81
|
+
# ブラウザを自動的に開かない
|
|
82
|
+
node bin/md-preview.js --no-open file.md
|
|
83
|
+
|
|
84
|
+
# ヘルプを表示
|
|
85
|
+
node bin/md-preview.js --help
|
|
86
|
+
|
|
87
|
+
# バージョンを表示
|
|
88
|
+
node bin/md-preview.js --version
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## オプション一覧
|
|
92
|
+
|
|
93
|
+
| オプション | 短縮形 | デフォルト | 説明 |
|
|
94
|
+
|-----------|--------|-----------|------|
|
|
95
|
+
| `--port` | `-p` | `6060` | Viteサーバーのポート番号 |
|
|
96
|
+
| `--api-port` | - | `3030` | APIサーバーのポート番号 |
|
|
97
|
+
| `--no-open` | - | - | ブラウザを自動的に開かない |
|
|
98
|
+
| `--help` | `-h` | - | ヘルプを表示 |
|
|
99
|
+
| `--version` | `-v` | - | バージョンを表示 |
|
|
100
|
+
|
|
101
|
+
## 起動の流れ
|
|
102
|
+
|
|
103
|
+
1. CLIコマンドを実行すると、以下のサーバーが起動します:
|
|
104
|
+
- **APIサーバー(Hono)**: `http://localhost:3030` - Markdownファイルを読み込むAPI
|
|
105
|
+
- **Viteサーバー**: `http://localhost:6060` - Reactアプリケーション
|
|
106
|
+
|
|
107
|
+
2. 自動的にブラウザで `http://localhost:6060` が開き、Markdownファイルが表示されます
|
|
108
|
+
|
|
109
|
+
3. 終了するには `Ctrl+C` を押してください
|
|
110
|
+
|
|
111
|
+
## 技術スタック
|
|
112
|
+
|
|
113
|
+
### フロントエンド
|
|
114
|
+
- **React** 19 - UIライブラリ
|
|
115
|
+
- **TypeScript** - 型安全な開発
|
|
116
|
+
- **Vite** - 高速な開発サーバー
|
|
117
|
+
- **react-markdown** - Markdownレンダリング
|
|
118
|
+
- **remark-gfm** - GFM記法サポート
|
|
119
|
+
- **rehype-highlight** - シンタックスハイライト
|
|
120
|
+
- **highlight.js** - コードハイライトライブラリ
|
|
121
|
+
|
|
122
|
+
### バックエンド
|
|
123
|
+
- **Hono** - 高速で軽量なWebフレームワーク
|
|
124
|
+
- **@hono/node-server** - Node.js用アダプター
|
|
125
|
+
|
|
126
|
+
### CLI
|
|
127
|
+
- **commander** - コマンドライン引数のパース
|
|
128
|
+
- **chalk** - ターミナル出力の色付け
|
|
129
|
+
- **open** - ブラウザを開く
|
|
130
|
+
|
|
131
|
+
## プロジェクト構成
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
md-preview/
|
|
135
|
+
├── bin/
|
|
136
|
+
│ └── md-preview.js # CLI エントリーポイント
|
|
137
|
+
├── server/
|
|
138
|
+
│ └── index.js # Hono APIサーバー
|
|
139
|
+
├── src/
|
|
140
|
+
│ ├── components/
|
|
141
|
+
│ │ ├── ErrorDisplay.tsx # エラー表示
|
|
142
|
+
│ │ └── MarkdownPreview.tsx # Markdownプレビュー
|
|
143
|
+
│ ├── hooks/
|
|
144
|
+
│ │ └── useMarkdown.ts # Markdown取得フック
|
|
145
|
+
│ ├── styles/
|
|
146
|
+
│ │ └── markdown.css # Markdownスタイル
|
|
147
|
+
│ ├── App.tsx
|
|
148
|
+
│ ├── main.tsx
|
|
149
|
+
│ └── index.css
|
|
150
|
+
├── test-samples/
|
|
151
|
+
│ └── sample.md # テスト用サンプル
|
|
152
|
+
├── index.html
|
|
153
|
+
├── vite.config.ts
|
|
154
|
+
├── tsconfig.json
|
|
155
|
+
└── package.json
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## サポートするMarkdown記法
|
|
159
|
+
|
|
160
|
+
### 基本記法
|
|
161
|
+
- 見出し (h1-h6)
|
|
162
|
+
- 段落
|
|
163
|
+
- 強調 (**太字**, *斜体*)
|
|
164
|
+
- リスト(順序付き/順序なし)
|
|
165
|
+
- インラインコード
|
|
166
|
+
- コードブロック(シンタックスハイライト付き)
|
|
167
|
+
- リンク
|
|
168
|
+
- 引用
|
|
169
|
+
- 水平線
|
|
170
|
+
|
|
171
|
+
### GFM拡張記法
|
|
172
|
+
- テーブル
|
|
173
|
+
- タスクリスト
|
|
174
|
+
- 取り消し線 (~~text~~)
|
|
175
|
+
|
|
176
|
+
## 開発
|
|
177
|
+
|
|
178
|
+
### 開発サーバーの起動
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Vite開発サーバーのみ起動
|
|
182
|
+
pnpm run dev
|
|
183
|
+
|
|
184
|
+
# APIサーバーのみ起動
|
|
185
|
+
pnpm run server
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### ビルド
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
pnpm run build
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## トラブルシューティング
|
|
195
|
+
|
|
196
|
+
### ポートが既に使用されている
|
|
197
|
+
|
|
198
|
+
デフォルトのポート(6060, 3030)が既に使用されている場合は、別のポートを指定してください:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
node bin/md-preview.js --port 8080 --api-port 3000 file.md
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### ブラウザが自動的に開かない
|
|
205
|
+
|
|
206
|
+
`--no-open` オプションを付けずに実行してください。または、手動で以下のURLを開いてください:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
http://localhost:6060
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Markdownが表示されない
|
|
213
|
+
|
|
214
|
+
1. APIサーバーが正常に起動しているか確認してください(`http://localhost:3030/api/health` にアクセス)
|
|
215
|
+
2. ファイルパスが正しいか確認してください
|
|
216
|
+
3. ファイルが読み取り可能か確認してください
|
|
217
|
+
|
|
218
|
+
## ライセンス
|
|
219
|
+
|
|
220
|
+
MIT
|
package/bin/md-review.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import { resolve, dirname } from 'path';
|
|
5
|
+
import { existsSync, readFileSync } from 'fs';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import mri from 'mri';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
const packageRoot = resolve(__dirname, '..');
|
|
12
|
+
|
|
13
|
+
const pkg = JSON.parse(readFileSync(resolve(packageRoot, 'package.json'), 'utf-8'));
|
|
14
|
+
|
|
15
|
+
const SERVER_READY_MESSAGE = 'md-review server started';
|
|
16
|
+
|
|
17
|
+
// Port validation function
|
|
18
|
+
function validatePort(value, name) {
|
|
19
|
+
const port = parseInt(value, 10);
|
|
20
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
21
|
+
console.error(`Error: Invalid ${name}: ${value}. Must be between 1 and 65535`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
return port;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check if file has markdown extension
|
|
28
|
+
function isMarkdownFile(filePath) {
|
|
29
|
+
return filePath.endsWith('.md') || filePath.endsWith('.markdown');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Parse arguments
|
|
33
|
+
const args = mri(process.argv.slice(2), {
|
|
34
|
+
alias: {
|
|
35
|
+
p: 'port',
|
|
36
|
+
h: 'help',
|
|
37
|
+
v: 'version'
|
|
38
|
+
},
|
|
39
|
+
default: {
|
|
40
|
+
port: '6060',
|
|
41
|
+
'api-port': '3030',
|
|
42
|
+
open: true
|
|
43
|
+
},
|
|
44
|
+
boolean: ['help', 'version', 'open']
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Help message
|
|
48
|
+
if (args.help) {
|
|
49
|
+
console.log(`
|
|
50
|
+
md-review - Review and annotate Markdown files with comments
|
|
51
|
+
|
|
52
|
+
Usage:
|
|
53
|
+
md-review [options] Start in dev mode (browse all markdown files)
|
|
54
|
+
md-review <file> [options] Preview a specific markdown file (.md or .markdown)
|
|
55
|
+
|
|
56
|
+
Options:
|
|
57
|
+
-p, --port <port> Vite server port (default: 6060)
|
|
58
|
+
--api-port <port> API server port (default: 3030)
|
|
59
|
+
--no-open Do not open browser automatically
|
|
60
|
+
-h, --help Show this help message
|
|
61
|
+
-v, --version Show version number
|
|
62
|
+
|
|
63
|
+
Examples:
|
|
64
|
+
md-review Start dev mode in current directory
|
|
65
|
+
md-review README.md Preview README.md
|
|
66
|
+
md-review docs/guide.md --port 8080
|
|
67
|
+
`);
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Version
|
|
72
|
+
if (args.version) {
|
|
73
|
+
console.log(pkg.version);
|
|
74
|
+
process.exit(0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const file = args._[0];
|
|
78
|
+
const port = validatePort(args.port, 'port');
|
|
79
|
+
const apiPort = validatePort(args['api-port'], 'api-port');
|
|
80
|
+
const shouldOpen = args.open;
|
|
81
|
+
|
|
82
|
+
// Set environment variables
|
|
83
|
+
process.env.API_PORT = apiPort;
|
|
84
|
+
process.env.VITE_PORT = port;
|
|
85
|
+
|
|
86
|
+
// If file is specified, validate it
|
|
87
|
+
if (file) {
|
|
88
|
+
const filePath = resolve(file);
|
|
89
|
+
|
|
90
|
+
if (!existsSync(filePath)) {
|
|
91
|
+
console.error(`Error: File not found: ${filePath}`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!isMarkdownFile(filePath)) {
|
|
96
|
+
console.error(`Error: File must have .md or .markdown extension: ${filePath}`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
process.env.MARKDOWN_FILE_PATH = filePath;
|
|
101
|
+
console.log(`File: ${filePath}`);
|
|
102
|
+
} else {
|
|
103
|
+
// Dev mode - browse all markdown files
|
|
104
|
+
process.env.BASE_DIR = process.cwd();
|
|
105
|
+
console.log(`Directory: ${process.cwd()}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log('Starting md-review...');
|
|
109
|
+
console.log(` API Port: ${apiPort}`);
|
|
110
|
+
console.log(` Vite Port: ${port}`);
|
|
111
|
+
|
|
112
|
+
// Start API server
|
|
113
|
+
const apiProcess = spawn('node', ['server/index.js'], {
|
|
114
|
+
cwd: packageRoot,
|
|
115
|
+
stdio: ['inherit', 'pipe', 'inherit'],
|
|
116
|
+
env: process.env
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
let viteProcess = null;
|
|
120
|
+
let serverReady = false;
|
|
121
|
+
|
|
122
|
+
// Wait for API server to be ready before starting Vite
|
|
123
|
+
apiProcess.stdout.on('data', (data) => {
|
|
124
|
+
process.stdout.write(data);
|
|
125
|
+
const output = data.toString();
|
|
126
|
+
|
|
127
|
+
if (!serverReady && output.includes(SERVER_READY_MESSAGE)) {
|
|
128
|
+
serverReady = true;
|
|
129
|
+
console.log('Starting Vite dev server...');
|
|
130
|
+
|
|
131
|
+
viteProcess = spawn('node', [
|
|
132
|
+
'node_modules/vite/bin/vite.js',
|
|
133
|
+
'--port', port,
|
|
134
|
+
...(shouldOpen ? ['--open'] : [])
|
|
135
|
+
], {
|
|
136
|
+
cwd: packageRoot,
|
|
137
|
+
stdio: 'inherit',
|
|
138
|
+
env: process.env
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
viteProcess.on('error', (err) => {
|
|
142
|
+
console.error('Vite server error:', err.message);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Handle graceful shutdown
|
|
148
|
+
const shutdown = () => {
|
|
149
|
+
console.log('\nShutting down...');
|
|
150
|
+
apiProcess.kill('SIGINT');
|
|
151
|
+
viteProcess?.kill('SIGINT');
|
|
152
|
+
process.exit(0);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
process.on('SIGINT', shutdown);
|
|
156
|
+
process.on('SIGTERM', shutdown);
|
|
157
|
+
|
|
158
|
+
// Handle API server exit
|
|
159
|
+
apiProcess.on('exit', (code) => {
|
|
160
|
+
if (code !== 0 && code !== null) {
|
|
161
|
+
console.error(`API server exited with code ${code}`);
|
|
162
|
+
}
|
|
163
|
+
viteProcess?.kill('SIGINT');
|
|
164
|
+
process.exit(code || 0);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
apiProcess.on('error', (err) => {
|
|
168
|
+
console.error('Failed to start API server:', err.message);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
});
|