@koda-sl/baker-cli 0.148.0 → 0.149.0-dev.7b64ca6b5
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/README.md +7 -4
- package/dist/{chunk-2F5SCTNS.js → chunk-ZBRVPPJP.js} +4 -4
- package/dist/chunk-ZBRVPPJP.js.map +1 -0
- package/dist/cli.js +152 -55
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2F5SCTNS.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
toModelSafeImage,
|
|
35
35
|
ulid,
|
|
36
36
|
validateCanvasDeep
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-ZBRVPPJP.js";
|
|
38
38
|
import {
|
|
39
39
|
csvOrJson,
|
|
40
40
|
daysAgoIso,
|
|
@@ -2544,6 +2544,13 @@ var imageDocSchema = z8.object({
|
|
|
2544
2544
|
width: z8.number().optional(),
|
|
2545
2545
|
height: z8.number().optional(),
|
|
2546
2546
|
aspectRatio: z8.number().optional(),
|
|
2547
|
+
/** Any non-opaque pixel in the decoded image. */
|
|
2548
|
+
hasAlpha: z8.boolean().optional(),
|
|
2549
|
+
/** Opaque pixels ÷ their bounding-box area, 0..1. Feed with `aspectRatio`
|
|
2550
|
+
* into `classifyLogoShape` to tell a brand wordmark from an app-icon plate
|
|
2551
|
+
* before placing it — the library keeps assets forever, so a bad ingest is
|
|
2552
|
+
* otherwise indistinguishable from a good one months later. */
|
|
2553
|
+
solidity: z8.number().optional(),
|
|
2547
2554
|
dominantColor: z8.string().optional(),
|
|
2548
2555
|
imagePalette: z8.array(z8.string()).optional(),
|
|
2549
2556
|
thumbhashDataUri: z8.string().optional(),
|
|
@@ -2626,6 +2633,13 @@ var imageSearchResultSchema = z8.object({
|
|
|
2626
2633
|
width: z8.number().optional(),
|
|
2627
2634
|
height: z8.number().optional(),
|
|
2628
2635
|
aspectRatio: z8.number().optional(),
|
|
2636
|
+
/** Any non-opaque pixel in the decoded image. */
|
|
2637
|
+
hasAlpha: z8.boolean().optional(),
|
|
2638
|
+
/** Opaque pixels ÷ their bounding-box area, 0..1. Feed with `aspectRatio`
|
|
2639
|
+
* into `classifyLogoShape` to tell a brand wordmark from an app-icon plate
|
|
2640
|
+
* before placing it — the library keeps assets forever, so a bad ingest is
|
|
2641
|
+
* otherwise indistinguishable from a good one months later. */
|
|
2642
|
+
solidity: z8.number().optional(),
|
|
2629
2643
|
dominantColor: z8.string().optional(),
|
|
2630
2644
|
imagePalette: z8.array(z8.string()).optional(),
|
|
2631
2645
|
source: z8.string(),
|
|
@@ -2749,10 +2763,13 @@ var imagesLogoRequestSchema = z8.object({
|
|
|
2749
2763
|
descriptionContext: z8.string().optional()
|
|
2750
2764
|
});
|
|
2751
2765
|
var imagesLogoResponseSchema = providerHitsResponseSchema();
|
|
2766
|
+
var hexColorSchema = z8.string().transform((value) => value.trim().replace(/^%23/i, "#")).refine((value) => /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value), {
|
|
2767
|
+
message: "Expected a hex color like #D7FFA4"
|
|
2768
|
+
}).transform((value) => value.startsWith("#") ? value : `#${value}`);
|
|
2752
2769
|
var imagesIconRequestSchema = z8.object({
|
|
2753
2770
|
name: z8.string().min(1),
|
|
2754
2771
|
set: z8.string().optional(),
|
|
2755
|
-
color:
|
|
2772
|
+
color: hexColorSchema.optional(),
|
|
2756
2773
|
width: z8.coerce.number().int().positive().optional(),
|
|
2757
2774
|
autoIngest: z8.coerce.number().int().min(0).max(20).optional(),
|
|
2758
2775
|
descriptionContext: z8.string().optional()
|
|
@@ -2802,6 +2819,19 @@ var imagesIngestResponseSchema = z8.object({
|
|
|
2802
2819
|
contentHash: z8.string()
|
|
2803
2820
|
});
|
|
2804
2821
|
|
|
2822
|
+
// ../api/src/logoShape.ts
|
|
2823
|
+
var PLATE_SOLIDITY_THRESHOLD = 0.6;
|
|
2824
|
+
var WORDMARK_MIN_ASPECT = 1.8;
|
|
2825
|
+
function classifyLogoShape({
|
|
2826
|
+
aspectRatio: aspectRatio2,
|
|
2827
|
+
hasAlpha,
|
|
2828
|
+
solidity
|
|
2829
|
+
}) {
|
|
2830
|
+
if (solidity === void 0 || aspectRatio2 === void 0) return "unknown";
|
|
2831
|
+
if (solidity >= PLATE_SOLIDITY_THRESHOLD || hasAlpha === false) return "plated-icon";
|
|
2832
|
+
return aspectRatio2 >= WORDMARK_MIN_ASPECT ? "wordmark" : "symbol";
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2805
2835
|
// ../api/src/tags.ts
|
|
2806
2836
|
import { z as z9 } from "zod";
|
|
2807
2837
|
var TAG_TYPES = [
|
|
@@ -5395,27 +5425,17 @@ var googleDraftStageRequestSchema = z13.object({
|
|
|
5395
5425
|
chatId: z13.string(),
|
|
5396
5426
|
op: googleDraftOpInputSchema
|
|
5397
5427
|
});
|
|
5398
|
-
var googleDraftStageResponseSchema = z13.
|
|
5399
|
-
z13.
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
}),
|
|
5410
|
-
z13.object({
|
|
5411
|
-
staged: z13.literal(false),
|
|
5412
|
-
noop: z13.literal(true),
|
|
5413
|
-
kind: googleDraftOpKindSchema,
|
|
5414
|
-
mode: googleWriteModeSchema,
|
|
5415
|
-
summary: z13.string(),
|
|
5416
|
-
reason: z13.string()
|
|
5417
|
-
})
|
|
5418
|
-
]);
|
|
5428
|
+
var googleDraftStageResponseSchema = z13.object({
|
|
5429
|
+
staged: z13.literal(true),
|
|
5430
|
+
ref: z13.string(),
|
|
5431
|
+
kind: googleDraftOpKindSchema,
|
|
5432
|
+
mode: googleWriteModeSchema,
|
|
5433
|
+
dependsOn: z13.array(z13.string()),
|
|
5434
|
+
summary: z13.string(),
|
|
5435
|
+
warnings: z13.array(z13.string()),
|
|
5436
|
+
/** True when the op amended an already-staged op in place instead of appending a new one. */
|
|
5437
|
+
amended: z13.boolean().optional()
|
|
5438
|
+
});
|
|
5419
5439
|
var googleDraftAmendRequestSchema = z13.object({
|
|
5420
5440
|
chatId: z13.string(),
|
|
5421
5441
|
ref: z13.string(),
|
|
@@ -5442,8 +5462,7 @@ var googleDraftStageBatchResponseSchema = z13.object({
|
|
|
5442
5462
|
summary: z13.string(),
|
|
5443
5463
|
warnings: z13.array(z13.string())
|
|
5444
5464
|
})
|
|
5445
|
-
)
|
|
5446
|
-
skipped: z13.array(z13.object({ kind: googleDraftOpKindSchema, summary: z13.string(), reason: z13.string() })).optional()
|
|
5465
|
+
)
|
|
5447
5466
|
});
|
|
5448
5467
|
var googleDraftOpViewSchema = z13.object({
|
|
5449
5468
|
ref: z13.string(),
|
|
@@ -5702,7 +5721,7 @@ function keywordEntries(args) {
|
|
|
5702
5721
|
const seen = /* @__PURE__ */ new Set();
|
|
5703
5722
|
for (const item of raw) {
|
|
5704
5723
|
const entry = parseKeywordEntry(item, defaultMatch);
|
|
5705
|
-
const key =
|
|
5724
|
+
const key = `${entry.text}\0${entry.matchType}`;
|
|
5706
5725
|
if (!seen.has(key)) {
|
|
5707
5726
|
seen.add(key);
|
|
5708
5727
|
entries.push(entry);
|
|
@@ -5769,9 +5788,6 @@ function handleGoogleError(err) {
|
|
|
5769
5788
|
});
|
|
5770
5789
|
process.exit(1);
|
|
5771
5790
|
}
|
|
5772
|
-
function noopHints(data) {
|
|
5773
|
-
return data.staged ? [] : [`NOT STAGED \u2014 ${data.reason}. Nothing to publish for this change; say so rather than reporting it as done.`];
|
|
5774
|
-
}
|
|
5775
5791
|
async function stageGoogleOp(raw, hints) {
|
|
5776
5792
|
const preflight = googleDraftOpInputSchema.safeParse(raw);
|
|
5777
5793
|
if (!preflight.success) {
|
|
@@ -5789,8 +5805,7 @@ async function stageGoogleOp(raw, hints) {
|
|
|
5789
5805
|
try {
|
|
5790
5806
|
const chatId = requireChatId();
|
|
5791
5807
|
const response = await apiPost("/api/ads/google/draft/stage", { chatId, op: preflight.data });
|
|
5792
|
-
|
|
5793
|
-
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
5808
|
+
writeJsonEnvelope(hints && hints.length > 0 ? { ...response, hints } : response);
|
|
5794
5809
|
} catch (err) {
|
|
5795
5810
|
handleGoogleError(err);
|
|
5796
5811
|
}
|
|
@@ -5826,14 +5841,7 @@ async function stageGoogleOps(rawOps, hints) {
|
|
|
5826
5841
|
try {
|
|
5827
5842
|
const chatId = requireChatId();
|
|
5828
5843
|
const response = await apiPost("/api/ads/google/draft/stage-batch", { chatId, ops });
|
|
5829
|
-
|
|
5830
|
-
const allHints = [
|
|
5831
|
-
...skipped.length > 0 ? [
|
|
5832
|
-
`${skipped.length} of ${ops.length} op(s) NOT STAGED \u2014 already in the requested state: ${skipped.map((s) => s.reason).join("; ")}`
|
|
5833
|
-
] : [],
|
|
5834
|
-
...hints ?? []
|
|
5835
|
-
];
|
|
5836
|
-
writeJsonEnvelope(allHints.length > 0 ? { ...response, hints: allHints } : response);
|
|
5844
|
+
writeJsonEnvelope(hints && hints.length > 0 ? { ...response, hints } : response);
|
|
5837
5845
|
} catch (err) {
|
|
5838
5846
|
handleGoogleError(err);
|
|
5839
5847
|
}
|
|
@@ -24492,6 +24500,31 @@ var ingestCommand = defineCommand119({
|
|
|
24492
24500
|
|
|
24493
24501
|
// src/commands/images/library.ts
|
|
24494
24502
|
import { defineCommand as defineCommand120 } from "citty";
|
|
24503
|
+
|
|
24504
|
+
// src/commands/images/logoHints.ts
|
|
24505
|
+
var LOGO_QUERY_RE = /\blogos?\b|\bwordmark\b|\bbrand mark\b/i;
|
|
24506
|
+
function withLogoShape(row) {
|
|
24507
|
+
return {
|
|
24508
|
+
...row,
|
|
24509
|
+
logoShape: classifyLogoShape({
|
|
24510
|
+
aspectRatio: row.aspectRatio,
|
|
24511
|
+
hasAlpha: row.hasAlpha,
|
|
24512
|
+
solidity: row.solidity
|
|
24513
|
+
})
|
|
24514
|
+
};
|
|
24515
|
+
}
|
|
24516
|
+
function buildLogoLibraryHints(query, rows) {
|
|
24517
|
+
if (!LOGO_QUERY_RE.test(query)) return [];
|
|
24518
|
+
const plates = rows.filter((row) => row.logoShape === "plated-icon");
|
|
24519
|
+
if (plates.length === 0) return [];
|
|
24520
|
+
const names = plates.map((row) => row.name).filter((name) => Boolean(name)).slice(0, 4);
|
|
24521
|
+
const subject = names.length > 0 ? names.join(", ") : `${plates.length} result(s)`;
|
|
24522
|
+
return [
|
|
24523
|
+
`PLATED ICON: ${subject} \u2014 solid tile with the mark knocked out, not a wordmark. In a logo strip it renders as a filled box and verify blocks it (logo-plate). Re-source with 'baker images logo <domain> --variant logo', or strip the plate with 'baker images normalize <file> --remove-bg --shrink-to-content'. Only use a plate in slots under ~32px.`
|
|
24524
|
+
];
|
|
24525
|
+
}
|
|
24526
|
+
|
|
24527
|
+
// src/commands/images/library.ts
|
|
24495
24528
|
registerSchema({
|
|
24496
24529
|
command: "images.library",
|
|
24497
24530
|
description: "Search the company image library. Returns only ready images.",
|
|
@@ -24556,8 +24589,10 @@ var libraryCommand = defineCommand120({
|
|
|
24556
24589
|
if (minScore !== void 0) {
|
|
24557
24590
|
data = data.filter((r) => typeof r.score === "number" && r.score >= minScore);
|
|
24558
24591
|
}
|
|
24592
|
+
const shaped = data.map(withLogoShape);
|
|
24593
|
+
const hints = buildLogoLibraryHints(query, shaped);
|
|
24559
24594
|
writeOutput(
|
|
24560
|
-
{ ok: true, data },
|
|
24595
|
+
{ ok: true, data: shaped, ...hints.length > 0 ? { hints } : {} },
|
|
24561
24596
|
args.output || "json",
|
|
24562
24597
|
args.fields ? args.fields.split(",") : void 0,
|
|
24563
24598
|
args.full
|
|
@@ -24575,11 +24610,16 @@ var libraryCommand = defineCommand120({
|
|
|
24575
24610
|
|
|
24576
24611
|
// src/commands/images/logo.ts
|
|
24577
24612
|
import { defineCommand as defineCommand121 } from "citty";
|
|
24613
|
+
var MAX_DOMAINS = 20;
|
|
24578
24614
|
registerSchema({
|
|
24579
24615
|
command: "images.logo",
|
|
24580
24616
|
description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
|
|
24581
24617
|
args: {
|
|
24582
|
-
domain: {
|
|
24618
|
+
domain: {
|
|
24619
|
+
type: "string",
|
|
24620
|
+
description: "Brand domain, or a comma-separated list for a whole strip (e.g. stripe.com,intercom.com)",
|
|
24621
|
+
required: true
|
|
24622
|
+
},
|
|
24583
24623
|
variant: { type: "string", description: "icon | logo | symbol", required: false },
|
|
24584
24624
|
"auto-ingest": {
|
|
24585
24625
|
type: "number",
|
|
@@ -24602,10 +24642,10 @@ registerSchema({
|
|
|
24602
24642
|
var logoCommand = defineCommand121({
|
|
24603
24643
|
meta: {
|
|
24604
24644
|
name: "logo",
|
|
24605
|
-
description: "Brand logo via Brandfetch CDN. Returns up to 5 variants (icon, light/dark logo, light/dark symbol). Auto-ingests the first variant.\n\
|
|
24645
|
+
description: "Brand logo via Brandfetch CDN. Returns up to 5 variants (icon, light/dark logo, light/dark symbol). Auto-ingests the first variant.\n\nSource a whole strip in one call by passing a comma-separated list \u2014 a text-rendered brand name is never the cheaper option.\n\nExamples:\n baker images logo stripe.com --variant logo\n baker images logo stripe.com,intercom.com,notion.so --variant logo"
|
|
24606
24646
|
},
|
|
24607
24647
|
args: {
|
|
24608
|
-
domain: { type: "positional", description: "Brand domain", required: false },
|
|
24648
|
+
domain: { type: "positional", description: "Brand domain, or a comma-separated list", required: false },
|
|
24609
24649
|
variant: { type: "string", description: "icon|logo|symbol", required: false },
|
|
24610
24650
|
"auto-ingest": { type: "string", description: "Ingest top N (0-20, default 1)", required: false },
|
|
24611
24651
|
"no-auto-ingest": { type: "boolean", description: "Skip auto-ingest", required: false },
|
|
@@ -24613,18 +24653,50 @@ var logoCommand = defineCommand121({
|
|
|
24613
24653
|
},
|
|
24614
24654
|
run: async ({ args }) => {
|
|
24615
24655
|
try {
|
|
24616
|
-
const
|
|
24617
|
-
|
|
24656
|
+
const raw = args.domain;
|
|
24657
|
+
const domains = [
|
|
24658
|
+
...new Set(
|
|
24659
|
+
(raw ?? "").split(",").map((d) => d.trim()).filter(Boolean)
|
|
24660
|
+
)
|
|
24661
|
+
];
|
|
24662
|
+
if (domains.length === 0) {
|
|
24618
24663
|
writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Domain is required" } });
|
|
24619
24664
|
process.exit(1);
|
|
24620
24665
|
}
|
|
24621
|
-
|
|
24622
|
-
|
|
24623
|
-
|
|
24624
|
-
|
|
24625
|
-
|
|
24626
|
-
|
|
24627
|
-
|
|
24666
|
+
if (domains.length > MAX_DOMAINS) {
|
|
24667
|
+
writeJson({
|
|
24668
|
+
ok: false,
|
|
24669
|
+
error: {
|
|
24670
|
+
code: "VALIDATION_ERROR",
|
|
24671
|
+
message: `Too many domains (${domains.length}); pass at most ${MAX_DOMAINS} per call`
|
|
24672
|
+
}
|
|
24673
|
+
});
|
|
24674
|
+
process.exit(1);
|
|
24675
|
+
}
|
|
24676
|
+
const base = {};
|
|
24677
|
+
if (args.variant) base.variant = args.variant;
|
|
24678
|
+
if (args["auto-ingest"] !== void 0) base.autoIngest = Number(args["auto-ingest"]);
|
|
24679
|
+
else if (args["no-auto-ingest"]) base.autoIngest = 0;
|
|
24680
|
+
if (args.context) base.descriptionContext = args.context;
|
|
24681
|
+
const fetchOne = (domain) => apiPost("/api/images/logo", { ...base, domain });
|
|
24682
|
+
if (domains.length === 1) {
|
|
24683
|
+
writeJson({ ok: true, data: await fetchOne(domains[0]) });
|
|
24684
|
+
return;
|
|
24685
|
+
}
|
|
24686
|
+
const settled = await Promise.all(
|
|
24687
|
+
domains.map(async (domain) => {
|
|
24688
|
+
try {
|
|
24689
|
+
return { domain, ...await fetchOne(domain) };
|
|
24690
|
+
} catch (err) {
|
|
24691
|
+
return { domain, hits: [], error: err instanceof ApiError ? err.message : "Lookup failed" };
|
|
24692
|
+
}
|
|
24693
|
+
})
|
|
24694
|
+
);
|
|
24695
|
+
const empty = settled.filter((r) => r.hits.length === 0).map((r) => r.domain);
|
|
24696
|
+
const hints = empty.length > 0 ? [
|
|
24697
|
+
`NO LOGO: ${empty.join(", ")} \u2014 Brandfetch doesn't know ${empty.length === 1 ? "this brand" : "these brands"}. Fall back per domain: 'baker images extract <domain> --auto-ingest 5', then 'baker images icon <brand> --set simple-icons'. Still nothing \u2192 'baker actions create' to acquire the file. Do not render the name as text.`
|
|
24698
|
+
] : [];
|
|
24699
|
+
writeJson({ ok: true, data: { results: settled }, ...hints.length > 0 ? { hints } : {} });
|
|
24628
24700
|
} catch (err) {
|
|
24629
24701
|
if (err instanceof ApiError) {
|
|
24630
24702
|
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
@@ -24668,6 +24740,7 @@ function getDominantEdgeColor(data, width, height) {
|
|
|
24668
24740
|
const colorCount = {};
|
|
24669
24741
|
function accumulateColor(i, j) {
|
|
24670
24742
|
const idx = (i * width + j) * 4;
|
|
24743
|
+
if ((data[idx + 3] ?? 0) < 10) return;
|
|
24671
24744
|
const colorKey = `${data[idx]},${data[idx + 1]},${data[idx + 2]}`;
|
|
24672
24745
|
colorCount[colorKey] = (colorCount[colorKey] ?? 0) + 1;
|
|
24673
24746
|
}
|
|
@@ -24680,7 +24753,7 @@ function getDominantEdgeColor(data, width, height) {
|
|
|
24680
24753
|
accumulateColor(i, width - 1);
|
|
24681
24754
|
}
|
|
24682
24755
|
let maxCount = 0;
|
|
24683
|
-
let dominantColor =
|
|
24756
|
+
let dominantColor = null;
|
|
24684
24757
|
for (const key in colorCount) {
|
|
24685
24758
|
const count = colorCount[key];
|
|
24686
24759
|
if (count > maxCount) {
|
|
@@ -24691,6 +24764,27 @@ function getDominantEdgeColor(data, width, height) {
|
|
|
24691
24764
|
}
|
|
24692
24765
|
return dominantColor;
|
|
24693
24766
|
}
|
|
24767
|
+
function opaqueSolidity(data, width, height) {
|
|
24768
|
+
let minX = width;
|
|
24769
|
+
let minY = height;
|
|
24770
|
+
let maxX = -1;
|
|
24771
|
+
let maxY = -1;
|
|
24772
|
+
let opaque = 0;
|
|
24773
|
+
for (let y = 0; y < height; y++) {
|
|
24774
|
+
for (let x = 0; x < width; x++) {
|
|
24775
|
+
if ((data[(y * width + x) * 4 + 3] ?? 0) <= 200) continue;
|
|
24776
|
+
opaque++;
|
|
24777
|
+
if (x < minX) minX = x;
|
|
24778
|
+
if (x > maxX) maxX = x;
|
|
24779
|
+
if (y < minY) minY = y;
|
|
24780
|
+
if (y > maxY) maxY = y;
|
|
24781
|
+
}
|
|
24782
|
+
}
|
|
24783
|
+
if (maxX < 0) return 0;
|
|
24784
|
+
const boxArea = (maxX - minX + 1) * (maxY - minY + 1);
|
|
24785
|
+
return boxArea === 0 ? 0 : opaque / boxArea;
|
|
24786
|
+
}
|
|
24787
|
+
var PLATE_SOLIDITY_THRESHOLD2 = 0.6;
|
|
24694
24788
|
function hasTransparency(data, threshold = 0.02) {
|
|
24695
24789
|
let transparentPixels = 0;
|
|
24696
24790
|
let totalPixels = 0;
|
|
@@ -24755,6 +24849,9 @@ function removeBackground(data, width, height, colorRangeThreshold = COLOR_RANGE
|
|
|
24755
24849
|
return data;
|
|
24756
24850
|
}
|
|
24757
24851
|
const dominantEdgeColor = getDominantEdgeColor(data, width, height);
|
|
24852
|
+
if (!dominantEdgeColor) {
|
|
24853
|
+
return data;
|
|
24854
|
+
}
|
|
24758
24855
|
const isGradient = hasGradientColors(data);
|
|
24759
24856
|
const result = Buffer.from(data);
|
|
24760
24857
|
if (isGradient) {
|
|
@@ -25032,8 +25129,8 @@ async function processInternal(inputBuffer, isSVG, options) {
|
|
|
25032
25129
|
const metadata = await sharp3(inputBuffer).metadata();
|
|
25033
25130
|
let alreadyTransparent = false;
|
|
25034
25131
|
if (metadata.hasAlpha) {
|
|
25035
|
-
const { data: alphaData } = await sharp3(inputBuffer).raw().toBuffer({ resolveWithObject: true });
|
|
25036
|
-
alreadyTransparent =
|
|
25132
|
+
const { data: alphaData, info: info2 } = await sharp3(inputBuffer).raw().toBuffer({ resolveWithObject: true });
|
|
25133
|
+
alreadyTransparent = opaqueSolidity(alphaData, info2.width, info2.height) < PLATE_SOLIDITY_THRESHOLD2;
|
|
25037
25134
|
}
|
|
25038
25135
|
let { data: processedData, info } = await sharp3(inputBuffer).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
25039
25136
|
if (options.color) {
|