라이트박스 이미지 파생 파일 적용

This commit is contained in:
2026-07-01 17:42:12 +09:00
parent 78ab394f7a
commit 129b68b939
13 changed files with 122 additions and 19 deletions

View File

@@ -5,17 +5,25 @@ import sharp from 'sharp'
import {
getPostBodyPreviewThumbnailUrl,
getPostBodyThumbnailUrl,
getPostLightboxThumbnailUrl,
isPostBodyThumbnailUrl,
isPostCardThumbnailUrl
} from '../../lib/post-card-thumbnail-url.js'
export { getPostBodyPreviewThumbnailUrl, getPostBodyThumbnailUrl, isPostBodyThumbnailUrl, isPostCardThumbnailUrl }
export {
getPostBodyPreviewThumbnailUrl,
getPostBodyThumbnailUrl,
getPostLightboxThumbnailUrl,
isPostBodyThumbnailUrl,
isPostCardThumbnailUrl
}
export const POST_THUMBNAIL_WIDTH = 640
export const POST_THUMBNAIL_HEIGHT = 360
export const POST_THUMBNAIL_QUALITY = 82
export const POST_BODY_IMAGE_WIDTH = 1600
export const POST_BODY_PREVIEW_IMAGE_WIDTH = 720
export const POST_LIGHTBOX_IMAGE_WIDTH = 2560
export const POST_BODY_IMAGE_QUALITY = 84
const postUploadUrlPattern = /^\/uploads\/posts\/\d{4}\/\d{2}\/[^/?#]+$/i
@@ -131,6 +139,21 @@ export const getPostBodyPreviewThumbnailDiskPath = (imageUrl) => {
return join(process.cwd(), 'public', decodeUrlPathPart(thumbnailUrl.replace(/^\/+/, '')))
}
/**
* 게시물 라이트박스용 이미지 URL의 디스크 경로를 조회한다.
* @param {string|null|undefined} imageUrl - 원본 이미지 URL
* @returns {string} 라이트박스용 이미지 디스크 경로
*/
export const getPostLightboxThumbnailDiskPath = (imageUrl) => {
const thumbnailUrl = getPostLightboxThumbnailUrl(imageUrl)
if (!thumbnailUrl) {
return ''
}
return join(process.cwd(), 'public', decodeUrlPathPart(thumbnailUrl.replace(/^\/+/, '')))
}
/**
* 게시물 원본 이미지 URL의 디스크 경로를 조회한다.
* @param {string|null|undefined} imageUrl - 원본 이미지 URL
@@ -207,6 +230,21 @@ export const getExistingPostBodyPreviewThumbnailUrl = (imageUrl) => {
return existsSync(getPostBodyPreviewThumbnailDiskPath(imageUrl)) ? thumbnailUrl : ''
}
/**
* 이미 생성된 게시물 라이트박스용 이미지 URL을 조회한다.
* @param {string|null|undefined} imageUrl - 원본 이미지 URL
* @returns {string} 존재하는 라이트박스용 이미지 URL
*/
export const getExistingPostLightboxThumbnailUrl = (imageUrl) => {
const thumbnailUrl = getPostLightboxThumbnailUrl(imageUrl)
if (!thumbnailUrl) {
return ''
}
return existsSync(getPostLightboxThumbnailDiskPath(imageUrl)) ? thumbnailUrl : ''
}
/**
* 게시물 대표 이미지의 카드 썸네일을 생성하거나 다시 생성한다.
* @param {string|null|undefined} imageUrl - 원본 이미지 URL
@@ -254,8 +292,9 @@ export const createPostBodyThumbnailForImageUrl = async (imageUrl) => {
const thumbnailUrl = getPostBodyThumbnailUrl(imageUrl)
const thumbnailPath = getPostBodyThumbnailDiskPath(imageUrl)
const previewThumbnailPath = getPostBodyPreviewThumbnailDiskPath(imageUrl)
const lightboxThumbnailPath = getPostLightboxThumbnailDiskPath(imageUrl)
if (!sourcePath || !thumbnailUrl || !thumbnailPath || !previewThumbnailPath) {
if (!sourcePath || !thumbnailUrl || !thumbnailPath || !previewThumbnailPath || !lightboxThumbnailPath) {
return ''
}
@@ -287,6 +326,16 @@ export const createPostBodyThumbnailForImageUrl = async (imageUrl) => {
})
.webp({ quality: POST_BODY_IMAGE_QUALITY })
.toFile(previewThumbnailPath)
await sharp(sourcePath)
.rotate()
.resize({
width: POST_LIGHTBOX_IMAGE_WIDTH,
fit: 'inside',
withoutEnlargement: true
})
.webp({ quality: POST_BODY_IMAGE_QUALITY })
.toFile(lightboxThumbnailPath)
} catch {
return ''
}