pabal-resource-mcp 1.5.2 → 1.5.3
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/bin/mcp-server.js +67 -7
- package/package.json +1 -1
package/dist/bin/mcp-server.js
CHANGED
|
@@ -3659,13 +3659,58 @@ async function getImageDimensions2(imagePath) {
|
|
|
3659
3659
|
height: metadata.height
|
|
3660
3660
|
};
|
|
3661
3661
|
}
|
|
3662
|
+
async function detectEdgeColor(imagePath) {
|
|
3663
|
+
const image = sharp2(imagePath);
|
|
3664
|
+
const metadata = await image.metadata();
|
|
3665
|
+
const width = metadata.width || 100;
|
|
3666
|
+
const height = metadata.height || 100;
|
|
3667
|
+
const { data, info } = await image.raw().toBuffer({ resolveWithObject: true });
|
|
3668
|
+
const channels = info.channels;
|
|
3669
|
+
const colorCounts = /* @__PURE__ */ new Map();
|
|
3670
|
+
const sampleEdgePixel = (x, y) => {
|
|
3671
|
+
const idx = (y * width + x) * channels;
|
|
3672
|
+
const r = data[idx];
|
|
3673
|
+
const g = data[idx + 1];
|
|
3674
|
+
const b = data[idx + 2];
|
|
3675
|
+
const qr = Math.round(r / 16) * 16;
|
|
3676
|
+
const qg = Math.round(g / 16) * 16;
|
|
3677
|
+
const qb = Math.round(b / 16) * 16;
|
|
3678
|
+
const key = `${qr},${qg},${qb}`;
|
|
3679
|
+
const existing = colorCounts.get(key);
|
|
3680
|
+
if (existing) {
|
|
3681
|
+
existing.count++;
|
|
3682
|
+
} else {
|
|
3683
|
+
colorCounts.set(key, { count: 1, color: { r: qr, g: qg, b: qb } });
|
|
3684
|
+
}
|
|
3685
|
+
};
|
|
3686
|
+
for (let x = 0; x < width; x += 2) {
|
|
3687
|
+
sampleEdgePixel(x, 0);
|
|
3688
|
+
sampleEdgePixel(x, height - 1);
|
|
3689
|
+
}
|
|
3690
|
+
for (let y = 0; y < height; y += 2) {
|
|
3691
|
+
sampleEdgePixel(0, y);
|
|
3692
|
+
sampleEdgePixel(width - 1, y);
|
|
3693
|
+
}
|
|
3694
|
+
let maxCount = 0;
|
|
3695
|
+
let dominantColor = { r: 255, g: 255, b: 255 };
|
|
3696
|
+
for (const { count, color } of colorCounts.values()) {
|
|
3697
|
+
if (count > maxCount) {
|
|
3698
|
+
maxCount = count;
|
|
3699
|
+
dominantColor = color;
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
return dominantColor;
|
|
3703
|
+
}
|
|
3662
3704
|
async function resizeImage(inputPath, outputPath, targetDimensions) {
|
|
3705
|
+
const bgColor = await detectEdgeColor(inputPath);
|
|
3663
3706
|
await sharp2(inputPath).resize(targetDimensions.width, targetDimensions.height, {
|
|
3664
|
-
fit: "
|
|
3665
|
-
//
|
|
3666
|
-
withoutEnlargement: false
|
|
3707
|
+
fit: "contain",
|
|
3708
|
+
// Preserve aspect ratio
|
|
3709
|
+
withoutEnlargement: false,
|
|
3667
3710
|
// Allow enlargement if needed
|
|
3668
|
-
|
|
3711
|
+
background: bgColor
|
|
3712
|
+
// Use detected edge color
|
|
3713
|
+
}).flatten({ background: bgColor }).png().toFile(outputPath + ".tmp");
|
|
3669
3714
|
fs11.renameSync(outputPath + ".tmp", outputPath);
|
|
3670
3715
|
}
|
|
3671
3716
|
async function validateAndResizeImage(sourcePath, translatedPath) {
|
|
@@ -3717,7 +3762,10 @@ var localizeScreenshotsInputSchema = z7.object({
|
|
|
3717
3762
|
),
|
|
3718
3763
|
deviceTypes: z7.array(z7.enum(["phone", "tablet"])).optional().default(["phone", "tablet"]).describe("Device types to process (default: both phone and tablet)"),
|
|
3719
3764
|
dryRun: z7.boolean().optional().default(false).describe("Preview mode - shows what would be translated without actually translating"),
|
|
3720
|
-
skipExisting: z7.boolean().optional().default(true).describe("Skip translation if target file already exists (default: true)")
|
|
3765
|
+
skipExisting: z7.boolean().optional().default(true).describe("Skip translation if target file already exists (default: true)"),
|
|
3766
|
+
screenshotNumbers: z7.array(z7.number().int().positive()).optional().describe(
|
|
3767
|
+
"Specific screenshot numbers to process (e.g., [1, 3, 5]). If not provided, all screenshots will be processed."
|
|
3768
|
+
)
|
|
3721
3769
|
});
|
|
3722
3770
|
var jsonSchema7 = zodToJsonSchema7(localizeScreenshotsInputSchema, {
|
|
3723
3771
|
name: "LocalizeScreenshotsInput",
|
|
@@ -3832,7 +3880,8 @@ async function handleLocalizeScreenshots(input) {
|
|
|
3832
3880
|
targetLocales: requestedTargetLocales,
|
|
3833
3881
|
deviceTypes = ["phone", "tablet"],
|
|
3834
3882
|
dryRun = false,
|
|
3835
|
-
skipExisting = true
|
|
3883
|
+
skipExisting = true,
|
|
3884
|
+
screenshotNumbers
|
|
3836
3885
|
} = input;
|
|
3837
3886
|
const results = [];
|
|
3838
3887
|
let appInfo;
|
|
@@ -3884,9 +3933,20 @@ async function handleLocalizeScreenshots(input) {
|
|
|
3884
3933
|
}
|
|
3885
3934
|
results.push(`\u{1F3AF} Target locales: ${targetLocales.join(", ")}`);
|
|
3886
3935
|
const sourceScreenshots = scanLocaleScreenshots(appInfo.slug, primaryLocale);
|
|
3887
|
-
|
|
3936
|
+
let filteredScreenshots = sourceScreenshots.filter(
|
|
3888
3937
|
(s) => deviceTypes.includes(s.type)
|
|
3889
3938
|
);
|
|
3939
|
+
if (screenshotNumbers && screenshotNumbers.length > 0) {
|
|
3940
|
+
filteredScreenshots = filteredScreenshots.filter((s) => {
|
|
3941
|
+
const match = s.filename.match(/^(\d+)\./);
|
|
3942
|
+
if (match) {
|
|
3943
|
+
const num = parseInt(match[1], 10);
|
|
3944
|
+
return screenshotNumbers.includes(num);
|
|
3945
|
+
}
|
|
3946
|
+
return false;
|
|
3947
|
+
});
|
|
3948
|
+
results.push(`\u{1F522} Filtering screenshots: ${screenshotNumbers.join(", ")}`);
|
|
3949
|
+
}
|
|
3890
3950
|
if (filteredScreenshots.length === 0) {
|
|
3891
3951
|
const screenshotsDir2 = getScreenshotsDir(appInfo.slug);
|
|
3892
3952
|
return {
|