@vint.tri/report_gen_mcp 1.5.26 → 1.5.28
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/dist/images/localImages.d.ts +19 -0
- package/dist/images/localImages.d.ts.map +1 -0
- package/dist/images/localImages.js +52 -0
- package/dist/index.js +1 -1
- package/dist/utils/reportGenerator.d.ts +2 -1
- package/dist/utils/reportGenerator.d.ts.map +1 -1
- package/dist/utils/reportGenerator.js +19 -9
- package/package.json +6 -3
- package/test_report.md +15 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const localImageSchema: z.ZodObject<{
|
|
3
|
+
src: z.ZodString;
|
|
4
|
+
alt: z.ZodOptional<z.ZodString>;
|
|
5
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
src: string;
|
|
9
|
+
alt?: string | undefined;
|
|
10
|
+
width?: number | undefined;
|
|
11
|
+
height?: number | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
src: string;
|
|
14
|
+
alt?: string | undefined;
|
|
15
|
+
width?: number | undefined;
|
|
16
|
+
height?: number | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function renderLocalImage(params: z.infer<typeof localImageSchema>): Promise<string>;
|
|
19
|
+
//# sourceMappingURL=localImages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localImages.d.ts","sourceRoot":"","sources":["../../src/images/localImages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAK3B,CAAC;AAqBH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BhG"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
// Schema for validating local image parameters
|
|
5
|
+
export const localImageSchema = z.object({
|
|
6
|
+
src: z.string().describe("Путь к локальному изображению"),
|
|
7
|
+
alt: z.string().optional().describe("Альтернативный текст для изображения"),
|
|
8
|
+
width: z.number().optional().describe("Ширина изображения в пикселях"),
|
|
9
|
+
height: z.number().optional().describe("Высота изображения в пикселях"),
|
|
10
|
+
});
|
|
11
|
+
// Function to determine MIME type from buffer
|
|
12
|
+
function getMimeTypeFromBuffer(buffer) {
|
|
13
|
+
// Check JPEG
|
|
14
|
+
if (buffer[0] === 0xFF && buffer[1] === 0xD8) {
|
|
15
|
+
return 'image/jpeg';
|
|
16
|
+
}
|
|
17
|
+
// Check PNG
|
|
18
|
+
if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && buffer[3] === 0x47) {
|
|
19
|
+
return 'image/png';
|
|
20
|
+
}
|
|
21
|
+
// Check GIF
|
|
22
|
+
if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46) {
|
|
23
|
+
return 'image/gif';
|
|
24
|
+
}
|
|
25
|
+
// Default to JPEG if unknown
|
|
26
|
+
return 'image/jpeg';
|
|
27
|
+
}
|
|
28
|
+
// Function to render local image to HTML
|
|
29
|
+
export async function renderLocalImage(params) {
|
|
30
|
+
const validatedParams = localImageSchema.parse(params);
|
|
31
|
+
const imagePath = path.resolve(process.cwd(), validatedParams.src);
|
|
32
|
+
let imageSrc;
|
|
33
|
+
try {
|
|
34
|
+
const imageBuffer = await fs.readFile(imagePath);
|
|
35
|
+
const mimeType = getMimeTypeFromBuffer(imageBuffer);
|
|
36
|
+
imageSrc = `data:${mimeType};base64,${imageBuffer.toString('base64')}`;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error(`Error reading local image file: ${imagePath}`, error);
|
|
40
|
+
// Fallback to original path if reading fails
|
|
41
|
+
imageSrc = validatedParams.src;
|
|
42
|
+
}
|
|
43
|
+
const widthStyle = validatedParams.width ? `width: ${validatedParams.width}px;` : '';
|
|
44
|
+
const heightStyle = validatedParams.height ? `height: ${validatedParams.height}px;` : '';
|
|
45
|
+
const altText = validatedParams.alt || '';
|
|
46
|
+
return `
|
|
47
|
+
<div class="image-container" style="margin: 20px 0; text-align: center;">
|
|
48
|
+
<img src="${imageSrc}" alt="${altText}" style="max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); ${widthStyle} ${heightStyle}">
|
|
49
|
+
${altText ? `<p style="margin-top: 10px; font-size: 14px; color: #666;">${altText}</p>` : ''}
|
|
50
|
+
</div>
|
|
51
|
+
`;
|
|
52
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -109,7 +109,7 @@ if (process.argv.length === 2) {
|
|
|
109
109
|
// No command specified, run in stdio mode using MCP SDK
|
|
110
110
|
const mcpServer = new McpServer({
|
|
111
111
|
name: "report_gen_mcp",
|
|
112
|
-
version: "1.5.
|
|
112
|
+
version: "1.5.28"
|
|
113
113
|
}, {
|
|
114
114
|
// Disable health check to prevent automatic calls
|
|
115
115
|
capabilities: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export declare function generateReport(
|
|
1
|
+
export declare function generateReport(markdownDocument: string, // Renamed 'document' to 'markdownDocument' for clarity
|
|
2
|
+
outputFile: string): Promise<{
|
|
2
3
|
success: boolean;
|
|
3
4
|
filePath: string;
|
|
4
5
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reportGenerator.d.ts","sourceRoot":"","sources":["../../src/utils/reportGenerator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reportGenerator.d.ts","sourceRoot":"","sources":["../../src/utils/reportGenerator.ts"],"names":[],"mappings":"AAuIA,wBAAsB,cAAc,CAClC,gBAAgB,EAAE,MAAM,EAAE,uDAAuD;AACjF,UAAU,EAAE,MAAM;;;GA4InB"}
|
|
@@ -9,6 +9,7 @@ import { doughnutSchema, renderDoughnutChart } from '../charts/doughnut.js';
|
|
|
9
9
|
import { radarSchema, renderRadarChart } from '../charts/radar.js';
|
|
10
10
|
import { polarAreaSchema, renderPolarAreaChart } from '../charts/polarArea.js';
|
|
11
11
|
import { urlImageSchema, renderUrlImage } from '../images/urlImages.js';
|
|
12
|
+
import { localImageSchema, renderLocalImage } from '../images/localImages.js'; // Added this line
|
|
12
13
|
async function extractElementsFromMarkdown(markdown) {
|
|
13
14
|
console.log("Starting extractElementsFromMarkdown...");
|
|
14
15
|
const elements = {};
|
|
@@ -40,13 +41,21 @@ async function extractElementsFromMarkdown(markdown) {
|
|
|
40
41
|
const src = imageMatch[1];
|
|
41
42
|
const alt = imageMatch[2] || '';
|
|
42
43
|
const id = `image-${elementCount++}`;
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
// Determine if it's a URL or local image
|
|
45
|
+
const isUrl = src.startsWith('http://') || src.startsWith('https://');
|
|
46
|
+
const imageType = isUrl ? 'url' : 'local';
|
|
47
|
+
if (isUrl) {
|
|
48
|
+
elements[id] = { type: imageType, config: { url: src, alt: alt } };
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
elements[id] = { type: imageType, config: { src: src, alt: alt } };
|
|
52
|
+
}
|
|
53
|
+
console.log(`Extracted image: ${id}, type: ${imageType}, src: ${src}`);
|
|
45
54
|
// Replace the original img tag with a placeholder
|
|
46
55
|
markdown = markdown.replace(imageMatch[0], `[[image:${id}]]`);
|
|
47
56
|
}
|
|
48
57
|
console.log("Finished extractElementsFromMarkdown. Extracted elements:", Object.keys(elements));
|
|
49
|
-
return elements;
|
|
58
|
+
return { updatedMarkdown: markdown, elements: elements };
|
|
50
59
|
}
|
|
51
60
|
const chartRenderers = {
|
|
52
61
|
bar: { schema: barSchema, renderer: renderBarChart },
|
|
@@ -58,7 +67,7 @@ const chartRenderers = {
|
|
|
58
67
|
};
|
|
59
68
|
const imageRenderers = {
|
|
60
69
|
url: { schema: urlImageSchema, renderer: renderUrlImage },
|
|
61
|
-
|
|
70
|
+
local: { schema: localImageSchema, renderer: renderLocalImage }, // Added this line
|
|
62
71
|
};
|
|
63
72
|
// Utility function to normalize chart configuration data
|
|
64
73
|
// Converts string values to arrays where the schema expects arrays
|
|
@@ -86,10 +95,11 @@ function normalizeChartConfig(config) {
|
|
|
86
95
|
}
|
|
87
96
|
return normalizedConfig;
|
|
88
97
|
}
|
|
89
|
-
export async function generateReport(
|
|
98
|
+
export async function generateReport(markdownDocument, // Renamed 'document' to 'markdownDocument' for clarity
|
|
99
|
+
outputFile) {
|
|
90
100
|
console.log("Starting generateReport...");
|
|
91
|
-
|
|
92
|
-
const elements =
|
|
101
|
+
// Extract elements and get the updated markdown
|
|
102
|
+
const { updatedMarkdown, elements } = await extractElementsFromMarkdown(markdownDocument); // Modified this line
|
|
93
103
|
console.log("Elements after extraction:", Object.keys(elements));
|
|
94
104
|
// Validate elements
|
|
95
105
|
for (const [id, element] of Object.entries(elements)) {
|
|
@@ -140,13 +150,13 @@ export async function generateReport(document, outputFile) {
|
|
|
140
150
|
}
|
|
141
151
|
}
|
|
142
152
|
// Replace placeholders in Markdown, e.g., [[chart:id]] or [[image:id]]
|
|
143
|
-
let mdWithElements =
|
|
153
|
+
let mdWithElements = updatedMarkdown; // Corrected this line
|
|
144
154
|
for (const [id, htmlElement] of Object.entries(renderedElements)) {
|
|
145
155
|
// Поддерживаем оба формата: [[chart:id]] и [[image:id]] для обратной совместимости
|
|
146
156
|
mdWithElements = mdWithElements.replace(new RegExp(`\\[\\[(chart|image):${id}\\]\\]`, 'g'), htmlElement);
|
|
147
157
|
}
|
|
148
158
|
// Convert Markdown to HTML
|
|
149
|
-
const htmlContent = await marked(mdWithElements);
|
|
159
|
+
const htmlContent = await marked(mdWithElements); // Modified this line to use mdWithElements
|
|
150
160
|
// Wrap in full HTML template with Chart.js library
|
|
151
161
|
const template = `
|
|
152
162
|
<!DOCTYPE html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vint.tri/report_gen_mcp",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.28",
|
|
4
4
|
"description": "CLI tool for generating HTML reports with embedded charts and images",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"start": "node dist/index.js",
|
|
13
13
|
"test": "echo \"No tests yet\"",
|
|
14
|
+
"generate-test-report": "ts-node src/test_utils/generate_test_report.ts",
|
|
14
15
|
"install-python-deps": "pip install -r src/python/requirements.txt",
|
|
15
16
|
"setup-python": "python -m venv venv && source venv/bin/activate && pip install -r src/python/requirements.txt"
|
|
16
17
|
},
|
|
@@ -22,10 +23,11 @@
|
|
|
22
23
|
"ejs": "^3.1.10",
|
|
23
24
|
"express": "^4.19.2",
|
|
24
25
|
"fs-extra": "^11.2.0",
|
|
26
|
+
"get-port": "^7.1.0",
|
|
27
|
+
"http-server": "^14.1.1",
|
|
25
28
|
"jsdom": "^26.1.0",
|
|
26
29
|
"marked": "^14.1.2",
|
|
27
|
-
"zod": "^3.23.8"
|
|
28
|
-
"get-port": "^7.1.0"
|
|
30
|
+
"zod": "^3.23.8"
|
|
29
31
|
},
|
|
30
32
|
"devDependencies": {
|
|
31
33
|
"@types/ejs": "^3.1.5",
|
|
@@ -33,6 +35,7 @@
|
|
|
33
35
|
"@types/fs-extra": "^11.0.4",
|
|
34
36
|
"@types/jsdom": "^21.1.7",
|
|
35
37
|
"@types/node": "^22.5.0",
|
|
38
|
+
"ts-node": "^10.9.2",
|
|
36
39
|
"typescript": "^5.5.4"
|
|
37
40
|
},
|
|
38
41
|
"license": "MIT",
|
package/test_report.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Sample Report with Local Image and Chart
|
|
2
|
+
|
|
3
|
+
This is a sample report to test the image and chart rendering functionality.
|
|
4
|
+
|
|
5
|
+
## Local Image Test
|
|
6
|
+
|
|
7
|
+
Here's a local image:
|
|
8
|
+
|
|
9
|
+
<img src="dollar.png" alt="A dollar bill" width="200">
|
|
10
|
+
|
|
11
|
+
## Bar Chart Test
|
|
12
|
+
|
|
13
|
+
Here's a sample bar chart:
|
|
14
|
+
|
|
15
|
+
<canvas data-chart='{"type":"bar","data":{"labels":["Red","Blue","Yellow","Green","Purple","Orange"],"datasets":[{"label":"# of Votes","data":[12,19,3,5,2,3],"backgroundColor":["rgba(255, 99, 132, 0.2)","rgba(54, 162, 235, 0.2)","rgba(255, 206, 86, 0.2)","rgba(75, 192, 192, 0.2)","rgba(153, 102, 255, 0.2)","rgba(255, 159, 64, 0.2)"],"borderColor":["rgba(255,99,132,1)","rgba(54, 162, 235, 1)","rgba(255, 206, 86, 1)","rgba(75, 192, 192, 1)","rgba(153, 102, 255, 1)","rgba(255, 159, 64, 1)"],"borderWidth":1}]},"options":{"scales":{"y":{"beginAtZero":true}}}}'></canvas>
|