vimd 0.1.12 → 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.
Files changed (39) hide show
  1. package/README.md +111 -193
  2. package/dist/cli/commands/build.d.ts +1 -0
  3. package/dist/cli/commands/build.d.ts.map +1 -1
  4. package/dist/cli/commands/build.js +19 -10
  5. package/dist/cli/commands/dev.d.ts +1 -0
  6. package/dist/cli/commands/dev.d.ts.map +1 -1
  7. package/dist/cli/commands/dev.js +27 -14
  8. package/dist/cli/commands/kill.d.ts +7 -0
  9. package/dist/cli/commands/kill.d.ts.map +1 -0
  10. package/dist/cli/commands/kill.js +110 -0
  11. package/dist/cli/index.js +11 -1
  12. package/dist/config/defaults.d.ts.map +1 -1
  13. package/dist/config/defaults.js +3 -1
  14. package/dist/config/types.d.ts +7 -0
  15. package/dist/config/types.d.ts.map +1 -1
  16. package/dist/core/converter.d.ts +18 -0
  17. package/dist/core/converter.d.ts.map +1 -1
  18. package/dist/core/converter.js +30 -1
  19. package/dist/core/pandoc-detector.d.ts.map +1 -1
  20. package/dist/core/pandoc-detector.js +7 -2
  21. package/dist/core/parser/index.d.ts +5 -0
  22. package/dist/core/parser/index.d.ts.map +1 -0
  23. package/dist/core/parser/index.js +4 -0
  24. package/dist/core/parser/markdown-it-parser.d.ts +23 -0
  25. package/dist/core/parser/markdown-it-parser.d.ts.map +1 -0
  26. package/dist/core/parser/markdown-it-parser.js +49 -0
  27. package/dist/core/parser/pandoc-parser.d.ts +27 -0
  28. package/dist/core/parser/pandoc-parser.d.ts.map +1 -0
  29. package/dist/core/parser/pandoc-parser.js +83 -0
  30. package/dist/core/parser/parser-factory.d.ts +36 -0
  31. package/dist/core/parser/parser-factory.d.ts.map +1 -0
  32. package/dist/core/parser/parser-factory.js +63 -0
  33. package/dist/core/parser/types.d.ts +26 -0
  34. package/dist/core/parser/types.d.ts.map +1 -0
  35. package/dist/core/parser/types.js +2 -0
  36. package/dist/core/server.d.ts +8 -1
  37. package/dist/core/server.d.ts.map +1 -1
  38. package/dist/core/server.js +32 -3
  39. package/package.json +6 -1
@@ -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,9 +17,10 @@ program
16
17
  program
17
18
  .command('dev <file>')
18
19
  .description('Start live preview server')
19
- .option('-p, --port <port>', 'Port number', '8080')
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')
23
+ .option('--pandoc', 'Use pandoc parser instead of markdown-it')
22
24
  .action(devCommand);
23
25
  // vimd build <file>
24
26
  program
@@ -26,6 +28,7 @@ program
26
28
  .description('Build static HTML file')
27
29
  .option('-o, --output <path>', 'Output file path')
28
30
  .option('-t, --theme <theme>', 'Theme name')
31
+ .option('--fast', 'Use markdown-it parser for faster build')
29
32
  .action(buildCommand);
30
33
  // vimd theme
31
34
  program
@@ -38,4 +41,11 @@ program
38
41
  .description('Edit configuration interactively')
39
42
  .option('-l, --list', 'List current configuration')
40
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);
41
51
  program.parse(process.argv);
@@ -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"}
@@ -1,6 +1,6 @@
1
1
  export const DEFAULT_CONFIG = {
2
2
  theme: 'github',
3
- port: 8080,
3
+ port: 38080,
4
4
  host: 'localhost',
5
5
  open: true,
6
6
  pandoc: {
@@ -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 {};