feat: add tool popularity and icons
This commit is contained in:
@@ -21,5 +21,8 @@
|
||||
"typescript": "^6.0.3",
|
||||
"vite": "^8.0.16",
|
||||
"vitest": "^4.1.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lucide/svelte": "^1.33.0"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+13
@@ -7,6 +7,10 @@ settings:
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@lucide/svelte':
|
||||
specifier: ^1.33.0
|
||||
version: 1.33.0(svelte@5.56.9)
|
||||
devDependencies:
|
||||
'@sveltejs/adapter-static':
|
||||
specifier: ^3.0.10
|
||||
@@ -51,6 +55,11 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.31':
|
||||
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||
|
||||
'@lucide/svelte@1.33.0':
|
||||
resolution: {integrity: sha512-b+osTYG2V4dge5Lr7tnaTaahhy/4vH7Xb8zcqVjmctjwgkpXS0NNOJPkGzHHZoxtw/OO+2YAU28omeMfYCaawg==}
|
||||
peerDependencies:
|
||||
svelte: ^5
|
||||
|
||||
'@oxc-project/types@0.144.0':
|
||||
resolution: {integrity: sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==}
|
||||
|
||||
@@ -627,6 +636,10 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
'@lucide/svelte@1.33.0(svelte@5.56.9)':
|
||||
dependencies:
|
||||
svelte: 5.56.9
|
||||
|
||||
'@oxc-project/types@0.144.0': {}
|
||||
|
||||
'@polka/url@1.0.0-next.29': {}
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
@@ -1,6 +1,8 @@
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [svelte()],
|
||||
test: {
|
||||
include: ['src/**/*.test.ts'],
|
||||
environment: 'node'
|
||||
|
||||
Reference in New Issue
Block a user