94 lines
2.6 KiB
TypeScript
94 lines
2.6 KiB
TypeScript
import { formatNumber, t } from '@/i18n'
|
||
import type { ImageVariant, VariantFit, VariantFormat } from '@/composables/useImageVariants'
|
||
|
||
const BYTES_PER_KB = 1024
|
||
const BYTES_PER_MB = BYTES_PER_KB * 1024
|
||
const KB_PER_MB = 1024
|
||
const MB_PER_GB = 1024
|
||
const NO_QUALITY = '—'
|
||
const SEPARATOR = ' · '
|
||
|
||
function oneDecimal(value: number) {
|
||
return Math.round(value * 10) / 10
|
||
}
|
||
|
||
export function formatVariantSize(bytes: number) {
|
||
const kilobytes = Math.round(bytes / BYTES_PER_KB)
|
||
if (bytes === 0) {
|
||
return t('{0} KB', [0])
|
||
}
|
||
if (kilobytes < KB_PER_MB) {
|
||
return t('{0} KB', [Math.max(1, kilobytes)])
|
||
}
|
||
const megabytes = bytes / BYTES_PER_MB
|
||
if (megabytes < MB_PER_GB) {
|
||
return t('{0} MB', [oneDecimal(megabytes)])
|
||
}
|
||
return t('{0} GB', [oneDecimal(megabytes / MB_PER_GB)])
|
||
}
|
||
|
||
export function formatDimensions(width: number | null, height: number | null) {
|
||
if (width !== null && height !== null) {
|
||
return `${width}×${height}`
|
||
}
|
||
if (width !== null) {
|
||
return `${width} × ${t('auto')}`
|
||
}
|
||
return `${t('auto')} × ${height ?? ''}`
|
||
}
|
||
|
||
export function formatLabel(format: VariantFormat) {
|
||
const labels: Record<VariantFormat, string> = {
|
||
webp: 'WebP',
|
||
jpeg: 'JPEG',
|
||
png: 'PNG',
|
||
original: t('Original'),
|
||
}
|
||
return labels[format]
|
||
}
|
||
|
||
export function fitLabel(fit: VariantFit) {
|
||
const labels: Record<VariantFit, string> = {
|
||
cover: t('cover'),
|
||
contain: t('contain'),
|
||
inside: t('inside'),
|
||
}
|
||
return labels[fit]
|
||
}
|
||
|
||
function hasQuality(variant: Pick<ImageVariant, 'format' | 'quality'>) {
|
||
return variant.format !== 'png' && variant.quality !== null
|
||
}
|
||
|
||
export function qualityCell(variant: Pick<ImageVariant, 'format' | 'quality'>) {
|
||
return hasQuality(variant) ? String(variant.quality) : NO_QUALITY
|
||
}
|
||
|
||
export function specLine(variant: ImageVariant) {
|
||
const parts = [
|
||
formatDimensions(variant.width, variant.height),
|
||
fitLabel(variant.fit),
|
||
formatLabel(variant.format),
|
||
]
|
||
if (hasQuality(variant)) {
|
||
parts.push(t('q{0}', [variant.quality ?? 0]))
|
||
}
|
||
return parts.join(SEPARATOR)
|
||
}
|
||
|
||
export function generatedLine(variant: ImageVariant) {
|
||
return t('{0} generated · {1}', [
|
||
formatNumber(variant.generated_files),
|
||
formatVariantSize(variant.cache_size),
|
||
])
|
||
}
|
||
|
||
export function variantsSummary(items: readonly ImageVariant[]) {
|
||
const files = items.reduce((total, item) => total + item.generated_files, 0)
|
||
const bytes = items.reduce((total, item) => total + item.cache_size, 0)
|
||
const variants = items.length === 1 ? t('1 variant') : t('{0} variants', [items.length])
|
||
const generated =
|
||
files === 1 ? t('1 generated file') : t('{0} generated files', [formatNumber(files)])
|
||
return [variants, generated, formatVariantSize(bytes)].join(SEPARATOR)
|
||
}
|