New:Socket for Asana Is Now Available.Learn more
Get Started

snapmcp

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

snapmcp - npm Package Compare versions

Comparing version
2.2.2
to
2.2.3
+6
-0
CHANGELOG.md

@@ -8,2 +8,8 @@ # Changelog

## [2.2.3] - 2026-06-28
### Fixed
- GIF frame auto-padding (centered, transparent) instead of throwing on dimension mismatch
- Auto-append file extension in outPath() and PDF capture
## [2.2.0] - 2026-06-27

@@ -10,0 +16,0 @@

+31
-13

@@ -27,17 +27,35 @@ /**

fs.mkdirSync(path.dirname(outputPath), { recursive: true });
// Read first frame to auto-detect dimensions
const first = readPng(frames[0].filePath);
const width = options?.width ?? first.width;
const height = options?.height ?? first.height;
const gif = new GIFEncoder(width, height, { loop });
// Read all frames to auto-detect max canvas dimensions
const framesData = frames.map(f => ({ frame: f, png: readPng(f.filePath) }));
let canvasWidth = options?.width ?? Math.max(...framesData.map(f => f.png.width));
let canvasHeight = options?.height ?? Math.max(...framesData.map(f => f.png.height));
const gif = new GIFEncoder(canvasWidth, canvasHeight, { loop });
try {
for (const frame of frames) {
for (const { frame, png } of framesData) {
const delay = (frame.delay ?? 80) * 10; // centiseconds → ms
const png = readPng(frame.filePath);
if (png.width !== width || png.height !== height) {
throw new GifError(`Frame dimensions (${png.width}x${png.height}) must match ` +
`GIF canvas (${width}x${height}): ${frame.filePath}`);
let data = png.data;
let w = png.width;
let h = png.height;
// Auto-pad smaller frames to match canvas dimensions
if (w !== canvasWidth || h !== canvasHeight) {
const padded = new Uint8Array(canvasWidth * canvasHeight * 4);
padded.fill(0); // transparent black
const ox = Math.floor((canvasWidth - w) / 2);
const oy = Math.floor((canvasHeight - h) / 2);
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
const si = (y * w + x) * 4;
const di = ((y + oy) * canvasWidth + (x + ox)) * 4;
padded[di] = data[si];
padded[di + 1] = data[si + 1];
padded[di + 2] = data[si + 2];
padded[di + 3] = data[si + 3];
}
}
data = padded;
w = canvasWidth;
h = canvasHeight;
}
const palette = quantize(png.data, 256);
const idxData = applyPalette(png.data, palette);
const palette = quantize(data, 256);
const idxData = applyPalette(data, palette);
const flatPalette = new Uint8Array(palette.length * 3);

@@ -49,3 +67,3 @@ for (let i = 0; i < palette.length; i++) {

}
gif.writeFrame(idxData, width, height, { delay, palette: flatPalette, transparent: false });
gif.writeFrame(idxData, w, h, { delay, palette: flatPalette, transparent: false });
}

@@ -52,0 +70,0 @@ gif.finish();

@@ -164,3 +164,6 @@ #!/usr/bin/env node

if (name) {
return resolveSafePath(OUTPUT_DIR, name);
// Append default extension if name lacks one (Playwright needs ext for MIME)
const hasExt = /\.(png|jpe?g|gif|pdf)$/i.test(name);
const finalName = hasExt ? name : `${name}.${ext()}`;
return resolveSafePath(OUTPUT_DIR, finalName);
}

@@ -303,3 +306,5 @@ return path.join(OUTPUT_DIR, `${prefix}-${Date.now()}.${ext()}`);

const filename = output || `pdf-${Date.now()}.pdf`;
const p = resolveSafePath(OUTPUT_DIR, filename);
const hasExt = /\.(pdf)$/i.test(filename);
const finalName = hasExt ? filename : `${filename}.pdf`;
const p = resolveSafePath(OUTPUT_DIR, finalName);
await capturePdf(url, p, fullPage, width, height, config);

@@ -306,0 +311,0 @@ logger.audit({ event: AuditEventType.CapturePdf, severity: "info", detail: `URL: ${url}`, source: "capture_pdf" });

{
"name": "snapmcp",
"version": "2.2.2",
"version": "2.2.3",
"description": "All-in-one MCP server for visual captures: terminal, code, browser, markdown, diffs, HTML, and PDF — via Playwright",

@@ -5,0 +5,0 @@ "keywords": [