v1.4.1: 관리자 미디어 업로드 한도·라이브 에디터 UX 개선

종류별 업로드 크기 한도와 413 안내를 추가하고, 임베드·미디어 라이브 프리뷰·제목 Enter 포커스·스크롤 동작을 보정한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-21 15:33:23 +09:00
parent f8e04003fd
commit 095a8fa5f0
25 changed files with 1445 additions and 103 deletions

View File

@@ -5,6 +5,7 @@ import { getSiteSettings, listAdminPosts, listPages } from '../repositories/cont
import { getPostgresClient } from '../repositories/postgres-client'
const uploadRoot = join(process.cwd(), 'public', 'uploads')
const mediaFilePattern = /\.(jpe?g|png|webp|gif|mp4|webm|mov|mp3|wav|ogg|m4a|pdf|zip|txt|csv|docx|xlsx|pptx)$/i
/** 회원 프로필 이미지 전용 논리 폴더명(디스크 경로와 별도) */
export const MEDIA_THUMBNAIL_ROOT = '썸네일'
@@ -377,19 +378,29 @@ const createMediaItem = async (filePath) => {
const fileStat = await stat(filePath)
const relativePath = relative(uploadRoot, filePath)
const url = `/uploads/${relativePath.split('/').join('/')}`
const extension = extname(filePath).toLowerCase()
const kind = /\.(jpe?g|png|webp|gif)$/i.test(extension)
? 'image'
: /\.(mp4|webm|mov)$/i.test(extension)
? 'video'
: /\.(mp3|wav|ogg|m4a)$/i.test(extension)
? 'audio'
: 'file'
return {
url,
name: basename(filePath),
title: basename(filePath, extname(filePath)),
size: fileStat.size,
extension,
kind,
updatedAt: fileStat.mtime.toISOString(),
category: getDefaultMediaCategory(relativePath)
}
}
/**
* 업로드 디렉토리의 이미지 파일을 재귀적으로 조회
* 업로드 디렉토리의 미디어 파일을 재귀적으로 조회
* @param {string} directoryPath - 조회할 디렉토리
* @returns {Promise<Array<Object>>} 미디어 항목 목록
*/
@@ -409,7 +420,7 @@ const readMediaDirectory = async (directoryPath) => {
return readMediaDirectory(entryPath)
}
if (!/\.(jpe?g|png|webp|gif)$/i.test(entry.name)) {
if (!mediaFilePattern.test(entry.name)) {
return []
}