8cd2ef91d3
Три изолированных модуля по TDD (тест до кода) — заголовок/второй заголовок/текст (creativeLimits.ts), проверка ссылки (urlRule.ts) и проверка картинки (imageRule.ts + imageMeta.ts). Цифры и сообщения — порт 1:1 из app/app/Services/Advertising/CreativeValidator.php (единый источник лимитов Яндекс.Директа). 23 новых теста зелёные. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
/**
|
||
* Клиентская проверка изображения-креатива по нормативам Яндекс.Директа.
|
||
* Порт 1:1 логики CreativeValidator::validateImage (app/app/Services/Advertising/CreativeValidator.php).
|
||
* Порядок проверок как на бэке: сначала формат, потом вес, потом размер стороны.
|
||
*/
|
||
|
||
const IMAGE_MIN_SIDE = 450;
|
||
const IMAGE_MAX_BYTES = 10 * 1024 * 1024; // 10 МБ
|
||
const IMAGE_ALLOWED_MIME = ['image/jpeg', 'image/png', 'image/gif'];
|
||
|
||
export interface ImageMeta {
|
||
width: number;
|
||
height: number;
|
||
bytes: number;
|
||
mime: string;
|
||
}
|
||
|
||
/** Возвращает текст ошибки по-русски или null, если картинка проходит проверку. */
|
||
export function checkImage(meta: ImageMeta): string | null {
|
||
if (!IMAGE_ALLOWED_MIME.includes(meta.mime)) {
|
||
return `Недопустимый формат картинки: ${meta.mime}`;
|
||
}
|
||
|
||
if (meta.bytes > IMAGE_MAX_BYTES) {
|
||
return `Картинка тяжелее ${Math.floor(IMAGE_MAX_BYTES / 1024 / 1024)} МБ`;
|
||
}
|
||
|
||
if (meta.width < IMAGE_MIN_SIDE || meta.height < IMAGE_MIN_SIDE) {
|
||
return `Картинка меньше минимума ${IMAGE_MIN_SIDE}×${IMAGE_MIN_SIDE} px`;
|
||
}
|
||
|
||
return null;
|
||
}
|