vimd 0.2.0 → 0.2.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 +7 -6
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +10 -5
- package/dist/cli/commands/kill.d.ts +7 -0
- package/dist/cli/commands/kill.d.ts.map +1 -0
- package/dist/cli/commands/kill.js +110 -0
- package/dist/cli/index.js +9 -1
- package/dist/config/defaults.js +1 -1
- package/dist/core/server.d.ts +8 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +32 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -146,7 +146,7 @@ export default {
|
|
|
146
146
|
| `markdown-it` | 高速、pandoc不要 | 開発時のプレビュー |
|
|
147
147
|
| `pandoc` | 高品質、多機能 | 最終出力の生成 |
|
|
148
148
|
|
|
149
|
-
詳細な設定オプションは [docs/api.md](docs/api.md) を参照してください。
|
|
149
|
+
詳細な設定オプションは [docs/ja/api.md](docs/ja/api.md) を参照してください。
|
|
150
150
|
|
|
151
151
|
---
|
|
152
152
|
|
|
@@ -165,11 +165,12 @@ export default {
|
|
|
165
165
|
|
|
166
166
|
## ドキュメント
|
|
167
167
|
|
|
168
|
-
- [開発ガイド](docs/development.md) - 開発環境構築
|
|
169
|
-
- [アーキテクチャ](docs/architecture.md) - プロジェクト構造
|
|
170
|
-
- [APIリファレンス](docs/api.md) - 詳細なオプション
|
|
171
|
-
- [テスト](docs/testing.md) - テスト構成
|
|
172
|
-
- [トラブルシューティング](docs/troubleshooting.md) - よくある問題
|
|
168
|
+
- [開発ガイド](docs/ja/development.md) - 開発環境構築
|
|
169
|
+
- [アーキテクチャ](docs/ja/architecture.md) - プロジェクト構造
|
|
170
|
+
- [APIリファレンス](docs/ja/api.md) - 詳細なオプション
|
|
171
|
+
- [テスト](docs/ja/testing.md) - テスト構成
|
|
172
|
+
- [トラブルシューティング](docs/ja/troubleshooting.md) - よくある問題
|
|
173
|
+
- [v0.2.0 リリースノート](docs/ja/releases/v0.2.0.md) - Dual Parser System
|
|
173
174
|
|
|
174
175
|
---
|
|
175
176
|
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,CA6Jf"}
|
package/dist/cli/commands/dev.js
CHANGED
|
@@ -87,11 +87,16 @@ export async function devCommand(filePath, options) {
|
|
|
87
87
|
open: config.open,
|
|
88
88
|
root: sourceDir,
|
|
89
89
|
});
|
|
90
|
-
await server.start(htmlPath);
|
|
91
|
-
//
|
|
90
|
+
const startResult = await server.start(htmlPath);
|
|
91
|
+
// Update port if live-server used a different one
|
|
92
|
+
const actualPort = startResult.actualPort;
|
|
93
|
+
if (startResult.portChanged) {
|
|
94
|
+
port = actualPort;
|
|
95
|
+
}
|
|
96
|
+
// 12. Save session with actual port
|
|
92
97
|
await SessionManager.saveSession({
|
|
93
98
|
pid: process.pid,
|
|
94
|
-
port:
|
|
99
|
+
port: actualPort,
|
|
95
100
|
htmlPath: htmlPath,
|
|
96
101
|
sourcePath: absolutePath,
|
|
97
102
|
startedAt: new Date().toISOString(),
|
|
@@ -128,8 +133,8 @@ export async function devCommand(filePath, options) {
|
|
|
128
133
|
catch {
|
|
129
134
|
// Ignore errors when removing file
|
|
130
135
|
}
|
|
131
|
-
// Remove session from registry
|
|
132
|
-
await SessionManager.removeSession(
|
|
136
|
+
// Remove session from registry (use actual port)
|
|
137
|
+
await SessionManager.removeSession(actualPort);
|
|
133
138
|
Logger.info('Cleanup complete');
|
|
134
139
|
});
|
|
135
140
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kill.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/kill.ts"],"names":[],"mappings":"AAQA,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAsDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyErE"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// src/cli/commands/kill.ts
|
|
2
|
+
import { SessionManager } from '../../utils/session-manager.js';
|
|
3
|
+
import { Logger } from '../../utils/logger.js';
|
|
4
|
+
import { exec } from 'child_process';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
/**
|
|
8
|
+
* Check if a PID belongs to a vimd/node process
|
|
9
|
+
*/
|
|
10
|
+
async function isVimdProcess(pid) {
|
|
11
|
+
try {
|
|
12
|
+
const { stdout } = await execAsync(`ps -p ${pid} -o comm=`);
|
|
13
|
+
const processName = stdout.trim().toLowerCase();
|
|
14
|
+
return processName.includes('node') || processName.includes('vimd');
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Process doesn't exist
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Kill a single session with validation
|
|
23
|
+
*/
|
|
24
|
+
async function killSession(session) {
|
|
25
|
+
const result = {
|
|
26
|
+
port: session.port,
|
|
27
|
+
pid: session.pid,
|
|
28
|
+
killed: false,
|
|
29
|
+
htmlRemoved: false,
|
|
30
|
+
};
|
|
31
|
+
// Check if process is alive
|
|
32
|
+
if (!SessionManager.isProcessAlive(session.pid)) {
|
|
33
|
+
result.reason = 'Process already dead';
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
// Validate that this is a vimd process (PID safety check)
|
|
37
|
+
const isVimd = await isVimdProcess(session.pid);
|
|
38
|
+
if (!isVimd) {
|
|
39
|
+
result.reason = 'PID reused by another process';
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
// Kill the process
|
|
43
|
+
result.killed = await SessionManager.killProcess(session.pid);
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
export async function killCommand(options) {
|
|
47
|
+
try {
|
|
48
|
+
// Clean up dead sessions first
|
|
49
|
+
const deadCleaned = await SessionManager.cleanDeadSessions();
|
|
50
|
+
if (deadCleaned > 0) {
|
|
51
|
+
Logger.info(`Cleaned ${deadCleaned} dead session(s)`);
|
|
52
|
+
}
|
|
53
|
+
// Load all sessions
|
|
54
|
+
const sessions = await SessionManager.loadSessions();
|
|
55
|
+
const sessionList = Object.values(sessions);
|
|
56
|
+
if (sessionList.length === 0) {
|
|
57
|
+
Logger.info('No active sessions found');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Filter sessions if --port is specified
|
|
61
|
+
let targetSessions;
|
|
62
|
+
if (options.port) {
|
|
63
|
+
const port = parseInt(options.port, 10);
|
|
64
|
+
const session = sessions[port.toString()];
|
|
65
|
+
if (!session) {
|
|
66
|
+
Logger.warn(`No session found on port ${port}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
targetSessions = [session];
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Kill all sessions (default behavior, same as --all)
|
|
73
|
+
targetSessions = sessionList;
|
|
74
|
+
}
|
|
75
|
+
Logger.info(`Found ${targetSessions.length} active session(s)`);
|
|
76
|
+
// Kill each session
|
|
77
|
+
const results = [];
|
|
78
|
+
let htmlRemovedCount = 0;
|
|
79
|
+
for (const session of targetSessions) {
|
|
80
|
+
const result = await killSession(session);
|
|
81
|
+
// Remove HTML file regardless of kill result
|
|
82
|
+
const cleanupResult = await SessionManager.cleanupSessionOnPort(session.port);
|
|
83
|
+
result.htmlRemoved = cleanupResult.htmlRemoved;
|
|
84
|
+
if (result.htmlRemoved) {
|
|
85
|
+
htmlRemovedCount++;
|
|
86
|
+
}
|
|
87
|
+
results.push(result);
|
|
88
|
+
// Log result
|
|
89
|
+
if (result.killed) {
|
|
90
|
+
Logger.success(`Killed session on port ${result.port} (PID: ${result.pid})`);
|
|
91
|
+
}
|
|
92
|
+
else if (result.reason) {
|
|
93
|
+
Logger.info(`Port ${result.port}: ${result.reason}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Summary
|
|
97
|
+
const killedCount = results.filter((r) => r.killed).length;
|
|
98
|
+
if (killedCount > 0 || htmlRemovedCount > 0) {
|
|
99
|
+
if (htmlRemovedCount > 0) {
|
|
100
|
+
Logger.success(`Removed ${htmlRemovedCount} preview file(s)`);
|
|
101
|
+
}
|
|
102
|
+
Logger.success('All sessions terminated');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
107
|
+
Logger.error(`Failed to kill sessions: ${errorMessage}`);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { devCommand } from './commands/dev.js';
|
|
|
5
5
|
import { buildCommand } from './commands/build.js';
|
|
6
6
|
import { themeCommand } from './commands/theme.js';
|
|
7
7
|
import { configCommand } from './commands/config.js';
|
|
8
|
+
import { killCommand } from './commands/kill.js';
|
|
8
9
|
const require = createRequire(import.meta.url);
|
|
9
10
|
const packageJson = require('../../package.json');
|
|
10
11
|
const program = new Command();
|
|
@@ -16,7 +17,7 @@ program
|
|
|
16
17
|
program
|
|
17
18
|
.command('dev <file>')
|
|
18
19
|
.description('Start live preview server')
|
|
19
|
-
.option('-p, --port <port>', 'Port number'
|
|
20
|
+
.option('-p, --port <port>', 'Port number')
|
|
20
21
|
.option('-t, --theme <theme>', 'Theme name')
|
|
21
22
|
.option('--no-open', 'Do not open browser automatically')
|
|
22
23
|
.option('--pandoc', 'Use pandoc parser instead of markdown-it')
|
|
@@ -40,4 +41,11 @@ program
|
|
|
40
41
|
.description('Edit configuration interactively')
|
|
41
42
|
.option('-l, --list', 'List current configuration')
|
|
42
43
|
.action(configCommand);
|
|
44
|
+
// vimd kill
|
|
45
|
+
program
|
|
46
|
+
.command('kill')
|
|
47
|
+
.description('Kill vimd dev sessions')
|
|
48
|
+
.option('--all', 'Kill all sessions (default)')
|
|
49
|
+
.option('--port <port>', 'Kill session on specific port')
|
|
50
|
+
.action(killCommand);
|
|
43
51
|
program.parse(process.argv);
|
package/dist/config/defaults.js
CHANGED
package/dist/core/server.d.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { ServerConfig } from '../config/types.js';
|
|
2
|
+
export interface ServerStartResult {
|
|
3
|
+
actualPort: number;
|
|
4
|
+
requestedPort: number;
|
|
5
|
+
portChanged: boolean;
|
|
6
|
+
}
|
|
2
7
|
export declare class LiveServer {
|
|
3
8
|
private config;
|
|
4
9
|
private running;
|
|
10
|
+
private actualPort;
|
|
5
11
|
constructor(config: ServerConfig);
|
|
6
|
-
start(htmlPath: string): Promise<
|
|
12
|
+
start(htmlPath: string): Promise<ServerStartResult>;
|
|
7
13
|
stop(): Promise<void>;
|
|
8
14
|
openBrowser(url: string): Promise<void>;
|
|
9
15
|
getURL(): string;
|
|
16
|
+
getActualPort(): number;
|
|
10
17
|
}
|
|
11
18
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/core/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/core/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,UAAU;IAIT,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEP,MAAM,EAAE,YAAY;IAIlC,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA8DnD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7C,MAAM,IAAI,MAAM;IAIhB,aAAa,IAAI,MAAM;CAGxB"}
|
package/dist/core/server.js
CHANGED
|
@@ -7,6 +7,7 @@ export class LiveServer {
|
|
|
7
7
|
constructor(config) {
|
|
8
8
|
this.config = config;
|
|
9
9
|
this.running = false;
|
|
10
|
+
this.actualPort = config.port;
|
|
10
11
|
}
|
|
11
12
|
async start(htmlPath) {
|
|
12
13
|
const root = path.dirname(htmlPath);
|
|
@@ -22,13 +23,38 @@ export class LiveServer {
|
|
|
22
23
|
watch: [root], // explicitly watch the root directory
|
|
23
24
|
};
|
|
24
25
|
try {
|
|
25
|
-
liveServer.start(params);
|
|
26
|
+
const server = liveServer.start(params);
|
|
27
|
+
// Wait for server to start and get actual port
|
|
28
|
+
const actualPort = await new Promise((resolve, reject) => {
|
|
29
|
+
const timeout = setTimeout(() => {
|
|
30
|
+
reject(new Error('Server start timeout'));
|
|
31
|
+
}, 10000);
|
|
32
|
+
server.addListener('listening', () => {
|
|
33
|
+
clearTimeout(timeout);
|
|
34
|
+
const address = server.address();
|
|
35
|
+
resolve(address.port);
|
|
36
|
+
});
|
|
37
|
+
server.addListener('error', (err) => {
|
|
38
|
+
clearTimeout(timeout);
|
|
39
|
+
reject(err);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
this.actualPort = actualPort;
|
|
26
43
|
this.running = true;
|
|
27
|
-
const
|
|
44
|
+
const portChanged = actualPort !== this.config.port;
|
|
45
|
+
const url = `http://${this.config.host}:${actualPort}`;
|
|
46
|
+
if (portChanged) {
|
|
47
|
+
Logger.warn(`Port ${this.config.port} was unavailable, using port ${actualPort}`);
|
|
48
|
+
}
|
|
28
49
|
Logger.success(`Server started at ${url}`);
|
|
29
50
|
if (this.config.open) {
|
|
30
51
|
await this.openBrowser(url);
|
|
31
52
|
}
|
|
53
|
+
return {
|
|
54
|
+
actualPort,
|
|
55
|
+
requestedPort: this.config.port,
|
|
56
|
+
portChanged,
|
|
57
|
+
};
|
|
32
58
|
}
|
|
33
59
|
catch (error) {
|
|
34
60
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -53,6 +79,9 @@ export class LiveServer {
|
|
|
53
79
|
}
|
|
54
80
|
}
|
|
55
81
|
getURL() {
|
|
56
|
-
return `http://${this.config.host}:${this.
|
|
82
|
+
return `http://${this.config.host}:${this.actualPort}`;
|
|
83
|
+
}
|
|
84
|
+
getActualPort() {
|
|
85
|
+
return this.actualPort;
|
|
57
86
|
}
|
|
58
87
|
}
|