@michelabboud/visual-forge-mcp 0.9.0 → 0.11.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +184 -1
  2. package/README.md +2 -1
  3. package/dist/pdf/image-converter.d.ts +53 -0
  4. package/dist/pdf/image-converter.d.ts.map +1 -0
  5. package/dist/pdf/image-converter.js +179 -0
  6. package/dist/pdf/image-converter.js.map +1 -0
  7. package/dist/pdf/index.d.ts +8 -0
  8. package/dist/pdf/index.d.ts.map +1 -0
  9. package/dist/pdf/index.js +11 -0
  10. package/dist/pdf/index.js.map +1 -0
  11. package/dist/pdf/pdf-types.d.ts +190 -0
  12. package/dist/pdf/pdf-types.d.ts.map +1 -0
  13. package/dist/pdf/pdf-types.js +6 -0
  14. package/dist/pdf/pdf-types.js.map +1 -0
  15. package/dist/pdf/typst-engine.d.ts +70 -0
  16. package/dist/pdf/typst-engine.d.ts.map +1 -0
  17. package/dist/pdf/typst-engine.js +477 -0
  18. package/dist/pdf/typst-engine.js.map +1 -0
  19. package/dist/placeholders/placeholder-manager.d.ts.map +1 -1
  20. package/dist/placeholders/placeholder-manager.js +18 -9
  21. package/dist/placeholders/placeholder-manager.js.map +1 -1
  22. package/dist/providers/base-provider.d.ts.map +1 -1
  23. package/dist/providers/base-provider.js +52 -20
  24. package/dist/providers/base-provider.js.map +1 -1
  25. package/dist/server/mcp-server.d.ts +7 -0
  26. package/dist/server/mcp-server.d.ts.map +1 -1
  27. package/dist/server/mcp-server.js +250 -0
  28. package/dist/server/mcp-server.js.map +1 -1
  29. package/dist/types/generation.d.ts +13 -1
  30. package/dist/types/generation.d.ts.map +1 -1
  31. package/dist/types/image-spec.d.ts +1 -0
  32. package/dist/types/image-spec.d.ts.map +1 -1
  33. package/dist/utils/index.d.ts +1 -0
  34. package/dist/utils/index.d.ts.map +1 -1
  35. package/dist/utils/index.js +1 -0
  36. package/dist/utils/index.js.map +1 -1
  37. package/dist/utils/multi-format-optimizer.d.ts +7 -2
  38. package/dist/utils/multi-format-optimizer.d.ts.map +1 -1
  39. package/dist/utils/multi-format-optimizer.js +22 -2
  40. package/dist/utils/multi-format-optimizer.js.map +1 -1
  41. package/dist/utils/optimization-strategy-manager.d.ts +99 -0
  42. package/dist/utils/optimization-strategy-manager.d.ts.map +1 -0
  43. package/dist/utils/optimization-strategy-manager.js +254 -0
  44. package/dist/utils/optimization-strategy-manager.js.map +1 -0
  45. package/dist/workflow/workflow-tools.d.ts.map +1 -1
  46. package/dist/workflow/workflow-tools.js +34 -11
  47. package/dist/workflow/workflow-tools.js.map +1 -1
  48. package/docs/guides/smart-optimization-guide.md +312 -0
  49. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,7 +5,190 @@ All notable changes to Visual Forge MCP will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.11.0] - 2026-01-17
9
+
10
+ ### Added 📄 **PDF Generation System**
11
+
12
+ Visual Forge now includes a complete PDF generation module using the Typst typesetting engine.
13
+
14
+ #### New MCP Tools
15
+ - **`pdf_generate`** - Generate PDF from markdown/Typst source
16
+ - Supports Typst (primary) and XeLaTeX (fallback) engines
17
+ - Automatic WebP to PNG conversion for PDF compatibility
18
+ - Custom templates, fonts, margins, and metadata
19
+ - Table of contents generation
20
+ - **`pdf_generate_batch`** - Batch process multiple files
21
+ - Concurrent generation with configurable parallelism
22
+ - Shared options across all files
23
+ - Progress tracking per file
24
+ - **`pdf_check_engine`** - Check engine availability
25
+ - Verify Typst and XeLaTeX installation
26
+ - Get version information
27
+ - **`pdf_list_templates`** - List available templates
28
+ - Built-in "visual-forge" branded template
29
+ - Support for custom .typ templates
30
+
31
+ #### Architecture
32
+ - **New module**: `src/pdf/` with:
33
+ - `pdf-types.ts` - TypeScript type definitions
34
+ - `image-converter.ts` - WebP to PNG conversion using Sharp
35
+ - `typst-engine.ts` - Main Typst PDF engine
36
+ - `index.ts` - Module exports
37
+ - **New template**: `templates/visual-forge.typ` - AWS-branded Typst template with callout boxes
38
+
39
+ #### Performance Benchmarks
40
+ | Metric | Typst | XeLaTeX |
41
+ |--------|-------|---------|
42
+ | Speed (large doc) | 2,646ms | 3,157ms |
43
+ | File Size | 746KB | 157KB |
44
+ | Binary Size | ~40MB | ~2.5GB |
45
+
46
+ #### Key Features
47
+ - Automatic fallback from Typst to XeLaTeX if Typst fails
48
+ - WebP images automatically converted to PNG
49
+ - Optional emoji sanitization for PDF compatibility
50
+ - Caching of converted images to avoid re-conversion
51
+ - Cross-platform font defaults (DejaVu family)
52
+
53
+ ---
54
+
55
+ ### Fixed 🔴 **Critical Bug Fixes**
56
+
57
+ #### Issue #1: Placeholder Replacement Failure (CRITICAL)
58
+ **Problem:** After image generation, placeholders in markdown files were NOT replaced with actual image links. All placeholders remained unchanged despite successful generation.
59
+
60
+ **Root Cause:** PlaceholderManager was replacing placeholders using a generic regex that matched ANY placeholder, causing sequential replacements to overwrite each other. Only the last image's replacement survived.
61
+
62
+ **Fix Applied:**
63
+ - Added `imageId` field to all placeholder blocks for unique identification
64
+ - Updated regex to match specific placeholder by imageId: `imageId: <unique-id>`
65
+ - Changed replacement logic to target exact placeholder, not just first match
66
+ - Added error logging when placeholder not found
67
+
68
+ **Files Changed:**
69
+ - `src/placeholders/placeholder-manager.ts`: Updated `insertPlaceholder()` and `replacePlaceholder()`
70
+
71
+ **Result:** ✅ Each image now correctly replaces its own specific placeholder
72
+
73
+ ---
74
+
75
+ #### Issue #2 & #3: Session Isolation Failure (CRITICAL)
76
+ **Problem:** Statistics showed images from ALL sessions (52 images, 32 failures from different files), not just current session (10 images).
77
+
78
+ **Root Cause:** `vf_generate_session` was pulling all images from global state instead of filtering by current session.
79
+
80
+ **Fix Applied:**
81
+ - Filter generated images by current session's imageIds before verification
82
+ - Calculate session-specific costs (sum from session images only)
83
+ - Update statistics to show only current session data
84
+
85
+ **Files Changed:**
86
+ - `src/workflow/workflow-tools.ts`: Lines 456-473 (session filtering), 629-638 (cost calculation)
87
+
88
+ **Result:** ✅ Statistics now accurate for current session only
89
+
90
+ ---
91
+
92
+ #### Issue #4: Image Status Not Updating (HIGH)
93
+ **Problem:** Image status remained stuck at `placeholder_added` despite successful generation.
94
+
95
+ **Root Cause:** No status update after verification step.
96
+
97
+ **Fix Applied:**
98
+ - Added status update to `generated` after successful file verification
99
+ - Status progression now works: `placeholder_added` → `generated` → `inserted_into_document`
100
+
101
+ **Files Changed:**
102
+ - `src/workflow/workflow-tools.ts`: Lines 508-517 (status update after verification)
103
+
104
+ **Result:** ✅ Image status correctly tracks generation progress
105
+
106
+ ---
107
+
108
+ #### Issue #5: Cost Tracking Showing $0 (MEDIUM)
109
+ **Problem:** Total cost reported as $0 despite generating 10 images via Gemini API.
110
+
111
+ **Root Cause:** Using global `updatedState.costs.totalCost` instead of calculating session-specific cost.
112
+
113
+ **Fix Applied:**
114
+ - Calculate session cost by summing `metadata.actualCost` from verified session images
115
+ - Return session-specific cost in tool response
116
+
117
+ **Files Changed:**
118
+ - `src/workflow/workflow-tools.ts`: Lines 629-638 (session cost calculation), Line 663 (return statement)
119
+
120
+ **Result:** ✅ Accurate cost tracking per session
121
+
122
+ ---
123
+
124
+ ### Added 🎨 **Smart Image Optimization System**
125
+
126
+ #### Intelligent Format Selection
127
+ - **New: Optimization Strategy Manager** (`src/utils/optimization-strategy-manager.ts`)
128
+ - Automatically recommends optimal format based on image type
129
+ - Hero images → WebP (90% quality, best compression)
130
+ - Screenshots → PNG lossy (95% quality, pixel-perfect)
131
+ - Diagrams/Flowcharts → PNG lossy (95% quality, sharp text)
132
+ - Architecture diagrams → PNG lossy (95% quality, precision)
133
+ - Icons → WebP (85% quality, smallest size, no watermark)
134
+ - Illustrations → WebP (88% quality, balanced)
135
+ - Charts → PNG lossy (92% quality, data accuracy)
136
+
137
+ #### All Formats Still Generated
138
+ - **No reduction in output** - Still generates WebP, JPEG, PNG, and Original
139
+ - **Smart recommendation** - System marks which format to use in document
140
+ - **Maximum flexibility** - All formats available for different contexts
141
+ - **Automatic insertion** - Placeholder replacement uses recommended format
142
+
143
+ #### Advanced User Override
144
+ - **New: `preferredFormat` metadata field**
145
+ - Allow advanced users to override smart selection
146
+ - Specify in image placeholder: `preferredFormat: jpeg`
147
+ - Supported values: `webp`, `jpeg`, `png`, `original`
148
+ - Falls back to smart recommendation if not specified
149
+
150
+ #### Enhanced Type System
151
+ - **Updated `ImageSpec.metadata`** - Added `preferredFormat` field
152
+ - **Updated `GeneratedImageMetadata`** - Added `multiFormat` object with:
153
+ - List of all generated formats
154
+ - Recommended format and path
155
+ - Recommendation reasoning
156
+ - Watermark status
157
+
158
+ #### Quality Optimization by Type
159
+ - **Type-specific quality settings** - Each image type gets optimal quality levels
160
+ - **Intelligent watermarking** - Icons don't get watermarked (too small)
161
+ - **PNG optimization** - Smart lossy/lossless selection per type
162
+
163
+ #### Transparency & Logging
164
+ - **Detailed logging** - Every image logs smart optimization decision
165
+ - **Reasoning provided** - Explains why format was chosen
166
+ - **All formats tracked** - Metadata includes all generated formats
167
+
168
+ #### Documentation
169
+ - **New Guide**: `docs/guides/smart-optimization-guide.md`
170
+ - Comprehensive explanation of smart optimization
171
+ - Format recommendations by image type
172
+ - Use case examples (web, PDF, technical docs)
173
+ - Advanced override instructions
174
+ - Performance comparisons
175
+ - Troubleshooting guide
176
+
177
+ #### Technical Changes
178
+ - **Updated Files**:
179
+ - `src/utils/optimization-strategy-manager.ts` (NEW - 300+ lines)
180
+ - `src/utils/multi-format-optimizer.ts` - Added recommendation parameters
181
+ - `src/providers/base-provider.ts` - Uses smart optimization
182
+ - `src/types/image-spec.ts` - Added `preferredFormat` field
183
+ - `src/types/generation.ts` - Added `multiFormat` metadata
184
+ - `src/workflow/workflow-tools.ts` - Updated validation messages
185
+
186
+ #### Benefits
187
+ - ✅ **Optimal quality** - Right format for each use case
188
+ - ✅ **Better performance** - WebP for web, PNG for technical content
189
+ - ✅ **User choice** - Can still override when needed
190
+ - ✅ **Transparency** - Clear reasoning for every decision
191
+ - ✅ **Backward compatible** - Existing workflows unaffected
9
192
 
10
193
  ---
11
194
 
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  An MCP (Model Context Protocol) server that automates AI image generation for technical documentation. Parse markdown files containing image prompts and generate professional images using multiple AI providers.
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/@michelabboud/visual-forge-mcp.svg)](https://www.npmjs.com/package/@michelabboud/visual-forge-mcp)
10
- [![Version](https://img.shields.io/badge/version-0.9.0-blue.svg)](https://github.com/michelabboud/visual-forge-mcp)
10
+ [![Version](https://img.shields.io/badge/version-0.11.0-blue.svg)](https://github.com/michelabboud/visual-forge-mcp)
11
11
  [![License](https://img.shields.io/badge/License-Personal%20Use%20Only-red.svg)](LICENSE)
12
12
  [![Node.js](https://img.shields.io/badge/node-%3E%3D24.0.0-brightgreen.svg)](https://nodejs.org/)
13
13
 
@@ -43,6 +43,7 @@ An MCP (Model Context Protocol) server that automates AI image generation for te
43
43
  - **📊 Cost Tracking**: Real-time cost monitoring and estimates per provider
44
44
  - **🎯 Smart Rate Limiting**: Token bucket algorithm prevents API bans
45
45
  - **🔒 Automatic Backups**: File backup system with approve/restore workflow (optional, enabled by default)
46
+ - **📄 PDF Generation** ✨ NEW v0.11.0: Generate PDFs from markdown using Typst engine with XeLaTeX fallback, custom templates, and automatic WebP to PNG conversion
46
47
  - **🌐 Universal MCP Support**: Compatible with 24+ MCP clients (tested with Claude Code, Claude Desktop, Zed)
47
48
 
48
49
  ---
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Visual Forge MCP - Image Converter
3
+ * Converts WebP images to PNG/JPG for PDF compatibility
4
+ */
5
+ import { ImageConversionResult } from './pdf-types.js';
6
+ /**
7
+ * Image converter for PDF compatibility
8
+ * WebP images are not supported by LaTeX/Typst, so we convert them to PNG
9
+ */
10
+ export declare class ImageConverter {
11
+ private outputDir;
12
+ private convertedCache;
13
+ constructor(outputDir?: string);
14
+ /**
15
+ * Convert a WebP image to PNG
16
+ */
17
+ convertWebPToPNG(imagePath: string): Promise<ImageConversionResult>;
18
+ /**
19
+ * Convert multiple images
20
+ */
21
+ convertImages(imagePaths: string[]): Promise<ImageConversionResult[]>;
22
+ /**
23
+ * Extract image paths from markdown content
24
+ */
25
+ extractImagePaths(content: string, baseDir: string): string[];
26
+ /**
27
+ * Process markdown content, converting WebP references to PNG
28
+ */
29
+ processMarkdownImages(content: string, baseDir: string): Promise<{
30
+ content: string;
31
+ conversions: ImageConversionResult[];
32
+ }>;
33
+ /**
34
+ * Escape special regex characters
35
+ */
36
+ private escapeRegex;
37
+ /**
38
+ * Clean up converted images
39
+ */
40
+ cleanup(): Promise<void>;
41
+ /**
42
+ * Get conversion statistics
43
+ */
44
+ getStats(): {
45
+ totalConverted: number;
46
+ cachePath: string;
47
+ };
48
+ }
49
+ /**
50
+ * Default image converter instance
51
+ */
52
+ export declare const imageConverter: ImageConverter;
53
+ //# sourceMappingURL=image-converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-converter.d.ts","sourceRoot":"","sources":["../../src/pdf/image-converter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAkC;gBAE5C,SAAS,CAAC,EAAE,MAAM;IAI9B;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA8EzE;;OAEG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAW3E;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAqB7D;;OAEG;IACG,qBAAqB,CACzB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,qBAAqB,EAAE,CAAA;KAAE,CAAC;IA4BrE;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B;;OAEG;IACH,QAAQ,IAAI;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CAM1D;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Visual Forge MCP - Image Converter
3
+ * Converts WebP images to PNG/JPG for PDF compatibility
4
+ */
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ import sharp from 'sharp';
8
+ import { logger } from '../utils/index.js';
9
+ /**
10
+ * Image converter for PDF compatibility
11
+ * WebP images are not supported by LaTeX/Typst, so we convert them to PNG
12
+ */
13
+ export class ImageConverter {
14
+ outputDir;
15
+ convertedCache = new Map();
16
+ constructor(outputDir) {
17
+ this.outputDir = outputDir || './.pdf-images';
18
+ }
19
+ /**
20
+ * Convert a WebP image to PNG
21
+ */
22
+ async convertWebPToPNG(imagePath) {
23
+ const absolutePath = path.resolve(imagePath);
24
+ const ext = path.extname(imagePath).toLowerCase();
25
+ // Skip if not WebP
26
+ if (ext !== '.webp') {
27
+ return {
28
+ originalPath: imagePath,
29
+ convertedPath: imagePath,
30
+ converted: false,
31
+ };
32
+ }
33
+ // Check cache
34
+ if (this.convertedCache.has(absolutePath)) {
35
+ return {
36
+ originalPath: imagePath,
37
+ convertedPath: this.convertedCache.get(absolutePath),
38
+ converted: true,
39
+ };
40
+ }
41
+ try {
42
+ // Ensure output directory exists
43
+ await fs.mkdir(this.outputDir, { recursive: true });
44
+ // Generate output path
45
+ const basename = path.basename(imagePath, '.webp');
46
+ const outputPath = path.join(this.outputDir, `${basename}.png`);
47
+ // Check if file exists
48
+ try {
49
+ await fs.access(absolutePath);
50
+ }
51
+ catch {
52
+ return {
53
+ originalPath: imagePath,
54
+ convertedPath: imagePath,
55
+ converted: false,
56
+ error: `File not found: ${imagePath}`,
57
+ };
58
+ }
59
+ // Convert using Sharp
60
+ await sharp(absolutePath)
61
+ .png({
62
+ quality: 90,
63
+ compressionLevel: 6,
64
+ })
65
+ .toFile(outputPath);
66
+ // Cache the result
67
+ this.convertedCache.set(absolutePath, outputPath);
68
+ logger.info('Converted WebP to PNG', {
69
+ original: imagePath,
70
+ converted: outputPath,
71
+ });
72
+ return {
73
+ originalPath: imagePath,
74
+ convertedPath: outputPath,
75
+ converted: true,
76
+ };
77
+ }
78
+ catch (error) {
79
+ logger.error('Failed to convert WebP image', {
80
+ imagePath,
81
+ error: error.message,
82
+ });
83
+ return {
84
+ originalPath: imagePath,
85
+ convertedPath: imagePath,
86
+ converted: false,
87
+ error: error.message,
88
+ };
89
+ }
90
+ }
91
+ /**
92
+ * Convert multiple images
93
+ */
94
+ async convertImages(imagePaths) {
95
+ const results = [];
96
+ for (const imagePath of imagePaths) {
97
+ const result = await this.convertWebPToPNG(imagePath);
98
+ results.push(result);
99
+ }
100
+ return results;
101
+ }
102
+ /**
103
+ * Extract image paths from markdown content
104
+ */
105
+ extractImagePaths(content, baseDir) {
106
+ const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
107
+ const paths = [];
108
+ let match;
109
+ while ((match = imageRegex.exec(content)) !== null) {
110
+ const imagePath = match[2];
111
+ // Skip URLs
112
+ if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
113
+ continue;
114
+ }
115
+ // Resolve relative paths
116
+ const absolutePath = path.isAbsolute(imagePath)
117
+ ? imagePath
118
+ : path.resolve(baseDir, imagePath);
119
+ paths.push(absolutePath);
120
+ }
121
+ return paths;
122
+ }
123
+ /**
124
+ * Process markdown content, converting WebP references to PNG
125
+ */
126
+ async processMarkdownImages(content, baseDir) {
127
+ const imagePaths = this.extractImagePaths(content, baseDir);
128
+ const conversions = [];
129
+ let processedContent = content;
130
+ for (const imagePath of imagePaths) {
131
+ const result = await this.convertWebPToPNG(imagePath);
132
+ conversions.push(result);
133
+ if (result.converted && result.convertedPath !== result.originalPath) {
134
+ // Replace the path in content
135
+ const relativePath = path.relative(baseDir, result.convertedPath);
136
+ processedContent = processedContent.replace(new RegExp(this.escapeRegex(result.originalPath), 'g'), relativePath);
137
+ // Also replace relative paths
138
+ const originalRelative = path.relative(baseDir, result.originalPath);
139
+ processedContent = processedContent.replace(new RegExp(this.escapeRegex(originalRelative), 'g'), relativePath);
140
+ }
141
+ }
142
+ return { content: processedContent, conversions };
143
+ }
144
+ /**
145
+ * Escape special regex characters
146
+ */
147
+ escapeRegex(str) {
148
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
149
+ }
150
+ /**
151
+ * Clean up converted images
152
+ */
153
+ async cleanup() {
154
+ try {
155
+ await fs.rm(this.outputDir, { recursive: true, force: true });
156
+ this.convertedCache.clear();
157
+ logger.info('Cleaned up converted images', { dir: this.outputDir });
158
+ }
159
+ catch (error) {
160
+ logger.warn('Failed to clean up converted images', {
161
+ error: error.message,
162
+ });
163
+ }
164
+ }
165
+ /**
166
+ * Get conversion statistics
167
+ */
168
+ getStats() {
169
+ return {
170
+ totalConverted: this.convertedCache.size,
171
+ cachePath: this.outputDir,
172
+ };
173
+ }
174
+ }
175
+ /**
176
+ * Default image converter instance
177
+ */
178
+ export const imageConverter = new ImageConverter();
179
+ //# sourceMappingURL=image-converter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-converter.js","sourceRoot":"","sources":["../../src/pdf/image-converter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Visual Forge MCP - PDF Generation Module
3
+ * Exports PDF generation functionality
4
+ */
5
+ export * from './pdf-types.js';
6
+ export { ImageConverter, imageConverter } from './image-converter.js';
7
+ export { TypstEngine, typstEngine, generatePDF, generateBatchPDF, } from './typst-engine.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pdf/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,gBAAgB,GACjB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Visual Forge MCP - PDF Generation Module
3
+ * Exports PDF generation functionality
4
+ */
5
+ // Types
6
+ export * from './pdf-types.js';
7
+ // Image converter
8
+ export { ImageConverter, imageConverter } from './image-converter.js';
9
+ // Typst engine
10
+ export { TypstEngine, typstEngine, generatePDF, generateBatchPDF, } from './typst-engine.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pdf/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,QAAQ;AACR,cAAc,gBAAgB,CAAC;AAE/B,kBAAkB;AAClB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,eAAe;AACf,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,gBAAgB,GACjB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Visual Forge MCP - PDF Generation Types
3
+ * Type definitions for PDF generation with Typst engine
4
+ */
5
+ /**
6
+ * Supported PDF engines
7
+ */
8
+ export type PDFEngine = 'typst' | 'xelatex';
9
+ /**
10
+ * Paper sizes for PDF generation
11
+ */
12
+ export type PaperSize = 'a4' | 'letter' | 'a5' | 'legal';
13
+ /**
14
+ * Document metadata for PDF
15
+ */
16
+ export interface DocumentMetadata {
17
+ title?: string;
18
+ author?: string;
19
+ date?: string;
20
+ abstract?: string;
21
+ subject?: string;
22
+ keywords?: string[];
23
+ logo?: string;
24
+ }
25
+ /**
26
+ * Font configuration for PDF generation
27
+ */
28
+ export interface FontOptions {
29
+ mainFont?: string;
30
+ sansFont?: string;
31
+ monoFont?: string;
32
+ fontSize?: number;
33
+ }
34
+ /**
35
+ * Page margin configuration
36
+ */
37
+ export interface MarginOptions {
38
+ top?: string;
39
+ bottom?: string;
40
+ left?: string;
41
+ right?: string;
42
+ }
43
+ /**
44
+ * PDF generation options
45
+ */
46
+ export interface PDFGenerationOptions {
47
+ /** Input markdown file path */
48
+ inputPath: string;
49
+ /** Output PDF file path */
50
+ outputPath: string;
51
+ /** PDF engine to use (default: typst) */
52
+ engine?: PDFEngine;
53
+ /** Custom Typst template path */
54
+ template?: string;
55
+ /** Document metadata */
56
+ metadata?: DocumentMetadata;
57
+ /** Font options */
58
+ fonts?: FontOptions;
59
+ /** Page margins */
60
+ margins?: MarginOptions;
61
+ /** Paper size (default: a4) */
62
+ paperSize?: PaperSize;
63
+ /** Include table of contents */
64
+ includeToc?: boolean;
65
+ /** Convert WebP images to PNG */
66
+ convertWebP?: boolean;
67
+ /** Remove emojis from content */
68
+ sanitizeEmoji?: boolean;
69
+ /** Working directory for relative paths */
70
+ workingDirectory?: string;
71
+ }
72
+ /**
73
+ * PDF generation result
74
+ */
75
+ export interface PDFGenerationResult {
76
+ /** Whether generation succeeded */
77
+ success: boolean;
78
+ /** Output PDF file path */
79
+ outputPath?: string;
80
+ /** File size in bytes */
81
+ fileSize?: number;
82
+ /** Page count */
83
+ pageCount?: number;
84
+ /** Generation time in milliseconds */
85
+ duration?: number;
86
+ /** Engine used */
87
+ engine: PDFEngine;
88
+ /** Error message if failed */
89
+ error?: string;
90
+ /** Warnings during generation */
91
+ warnings?: string[];
92
+ /** Images converted from WebP */
93
+ convertedImages?: string[];
94
+ }
95
+ /**
96
+ * Batch PDF generation options
97
+ */
98
+ export interface BatchPDFOptions {
99
+ /** Input files to process */
100
+ files: string[];
101
+ /** Output directory */
102
+ outputDir: string;
103
+ /** Shared options for all files */
104
+ options?: Omit<PDFGenerationOptions, 'inputPath' | 'outputPath'>;
105
+ /** Concurrency for parallel generation */
106
+ concurrency?: number;
107
+ }
108
+ /**
109
+ * Batch PDF generation result
110
+ */
111
+ export interface BatchPDFResult {
112
+ /** Total files processed */
113
+ totalFiles: number;
114
+ /** Successfully generated */
115
+ successful: number;
116
+ /** Failed generations */
117
+ failed: number;
118
+ /** Total time in milliseconds */
119
+ totalDuration: number;
120
+ /** Individual results */
121
+ results: PDFGenerationResult[];
122
+ }
123
+ /**
124
+ * Image conversion result
125
+ */
126
+ export interface ImageConversionResult {
127
+ /** Original image path */
128
+ originalPath: string;
129
+ /** Converted image path */
130
+ convertedPath: string;
131
+ /** Whether conversion was needed */
132
+ converted: boolean;
133
+ /** Error if conversion failed */
134
+ error?: string;
135
+ }
136
+ /**
137
+ * Preprocessor options for markdown
138
+ */
139
+ export interface PreprocessOptions {
140
+ /** Convert WebP images to PNG */
141
+ convertWebP?: boolean;
142
+ /** Remove/replace emojis */
143
+ sanitizeEmoji?: boolean;
144
+ /** Base directory for image resolution */
145
+ baseDir?: string;
146
+ /** Output directory for converted images */
147
+ outputDir?: string;
148
+ }
149
+ /**
150
+ * Preprocessor result
151
+ */
152
+ export interface PreprocessResult {
153
+ /** Preprocessed markdown content */
154
+ content: string;
155
+ /** Converted images */
156
+ convertedImages: ImageConversionResult[];
157
+ /** Warnings during preprocessing */
158
+ warnings: string[];
159
+ }
160
+ /**
161
+ * Typst template information
162
+ */
163
+ export interface TemplateInfo {
164
+ /** Template name */
165
+ name: string;
166
+ /** Template file path */
167
+ path: string;
168
+ /** Template description */
169
+ description?: string;
170
+ /** Supported features */
171
+ features?: string[];
172
+ }
173
+ /**
174
+ * PDF engine capabilities
175
+ */
176
+ export interface EngineCapabilities {
177
+ /** Engine name */
178
+ name: string;
179
+ /** Whether engine is available */
180
+ available: boolean;
181
+ /** Engine version */
182
+ version?: string;
183
+ /** Supported output formats */
184
+ outputFormats: string[];
185
+ /** Supported input formats */
186
+ inputFormats: string[];
187
+ /** Available templates */
188
+ templates: TemplateInfo[];
189
+ }
190
+ //# sourceMappingURL=pdf-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf-types.d.ts","sourceRoot":"","sources":["../../src/pdf/pdf-types.ts"],"names":[],"mappings":"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"}