본문 이미지 최적화 및 백필 보정
This commit is contained in:
@@ -5,7 +5,7 @@ import {
|
||||
isImageUrl,
|
||||
parseImageMarkdownLine
|
||||
} from '../../lib/markdown-image.js'
|
||||
import { getPostBodyThumbnailUrl } from '../../lib/post-card-thumbnail-url.js'
|
||||
import { getPostBodyPreviewThumbnailUrl, getPostBodyThumbnailUrl } from '../../lib/post-card-thumbnail-url.js'
|
||||
import { readEditableTextFromElement, setEditableCaretOffset } from '../../lib/markdown-inline.js'
|
||||
import {
|
||||
applyLiveSelectionDelete,
|
||||
@@ -1057,6 +1057,32 @@ const contentLightboxImages = computed(() => {
|
||||
*/
|
||||
const getContentDisplayImageUrl = (imageUrl) => getPostBodyThumbnailUrl(imageUrl) || imageUrl || ''
|
||||
|
||||
/**
|
||||
* 게시물 본문 이미지의 반응형 srcset을 만든다.
|
||||
* @param {string|null|undefined} imageUrl - 원본 이미지 URL
|
||||
* @returns {string} srcset 문자열
|
||||
*/
|
||||
const getContentDisplayImageSrcset = (imageUrl) => {
|
||||
const previewUrl = getPostBodyPreviewThumbnailUrl(imageUrl)
|
||||
const bodyUrl = getPostBodyThumbnailUrl(imageUrl)
|
||||
|
||||
return [
|
||||
previewUrl ? `${previewUrl} 720w` : '',
|
||||
bodyUrl ? `${bodyUrl} 1600w` : ''
|
||||
].filter(Boolean).join(', ')
|
||||
}
|
||||
|
||||
/**
|
||||
* 갤러리 표시용 이미지 sizes 값을 만든다.
|
||||
* @param {number} rowLength - 갤러리 행 이미지 개수
|
||||
* @returns {string} sizes 속성
|
||||
*/
|
||||
const getGalleryImageSizes = (rowLength) => {
|
||||
const columnWidth = rowLength >= 3 ? '33vw' : rowLength === 2 ? '50vw' : '100vw'
|
||||
|
||||
return `(max-width: 768px) 100vw, ${columnWidth}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 갤러리 이미지를 행 단위로 최대 3개씩 나눈다.
|
||||
* @param {Array<Object>} images - 갤러리 이미지 목록
|
||||
@@ -1118,6 +1144,8 @@ const onGalleryImageError = (event, fallbackUrl) => {
|
||||
return
|
||||
}
|
||||
|
||||
image.removeAttribute('srcset')
|
||||
image.removeAttribute('sizes')
|
||||
image.src = fallbackUrl
|
||||
}
|
||||
|
||||
@@ -3233,6 +3261,7 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
<ProseImage
|
||||
:src="getContentDisplayImageUrl(block.url)"
|
||||
:srcset="getContentDisplayImageSrcset(block.url)"
|
||||
:fallback-src="block.url"
|
||||
:alt="getImageAltAttribute(block)"
|
||||
:caption="getImageDisplayCaption(block)"
|
||||
@@ -3244,6 +3273,7 @@ onBeforeUnmount(() => {
|
||||
<ProseImage
|
||||
v-else-if="block.type === 'image'"
|
||||
:src="getContentDisplayImageUrl(block.url)"
|
||||
:srcset="getContentDisplayImageSrcset(block.url)"
|
||||
:fallback-src="block.url"
|
||||
:alt="getImageAltAttribute(block)"
|
||||
:caption="getImageDisplayCaption(block)"
|
||||
@@ -3447,6 +3477,8 @@ onBeforeUnmount(() => {
|
||||
<img
|
||||
class="content-markdown-renderer__gallery-image h-full w-full object-cover transition-transform hover:scale-[1.02]"
|
||||
:src="getContentDisplayImageUrl(image.url)"
|
||||
:srcset="getContentDisplayImageSrcset(image.url) || undefined"
|
||||
:sizes="getContentDisplayImageSrcset(image.url) ? getGalleryImageSizes(row.images.length) : undefined"
|
||||
:alt="getImageAltAttribute(image)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
|
||||
@@ -10,6 +10,14 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
srcset: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
sizes: {
|
||||
type: String,
|
||||
default: '(max-width: 768px) 100vw, 760px'
|
||||
},
|
||||
alt: {
|
||||
type: String,
|
||||
default: ''
|
||||
@@ -35,6 +43,7 @@ const loadFailed = ref(false)
|
||||
const currentSrc = ref(props.src)
|
||||
|
||||
const hasRenderableSrc = computed(() => String(currentSrc.value || '').trim().length > 0)
|
||||
const currentSrcset = computed(() => currentSrc.value === props.src ? props.srcset : '')
|
||||
|
||||
const errorLabel = computed(() => {
|
||||
const trimmed = String(props.fallbackSrc || props.src || '').trim()
|
||||
@@ -111,6 +120,8 @@ const activateImage = () => {
|
||||
v-if="hasRenderableSrc && !loadFailed"
|
||||
class="prose-image__media w-full object-cover"
|
||||
:src="currentSrc"
|
||||
:srcset="currentSrcset || undefined"
|
||||
:sizes="currentSrcset ? sizes : undefined"
|
||||
:alt="alt"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
|
||||
Reference in New Issue
Block a user