Improve/streamline camera text formatting

This commit is contained in:
Sam Becker 2025-02-04 20:43:27 -06:00
parent d132e85ced
commit 403c846d33
7 changed files with 60 additions and 42 deletions

View File

@ -14,19 +14,24 @@ const RICOH : Camera = {
describe('Camera', () => {
it('labels full text correctly', () => {
expect(formatCameraText(APPLE)).toBe('iPhone 11 Pro');
expect(formatCameraText(APPLE, 'always')).toBe('Apple iPhone 11 Pro');
expect(formatCameraText(APPLE, 'if-not-apple')).toBe('iPhone 11 Pro');
expect(formatCameraText(APPLE, 'never')).toBe('iPhone 11 Pro');
expect(formatCameraText(APPLE, 'long')).toBe('Apple iPhone 11 Pro');
expect(formatCameraText(APPLE, 'medium')).toBe('iPhone 11 Pro');
expect(formatCameraText(APPLE, 'short')).toBe('11 Pro');
expect(formatCameraText(FUJIFILM)).toBe('Fujifilm X-T5');
expect(formatCameraText(CANON)).toBe('Canon EOS 800D');
expect(formatCameraText(NIKON, 'long'))
.toBe('Nikon Corporation Nikon D7000');
expect(formatCameraText(NIKON)).toBe('Nikon D7000');
expect(formatCameraText(RICOH)).toBe('RICOH GR III');
});
it('labels models correctly', () => {
expect(formatCameraText(APPLE, 'never')).toBe('iPhone 11 Pro');
expect(formatCameraText(APPLE, 'never', true)).toBe('11 Pro');
expect(formatCameraText(APPLE_01, 'never', true)).toBe('iPhone 11');
expect(formatCameraText(APPLE_02, 'never', true)).toBe('15 Pro Max');
expect(formatCameraText(APPLE, 'medium')).toBe('iPhone 11 Pro');
expect(formatCameraText(APPLE, 'short')).toBe('11 Pro');
expect(formatCameraText(APPLE_01, 'short')).toBe('iPhone 11');
expect(formatCameraText(APPLE_02, 'short')).toBe('15 Pro Max');
expect(formatCameraText(FUJIFILM, 'short')).toBe('X-T5');
expect(formatCameraText(RICOH, 'short')).toBe('GR III');
expect(formatCameraText(NIKON, 'short')).toBe('D7000');
});
});

View File

@ -57,8 +57,11 @@ export const cameraFromPhoto = (
export const formatCameraText = (
{ make, model: modelRaw }: Camera,
includeMake: 'always' | 'never' | 'if-not-apple' = 'if-not-apple',
removeIPhoneOnLongModels?: boolean,
length:
'long' | // Unmodified make and model
'medium' | // Make and model, with modifiers removed
'short' // Model only
= 'medium',
) => {
// Capture simple make without modifiers like 'Corporation' or 'Company'
const makeSimple = make.match(/^(\S+)/)?.[1];
@ -67,20 +70,23 @@ export const formatCameraText = (
modelRaw.toLocaleLowerCase().startsWith(makeSimple.toLocaleLowerCase())
);
let model = modelRaw;
if (
removeIPhoneOnLongModels &&
model.includes('iPhone') &&
model.length > 9
) {
model = model.replace(/iPhone\s*/i, '');
switch (length) {
case 'long':
return `${make} ${model}`;
case 'medium':
return doesModelStartWithMake || make === 'Apple'
? model
: `${make} ${model}`;
case 'short':
model = doesModelStartWithMake
? model.replace(makeSimple, '').trim()
: model;
if (
model.includes('iPhone') &&
model.length > 9
) {
model = model.replace(/iPhone\s*/i, '');
}
return model;
}
return (
includeMake === 'never' ||
doesModelStartWithMake ||
(includeMake === 'if-not-apple' && make === 'Apple')
) ? model
: `${make} ${model}`;
};
export const formatCameraModelTextShort = (camera: Camera) =>
formatCameraText(camera, 'never', true);

View File

@ -40,7 +40,6 @@ export default function CameraImageResponse({
icon: <IoMdCamera
size={height * .079}
style={{
transform: `translateY(${height * .003}px)`,
marginRight: height * .015,
}}
/>,

View File

@ -39,7 +39,7 @@ export default function FocalLengthImageResponse({
icon: <TbCone
size={height * .075}
style={{
transform: `translateY(${height * .007}px) rotate(270deg)`,
transform: `translateY(${height * .002}px) rotate(270deg)`,
marginRight: height * .01,
}}
/>,

View File

@ -5,7 +5,7 @@ import ImagePhotoGrid from './components/ImagePhotoGrid';
import ImageContainer from './components/ImageContainer';
import { OG_TEXT_BOTTOM_ALIGNMENT } from '@/site/config';
import { NextImageSize } from '@/services/next-image';
import { cameraFromPhoto, formatCameraModelTextShort } from '@/camera';
import { cameraFromPhoto, formatCameraText } from '@/camera';
export default function PhotoImageResponse({
photo,
@ -22,7 +22,7 @@ export default function PhotoImageResponse({
}) {
const caption = [
photo.model
? formatCameraModelTextShort(cameraFromPhoto(photo))
? formatCameraText(cameraFromPhoto(photo), 'short')
: undefined,
photo.focalLengthFormatted,
photo.fNumberFormatted,

View File

@ -40,7 +40,6 @@ export default function TagImageResponse({
? <FaStar
size={height * .066}
style={{
transform: `translateY(${height * .0095}px)`,
// Fix horizontal distortion in icon size
width: height * .076,
marginRight: height * .015,
@ -49,7 +48,7 @@ export default function TagImageResponse({
: <FaTag
size={height * .06}
style={{
transform: `translateY(${height * .016}px)`,
transform: `translateY(${height * .006}px)`,
marginRight: height * .02,
}}
/>,

View File

@ -28,7 +28,7 @@ export default function ImageCaption({
fontFamily,
fontSize: height *.08,
gap: '1rem', // Mimic mono font space metric
lineHeight: 1,
lineHeight: 1.2,
left: 0,
right: 0,
...OG_TEXT_BOTTOM_ALIGNMENT
@ -45,17 +45,26 @@ export default function ImageCaption({
top: 0,
},
}}>
{icon}
<div
style={{
display: 'flex',
gap: height * .048,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{children}
<div style={{
display: 'flex',
alignItems: 'center',
gap: height * .034,
...OG_TEXT_BOTTOM_ALIGNMENT
? { marginBottom: -height * .008 }
: { marginTop: -height * .008 },
}}>
{icon}
<div
style={{
display: 'flex',
gap: height * .048,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{children}
</div>
</div>
</div>
);