mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-09-14 13:36:36 +00:00
feat: update convert and analyze tools to new types
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import type { ToolEntry } from "./types";
|
import { imgTool, textGen, type ToolEntry } from "./types";
|
||||||
import { field, toolSchema } from "../registry-schema";
|
import { field, toolSchema } from "../registry-schema";
|
||||||
import {
|
import {
|
||||||
extractByColor,
|
extractByColor,
|
||||||
@@ -28,7 +28,8 @@ const extractColor: ToolEntry<ExtractColorParams> = {
|
|||||||
"Keeps only pixels close to the chosen color and makes everything else transparent — the inverse of Remove Color.",
|
"Keeps only pixels close to the chosen color and makes everything else transparent — the inverse of Remove Color.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: extractColorSchema,
|
schema: extractColorSchema,
|
||||||
run: (img, p) => extractByColor(img, p.color, p.tolerance),
|
input: "image",
|
||||||
|
run: imgTool((img, p) => extractByColor(img, p.color, p.tolerance)),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface MaskParams {
|
interface MaskParams {
|
||||||
@@ -79,7 +80,8 @@ const showTransparent: ToolEntry<MaskParams> = {
|
|||||||
"Highlights every transparent or semi-transparent pixel with the chosen color so gaps become obvious.",
|
"Highlights every transparent or semi-transparent pixel with the chosen color so gaps become obvious.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: showTransparentSchema,
|
schema: showTransparentSchema,
|
||||||
run: (img, p) => renderMask(img, p, (_r, _g, _b, a) => a < 255),
|
input: "image",
|
||||||
|
run: imgTool((img, p) => renderMask(img, p, (_r, _g, _b, a) => a < 255)),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface GrayscalePixelsParams extends MaskParams {
|
interface GrayscalePixelsParams extends MaskParams {
|
||||||
@@ -98,8 +100,10 @@ const showGrayscalePixels: ToolEntry<GrayscalePixelsParams> = {
|
|||||||
"Finds pixels whose channels are nearly equal and renders them as a mask. Tolerance is in channel units.",
|
"Finds pixels whose channels are nearly equal and renders them as a mask. Tolerance is in channel units.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: showGrayscalePixelsSchema,
|
schema: showGrayscalePixelsSchema,
|
||||||
run: (img, p) =>
|
input: "image",
|
||||||
|
run: imgTool((img, p) =>
|
||||||
renderMask(img, p, (r, g, b) => isGrayscaleish(r, g, b, p.tolerance)),
|
renderMask(img, p, (r, g, b) => isGrayscaleish(r, g, b, p.tolerance)),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ColorPixelsParams extends MaskParams {
|
interface ColorPixelsParams extends MaskParams {
|
||||||
@@ -118,8 +122,10 @@ const showColorPixels: ToolEntry<ColorPixelsParams> = {
|
|||||||
"Finds colored (non-gray) pixels beyond the channel tolerance and renders them as a mask.",
|
"Finds colored (non-gray) pixels beyond the channel tolerance and renders them as a mask.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: showColorPixelsSchema,
|
schema: showColorPixelsSchema,
|
||||||
run: (img, p) =>
|
input: "image",
|
||||||
|
run: imgTool((img, p) =>
|
||||||
renderMask(img, p, (r, g, b) => !isGrayscaleish(r, g, b, p.tolerance)),
|
renderMask(img, p, (r, g, b) => !isGrayscaleish(r, g, b, p.tolerance)),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface LightPixelParams extends MaskParams {
|
interface LightPixelParams extends MaskParams {
|
||||||
@@ -137,8 +143,10 @@ const lightPixelMask: ToolEntry<LightPixelParams> = {
|
|||||||
description: "Selects pixels brighter than the luminance threshold.",
|
description: "Selects pixels brighter than the luminance threshold.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: lightPixelMaskSchema,
|
schema: lightPixelMaskSchema,
|
||||||
run: (img, p) =>
|
input: "image",
|
||||||
|
run: imgTool((img, p) =>
|
||||||
renderMask(img, p, (r, g, b) => luma01(r, g, b) >= p.threshold / 100),
|
renderMask(img, p, (r, g, b) => luma01(r, g, b) >= p.threshold / 100),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface DarkPixelParams extends MaskParams {
|
interface DarkPixelParams extends MaskParams {
|
||||||
@@ -156,8 +164,10 @@ const darkPixelMask: ToolEntry<DarkPixelParams> = {
|
|||||||
description: "Selects pixels darker than the luminance threshold.",
|
description: "Selects pixels darker than the luminance threshold.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: darkPixelMaskSchema,
|
schema: darkPixelMaskSchema,
|
||||||
run: (img, p) =>
|
input: "image",
|
||||||
|
run: imgTool((img, p) =>
|
||||||
renderMask(img, p, (r, g, b) => luma01(r, g, b) <= p.threshold / 100),
|
renderMask(img, p, (r, g, b) => luma01(r, g, b) <= p.threshold / 100),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface UniqueColorParams extends MaskParams {
|
interface UniqueColorParams extends MaskParams {
|
||||||
@@ -176,7 +186,8 @@ const uniqueColorMask: ToolEntry<UniqueColorParams> = {
|
|||||||
"Selects colors that occur no more than the given number of times — rare and one-off pixels.",
|
"Selects colors that occur no more than the given number of times — rare and one-off pixels.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: uniqueColorMaskSchema,
|
schema: uniqueColorMaskSchema,
|
||||||
run: (img, p) => renderMask(img, p, rarityPredicate(img, p.rarity)),
|
input: "image",
|
||||||
|
run: imgTool((img, p) => renderMask(img, p, rarityPredicate(img, p.rarity))),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface NoParams {}
|
interface NoParams {}
|
||||||
@@ -192,10 +203,11 @@ const verifyIsPng: ToolEntry<NoParams> = {
|
|||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
input: "text",
|
input: "text",
|
||||||
result: "verdict",
|
result: "verdict",
|
||||||
textToText: (text) =>
|
run: textGen((text) =>
|
||||||
looksLikePng(base64ToBytes(stripDataUri(text)))
|
looksLikePng(base64ToBytes(stripDataUri(text)))
|
||||||
? "Yes — valid PNG signature."
|
? "Yes — valid PNG signature."
|
||||||
: "No — the content is not a PNG.",
|
: "No — the content is not a PNG.",
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngIsGrayscale: ToolEntry<NoParams> = {
|
const pngIsGrayscale: ToolEntry<NoParams> = {
|
||||||
@@ -204,9 +216,11 @@ const pngIsGrayscale: ToolEntry<NoParams> = {
|
|||||||
description: "Reports whether the image consists only of shades of gray.",
|
description: "Reports whether the image consists only of shades of gray.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
|
input: "image",
|
||||||
result: "verdict",
|
result: "verdict",
|
||||||
toText: (img) =>
|
run: imgTool((img) =>
|
||||||
isGrayscale(img) ? "Yes — grayscale." : "No — contains colors.",
|
isGrayscale(img) ? "Yes — grayscale." : "No — contains colors.",
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngFileSize: ToolEntry<NoParams> = {
|
const pngFileSize: ToolEntry<NoParams> = {
|
||||||
@@ -216,13 +230,14 @@ const pngFileSize: ToolEntry<NoParams> = {
|
|||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
domOnly: true,
|
domOnly: true,
|
||||||
|
input: "image",
|
||||||
result: "verdict",
|
result: "verdict",
|
||||||
toText: async (img) => {
|
run: imgTool(async (img) => {
|
||||||
const blob = await encode(img, "image/png");
|
const blob = await encode(img, "image/png");
|
||||||
const kb = blob.size / 1024;
|
const kb = blob.size / 1024;
|
||||||
const kbText = kb >= 100 ? Math.round(kb).toString() : kb.toFixed(1);
|
const kbText = kb >= 100 ? Math.round(kb).toString() : kb.toFixed(1);
|
||||||
return `${kbText} KB`;
|
return `${kbText} KB`;
|
||||||
},
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngIsTransparent: ToolEntry<NoParams> = {
|
const pngIsTransparent: ToolEntry<NoParams> = {
|
||||||
@@ -232,9 +247,11 @@ const pngIsTransparent: ToolEntry<NoParams> = {
|
|||||||
"Reports whether the image contains transparent or semi-transparent pixels.",
|
"Reports whether the image contains transparent or semi-transparent pixels.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
|
input: "image",
|
||||||
result: "verdict",
|
result: "verdict",
|
||||||
toText: (img) =>
|
run: imgTool((img) =>
|
||||||
hasTransparency(img) ? "Yes — has transparency." : "No — fully opaque.",
|
hasTransparency(img) ? "Yes — has transparency." : "No — fully opaque.",
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngOrientation: ToolEntry<NoParams> = {
|
const pngOrientation: ToolEntry<NoParams> = {
|
||||||
@@ -243,8 +260,9 @@ const pngOrientation: ToolEntry<NoParams> = {
|
|||||||
description: "Reports whether it is portrait, landscape or square.",
|
description: "Reports whether it is portrait, landscape or square.",
|
||||||
category: "analyze",
|
category: "analyze",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
|
input: "image",
|
||||||
result: "verdict",
|
result: "verdict",
|
||||||
toText: (img) => {
|
run: imgTool((img) => {
|
||||||
switch (orientationOf(img)) {
|
switch (orientationOf(img)) {
|
||||||
case "portrait":
|
case "portrait":
|
||||||
return "Portrait";
|
return "Portrait";
|
||||||
@@ -253,7 +271,7 @@ const pngOrientation: ToolEntry<NoParams> = {
|
|||||||
default:
|
default:
|
||||||
return "Square";
|
return "Square";
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const analyzeEntries = [
|
export const analyzeEntries = [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ToolEntry } from "./types";
|
import { imgTool, textGen, type ToolEntry } from "./types";
|
||||||
import { field, toolSchema } from "../registry-schema";
|
import { field, toolSchema } from "../registry-schema";
|
||||||
import { flattenOntoColor } from "../core/alpha";
|
import { flattenOntoColor } from "../core/alpha";
|
||||||
import {
|
import {
|
||||||
@@ -33,7 +33,8 @@ const convertToJpg: ToolEntry<ConvertToJpgParams> = {
|
|||||||
"Transparency is composited over the chosen backdrop color (white by default) and saved as JPEG.",
|
"Transparency is composited over the chosen backdrop color (white by default) and saved as JPEG.",
|
||||||
category: "convert",
|
category: "convert",
|
||||||
schema: convertToJpgSchema,
|
schema: convertToJpgSchema,
|
||||||
run: (img, p) => flattenOntoColor(img, p.background),
|
input: "image",
|
||||||
|
run: imgTool((img, p) => flattenOntoColor(img, p.background)),
|
||||||
output: { mime: "image/jpeg", ext: "jpg", qualityParamId: "quality" },
|
output: { mime: "image/jpeg", ext: "jpg", qualityParamId: "quality" },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -52,7 +53,8 @@ const convertToWebp: ToolEntry<ConvertToWebpParams> = {
|
|||||||
"Re-encodes the image into WebP with adjustable quality. Transparency is preserved.",
|
"Re-encodes the image into WebP with adjustable quality. Transparency is preserved.",
|
||||||
category: "convert",
|
category: "convert",
|
||||||
schema: convertToWebpSchema,
|
schema: convertToWebpSchema,
|
||||||
run: (img) => clonePixelImage(img),
|
input: "image",
|
||||||
|
run: imgTool((img) => clonePixelImage(img)),
|
||||||
output: { mime: "image/webp", ext: "webp", qualityParamId: "quality" },
|
output: { mime: "image/webp", ext: "webp", qualityParamId: "quality" },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,7 +69,8 @@ const convertToBmp: ToolEntry<ConvertToBmpParams> = {
|
|||||||
"Saves the image as 24-bit BMP without an alpha channel: transparency is replaced with a black background.",
|
"Saves the image as 24-bit BMP without an alpha channel: transparency is replaced with a black background.",
|
||||||
category: "convert",
|
category: "convert",
|
||||||
schema: convertToBmpSchema,
|
schema: convertToBmpSchema,
|
||||||
run: (img) => flattenOntoColor(img, "#000000"),
|
input: "image",
|
||||||
|
run: imgTool((img) => flattenOntoColor(img, "#000000")),
|
||||||
output: { mime: "image/bmp", ext: "bmp" },
|
output: { mime: "image/bmp", ext: "bmp" },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -82,8 +85,9 @@ const pngToBase64: ToolEntry<NoParams> = {
|
|||||||
"Encodes the image into a base64 string for embedding in code or styles.",
|
"Encodes the image into a base64 string for embedding in code or styles.",
|
||||||
category: "convert",
|
category: "convert",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
|
input: "image",
|
||||||
result: "text",
|
result: "text",
|
||||||
toText: (img) => toBase64(img),
|
run: imgTool((img) => toBase64(img)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngToDataUri: ToolEntry<NoParams> = {
|
const pngToDataUri: ToolEntry<NoParams> = {
|
||||||
@@ -93,8 +97,9 @@ const pngToDataUri: ToolEntry<NoParams> = {
|
|||||||
"Builds a full data-uri (data:image/png;base64,…) for embedding in HTML/CSS.",
|
"Builds a full data-uri (data:image/png;base64,…) for embedding in HTML/CSS.",
|
||||||
category: "convert",
|
category: "convert",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
|
input: "image",
|
||||||
result: "text",
|
result: "text",
|
||||||
toText: (img) => toDataUrl(img),
|
run: imgTool((img) => toDataUrl(img)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngToHex: ToolEntry<NoParams> = {
|
const pngToHex: ToolEntry<NoParams> = {
|
||||||
@@ -104,8 +109,9 @@ const pngToHex: ToolEntry<NoParams> = {
|
|||||||
"Shows all pixels as rrggbbaa hex values — row by row, space separated.",
|
"Shows all pixels as rrggbbaa hex values — row by row, space separated.",
|
||||||
category: "convert",
|
category: "convert",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
|
input: "image",
|
||||||
result: "text",
|
result: "text",
|
||||||
toText: (img) => pixelsToHex(img),
|
run: imgTool((img) => pixelsToHex(img)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngToBytes: ToolEntry<NoParams> = {
|
const pngToBytes: ToolEntry<NoParams> = {
|
||||||
@@ -115,8 +121,9 @@ const pngToBytes: ToolEntry<NoParams> = {
|
|||||||
"Lists every pixel as four decimal bytes (R G B A), one image row per line.",
|
"Lists every pixel as four decimal bytes (R G B A), one image row per line.",
|
||||||
category: "convert",
|
category: "convert",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
|
input: "image",
|
||||||
result: "text",
|
result: "text",
|
||||||
toText: (img) => imageToByteRows(img),
|
run: imgTool((img) => imageToByteRows(img)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const pngToRgbValues: ToolEntry<NoParams> = {
|
const pngToRgbValues: ToolEntry<NoParams> = {
|
||||||
@@ -125,8 +132,9 @@ const pngToRgbValues: ToolEntry<NoParams> = {
|
|||||||
description: "Lists every pixel as rgba(r, g, b, a), one image row per line.",
|
description: "Lists every pixel as rgba(r, g, b, a), one image row per line.",
|
||||||
category: "convert",
|
category: "convert",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
|
input: "image",
|
||||||
result: "text",
|
result: "text",
|
||||||
toText: (img) => imageToRgbValues(img),
|
run: imgTool((img) => imageToRgbValues(img)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const base64ToPng: ToolEntry<NoParams> = {
|
const base64ToPng: ToolEntry<NoParams> = {
|
||||||
@@ -137,7 +145,7 @@ const base64ToPng: ToolEntry<NoParams> = {
|
|||||||
category: "convert",
|
category: "convert",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
input: "text",
|
input: "text",
|
||||||
runFromText: async (text) => decodeBytes(base64ToBytes(stripDataUri(text))),
|
run: textGen((text) => decodeBytes(base64ToBytes(stripDataUri(text)))),
|
||||||
};
|
};
|
||||||
|
|
||||||
const dataUriToPng: ToolEntry<NoParams> = {
|
const dataUriToPng: ToolEntry<NoParams> = {
|
||||||
@@ -147,7 +155,7 @@ const dataUriToPng: ToolEntry<NoParams> = {
|
|||||||
category: "convert",
|
category: "convert",
|
||||||
schema: emptySchema,
|
schema: emptySchema,
|
||||||
input: "text",
|
input: "text",
|
||||||
runFromText: async (text) => decodeBytes(base64ToBytes(stripDataUri(text))),
|
run: textGen((text) => decodeBytes(base64ToBytes(stripDataUri(text)))),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface HexToPngParams {
|
interface HexToPngParams {
|
||||||
@@ -166,7 +174,7 @@ const hexToPng: ToolEntry<HexToPngParams> = {
|
|||||||
category: "convert",
|
category: "convert",
|
||||||
schema: hexToPngSchema,
|
schema: hexToPngSchema,
|
||||||
input: "text",
|
input: "text",
|
||||||
runFromText: (text, p) => hexToPixels(text, Math.trunc(p.width)),
|
run: textGen((text, p) => hexToPixels(text, Math.trunc(p.width))),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface BytesToPngParams {
|
interface BytesToPngParams {
|
||||||
@@ -185,7 +193,7 @@ const bytesToPng: ToolEntry<BytesToPngParams> = {
|
|||||||
category: "convert",
|
category: "convert",
|
||||||
schema: bytesToPngSchema,
|
schema: bytesToPngSchema,
|
||||||
input: "text",
|
input: "text",
|
||||||
runFromText: (text, p) => bytesToImage(text, Math.trunc(p.width)),
|
run: textGen((text, p) => bytesToImage(text, Math.trunc(p.width))),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface RgbValuesToPngParams {
|
interface RgbValuesToPngParams {
|
||||||
@@ -204,7 +212,7 @@ const rgbValuesToPng: ToolEntry<RgbValuesToPngParams> = {
|
|||||||
category: "convert",
|
category: "convert",
|
||||||
schema: rgbValuesToPngSchema,
|
schema: rgbValuesToPngSchema,
|
||||||
input: "text",
|
input: "text",
|
||||||
runFromText: (text, p) => rgbValuesToImage(text, Math.trunc(p.width)),
|
run: textGen((text, p) => rgbValuesToImage(text, Math.trunc(p.width))),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface SvgToPngParams {
|
interface SvgToPngParams {
|
||||||
@@ -224,7 +232,7 @@ const svgToPng: ToolEntry<SvgToPngParams> = {
|
|||||||
schema: svgToPngSchema,
|
schema: svgToPngSchema,
|
||||||
input: "text",
|
input: "text",
|
||||||
domOnly: true,
|
domOnly: true,
|
||||||
runFromText: (text, p) => decodeSvgText(text, Math.trunc(p.width)),
|
run: textGen((text, p) => decodeSvgText(text, Math.trunc(p.width))),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const convertEntries = [
|
export const convertEntries = [
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { ToolError } from "../core/errors";
|
||||||
|
import type { OutputMime } from "../core/io";
|
||||||
|
import type { PixelImage } from "../core/types";
|
||||||
import type { CategoryId } from "../preview/categories";
|
import type { CategoryId } from "../preview/categories";
|
||||||
import type { ToolSchema } from "../registry-schema";
|
import type { ToolSchema } from "../registry-schema";
|
||||||
import type { PixelImage } from "../core/types";
|
|
||||||
import type { OutputMime } from "../core/io";
|
|
||||||
import { ToolError } from "../core/errors";
|
|
||||||
|
|
||||||
/** Формат скачивания, отличный от PNG (bmp/jpeg/webp). */
|
/** Формат скачивания, отличный от PNG (bmp/jpeg/webp). */
|
||||||
export interface OutputFormat {
|
export interface OutputFormat {
|
||||||
@@ -83,21 +83,21 @@ export function requireText<P>(ctx: ToolContext<P>): string {
|
|||||||
* из контекста. Позволяет оставить тело инструмента в виде `(img, p) => …`.
|
* из контекста. Позволяет оставить тело инструмента в виде `(img, p) => …`.
|
||||||
*/
|
*/
|
||||||
export function imgTool<P>(
|
export function imgTool<P>(
|
||||||
fn: (img: PixelImage, params: P) => ToolResult,
|
fn: (img: PixelImage, params: P) => ToolResult | Promise<ToolResult>,
|
||||||
): (ctx: ToolContext<P>) => ToolResult {
|
): (ctx: ToolContext<P>) => ToolResult | Promise<ToolResult> {
|
||||||
return (ctx) => fn(requireSource(ctx), ctx.params);
|
return (ctx) => fn(requireSource(ctx), ctx.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Обёртка для генераторов: инструменту нужны только параметры. */
|
/** Обёртка для генераторов: инструменту нужны только параметры. */
|
||||||
export function genTool<P>(
|
export function genTool<P>(
|
||||||
fn: (params: P) => ToolResult,
|
fn: (params: P) => ToolResult | Promise<ToolResult>,
|
||||||
): (ctx: ToolContext<P>) => ToolResult {
|
): (ctx: ToolContext<P>) => ToolResult | Promise<ToolResult> {
|
||||||
return (ctx) => fn(ctx.params);
|
return (ctx) => fn(ctx.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Обёртка для text-to-image инструментов: подставляет `text` и `params`. */
|
/** Обёртка для text-to-image инструментов: подставляет `text` и `params`. */
|
||||||
export function textGen<P>(
|
export function textGen<P>(
|
||||||
fn: (text: string, params: P) => ToolResult,
|
fn: (text: string, params: P) => ToolResult | Promise<ToolResult>,
|
||||||
): (ctx: ToolContext<P>) => ToolResult {
|
): (ctx: ToolContext<P>) => ToolResult | Promise<ToolResult> {
|
||||||
return (ctx) => fn(requireText(ctx), ctx.params);
|
return (ctx) => fn(requireText(ctx), ctx.params);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user