feat: start implement mvp
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import { ImageError } from "../types/errors";
|
||||
|
||||
export const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
||||
export const SUPPORTED_FORMATS = ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif"];
|
||||
|
||||
export interface ValidationResult {
|
||||
isValid: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export function validateFileSize(file: File): ValidationResult {
|
||||
if (file.size > MAX_FILE_SIZE) {
|
||||
return {
|
||||
isValid: false,
|
||||
error: `Файл слишком большой. Максимальный размер: ${MAX_FILE_SIZE / 1024 / 1024}MB`,
|
||||
};
|
||||
}
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
export function validateFileType(file: File): ValidationResult {
|
||||
if (!SUPPORTED_FORMATS.includes(file.type)) {
|
||||
return {
|
||||
isValid: false,
|
||||
error: `Неподдерживаемый формат. Допустимые форматы: ${SUPPORTED_FORMATS.join(", ")}`,
|
||||
};
|
||||
}
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
export function validateImageFile(file: File): ValidationResult {
|
||||
const sizeValidation = validateFileSize(file);
|
||||
if (!sizeValidation.isValid) {
|
||||
return sizeValidation;
|
||||
}
|
||||
|
||||
const typeValidation = validateFileType(file);
|
||||
if (!typeValidation.isValid) {
|
||||
return typeValidation;
|
||||
}
|
||||
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
export function validateImageUrl(url: string): ValidationResult {
|
||||
try {
|
||||
new URL(url);
|
||||
return { isValid: true };
|
||||
} catch {
|
||||
return {
|
||||
isValid: false,
|
||||
error: "Неверный URL формат",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function validateImageElement(img: HTMLImageElement): ValidationResult {
|
||||
if (!img.naturalWidth || !img.naturalHeight) {
|
||||
return {
|
||||
isValid: false,
|
||||
error: "Изображение не может быть загружено или повреждено",
|
||||
};
|
||||
}
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
export async function loadImage(src: string): Promise<HTMLImageElement> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.crossOrigin = "anonymous";
|
||||
|
||||
img.onload = () => resolve(img);
|
||||
img.onerror = () => reject(new ImageError("Не удалось загрузить изображение"));
|
||||
|
||||
img.src = src;
|
||||
});
|
||||
}
|
||||
|
||||
export function getImageDimensions(img: HTMLImageElement): { width: number; height: number } {
|
||||
return {
|
||||
width: img.naturalWidth,
|
||||
height: img.naturalHeight,
|
||||
};
|
||||
}
|
||||
|
||||
export function calculateAspectRatioFit(
|
||||
srcWidth: number,
|
||||
srcHeight: number,
|
||||
maxWidth: number,
|
||||
maxHeight: number,
|
||||
): { width: number; height: number } {
|
||||
const ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
|
||||
return {
|
||||
width: srcWidth * ratio,
|
||||
height: srcHeight * ratio,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user