feat: add tool popularity and icons

This commit is contained in:
2026-08-24 09:16:29 +05:00
parent 68476c3b8c
commit 76f1770286
7 changed files with 189 additions and 0 deletions
+16
View File
@@ -1,5 +1,6 @@
import { describe, expect, it } from 'vitest';
import { CATEGORIES } from './categories';
import { TOOL_ICONS } from './tools/tool-icons';
import {
defaultParams,
getTool,
@@ -150,6 +151,21 @@ describe('реестр инструментов', () => {
const resize = getToolOrThrow('resize-png');
expect(defaultParams(resize)).toEqual({ width: 0, height: 0, keepAspect: true });
});
it('словарь иконок покрывает все инструменты', () => {
for (const tool of TOOLS) {
expect(TOOL_ICONS[tool.id]).toBeDefined();
}
});
it('у каждого инструмента популярность в диапазоне 0..100 и ключ иконки', () => {
for (const tool of TOOLS) {
expect(tool.popularity).toBeGreaterThanOrEqual(0);
expect(tool.popularity).toBeLessThanOrEqual(100);
expect(typeof tool.icon).toBe('string');
expect(tool.icon!.length).toBeGreaterThan(0);
}
});
});
describe('sanitizeParams', () => {
+10
View File
@@ -88,6 +88,8 @@ export type ToolEntry = {
img: PixelImage,
params: Record<string, unknown>
) => Promise<PixelImage> | PixelImage;
popularity?: number;
icon?: string;
resultType?: 'image' | 'info' | 'text';
output?: OutputFormat;
};
@@ -803,6 +805,14 @@ export const TOOLS: ToolEntry[] = [
}
];
import { TOOL_ICONS } from './tools/tool-icons';
import { TOOL_POPULARITY } from './tools/tool-popularity';
for (const entry of TOOLS) {
entry.icon = entry.id;
entry.popularity = TOOL_POPULARITY[entry.id] ?? 50;
}
export function getTool(id: string): ToolEntry | undefined {
return TOOLS.find((tool) => tool.id === id);
}
+92
View File
@@ -0,0 +1,92 @@
import {
AppWindow,
Binary,
Blend,
ClipboardPaste,
Contrast,
Crop,
Crosshair,
Dices,
Droplet,
Droplets,
Eye,
FileImage,
FileOutput,
FilePlus2,
Film,
FlipHorizontal2,
Focus,
Frame,
Grid3x3,
Hash,
Image as ImageIcon,
Info,
Layers,
Link2,
Maximize2,
PaintBucket,
Palette,
Rainbow,
Repeat2,
RotateCw,
Ruler,
Scaling,
Scissors,
SearchCheck,
Square,
Sun
} from '@lucide/svelte';
export const TOOL_ICONS: Record<string, typeof AppWindow> = {
'resize-png': Scaling,
'crop-png': Crop,
'rotate-png': RotateCw,
'flip-png': FlipHorizontal2,
'grayscale-png': Contrast,
'invert-colors-png': Blend,
'adjust-brightness-contrast-png': Sun,
'convert-png-to-jpg': FileImage,
'convert-png-to-webp': FileImage,
'remove-color-from-png': Scissors,
'png-info': Info,
'jpg-to-png': FileImage,
'webp-to-png': FileImage,
'gif-to-png': Film,
'bmp-to-png': FileImage,
'ico-to-png': AppWindow,
'png-to-bmp': FileOutput,
'png-to-base64': Binary,
'base64-to-png': ClipboardPaste,
'png-to-data-uri': Link2,
'data-uri-to-png': ClipboardPaste,
'png-to-hex': Hash,
'hex-to-png': Hash,
'change-png-opacity': Droplet,
'sepia-png': Palette,
'change-png-hue': Rainbow,
'extract-channel-png': Layers,
'swap-channels-png': Repeat2,
'black-and-white-png': Contrast,
'posterize-png': Layers,
'two-colors-png': Blend,
'invert-alpha-png': Droplets,
'remove-alpha-channel-png': Square,
'set-alpha-channel-png': Droplet,
'extract-alpha-mask-png': Layers,
'round-corners-png': Frame,
'add-padding-png': Maximize2,
'add-border-png': Frame,
'fit-on-background-png': ImageIcon,
'tile-png': Grid3x3,
'center-by-alpha-png': Crosshair,
'create-empty-png': FilePlus2,
'single-color-png': PaintBucket,
'random-noise-png': Dices,
'linear-gradient-png': Sun,
'png-is-grayscale': SearchCheck,
'png-is-transparent': Eye,
'png-orientation': Ruler,
'blur-png': Droplets,
'sharpen-png': Focus,
'remove-background-png': Scissors
};
+53
View File
@@ -0,0 +1,53 @@
export const TOOL_POPULARITY: Record<string, number> = {
'crop-png': 92,
'resize-png': 90,
'remove-background-png': 95,
'blur-png': 85,
'sharpen-png': 80,
'convert-png-to-jpg': 82,
'jpg-to-png': 78,
'rotate-png': 75,
'flip-png': 70,
'convert-png-to-webp': 68,
'webp-to-png': 62,
'grayscale-png': 60,
'adjust-brightness-contrast-png': 58,
'invert-colors-png': 52,
'remove-color-from-png': 65,
'change-png-opacity': 45,
'sepia-png': 40,
'change-png-hue': 38,
'add-padding-png': 42,
'add-border-png': 38,
'two-colors-png': 35,
'black-and-white-png': 42,
'posterize-png': 30,
'round-corners-png': 36,
'fit-on-background-png': 34,
'extract-channel-png': 24,
'swap-channels-png': 22,
'invert-alpha-png': 26,
'remove-alpha-channel-png': 30,
'set-alpha-channel-png': 24,
'extract-alpha-mask-png': 20,
'tile-png': 28,
'center-by-alpha-png': 26,
'png-info': 44,
'png-is-transparent': 18,
'png-is-grayscale': 14,
'png-orientation': 16,
'png-to-base64': 40,
'base64-to-png': 32,
'png-to-data-uri': 34,
'data-uri-to-png': 26,
'png-to-hex': 10,
'hex-to-png': 8,
'gif-to-png': 30,
'bmp-to-png': 18,
'ico-to-png': 20,
'png-to-bmp': 12,
'create-empty-png': 25,
'single-color-png': 20,
'random-noise-png': 12,
'linear-gradient-png': 22
};