본문 이미지 최적화·라이트박스·번호형 페이지네이션 반영 (v1.10.3)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
isImageUrl,
|
||||
parseImageMarkdownLine
|
||||
} from '../../lib/markdown-image.js'
|
||||
import { getPostBodyThumbnailUrl } from '../../lib/post-card-thumbnail-url.js'
|
||||
import { readEditableTextFromElement, setEditableCaretOffset } from '../../lib/markdown-inline.js'
|
||||
import {
|
||||
applyLiveSelectionDelete,
|
||||
@@ -989,6 +990,42 @@ const tailInsertBeforeLine = computed(() => {
|
||||
})
|
||||
const activeLightboxImage = computed(() => activeLightboxImages.value[activeLightboxIndex.value])
|
||||
|
||||
const contentLightboxImages = computed(() => {
|
||||
const images = []
|
||||
|
||||
blocks.value.forEach((block) => {
|
||||
if (block.type === 'image' && block.url) {
|
||||
images.push({
|
||||
...block,
|
||||
lightboxKey: block.id
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (block.type === 'gallery' && Array.isArray(block.images)) {
|
||||
block.images.forEach((image, imageIndex) => {
|
||||
if (!image?.url) {
|
||||
return
|
||||
}
|
||||
|
||||
images.push({
|
||||
...image,
|
||||
lightboxKey: `${block.id}:${imageIndex}`
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return images
|
||||
})
|
||||
|
||||
/**
|
||||
* 게시물 본문 표시용 이미지 URL을 조회한다.
|
||||
* @param {string|null|undefined} imageUrl - 원본 이미지 URL
|
||||
* @returns {string} 표시용 이미지 URL
|
||||
*/
|
||||
const getContentDisplayImageUrl = (imageUrl) => getPostBodyThumbnailUrl(imageUrl) || imageUrl || ''
|
||||
|
||||
/**
|
||||
* 갤러리 이미지를 행 단위로 최대 3개씩 나눈다.
|
||||
* @param {Array<Object>} images - 갤러리 이미지 목록
|
||||
@@ -1037,6 +1074,22 @@ const onGalleryImageLoad = (event, blockId, imageIndex, url) => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 갤러리 표시용 이미지 로드 실패 시 원본 이미지로 되돌린다.
|
||||
* @param {Event} event - 이미지 로드 이벤트
|
||||
* @param {string} fallbackUrl - 원본 이미지 URL
|
||||
* @returns {void}
|
||||
*/
|
||||
const onGalleryImageError = (event, fallbackUrl) => {
|
||||
const image = event.target
|
||||
|
||||
if (!(image instanceof HTMLImageElement) || !fallbackUrl || image.src.endsWith(fallbackUrl)) {
|
||||
return
|
||||
}
|
||||
|
||||
image.src = fallbackUrl
|
||||
}
|
||||
|
||||
/**
|
||||
* 갤러리 이미지 셀의 flex 비율 스타일을 만든다.
|
||||
* @param {Object} block - 갤러리 블록
|
||||
@@ -2457,6 +2510,22 @@ const openLightbox = (images, index) => {
|
||||
activeLightboxIndex.value = index
|
||||
}
|
||||
|
||||
/**
|
||||
* 본문 전체 이미지 목록에서 지정 이미지를 라이트박스로 연다.
|
||||
* @param {string} lightboxKey - 이미지 식별 키
|
||||
* @returns {void}
|
||||
*/
|
||||
const openContentLightbox = (lightboxKey) => {
|
||||
const images = contentLightboxImages.value
|
||||
const index = images.findIndex((image) => image.lightboxKey === lightboxKey)
|
||||
|
||||
if (index < 0) {
|
||||
return
|
||||
}
|
||||
|
||||
openLightbox(images, index)
|
||||
}
|
||||
|
||||
/**
|
||||
* 라이트박스를 닫는다
|
||||
* @returns {void}
|
||||
@@ -3131,18 +3200,24 @@ onBeforeUnmount(() => {
|
||||
</button>
|
||||
</div>
|
||||
<ProseImage
|
||||
:src="block.url"
|
||||
:src="getContentDisplayImageUrl(block.url)"
|
||||
:fallback-src="block.url"
|
||||
:alt="getImageAltAttribute(block)"
|
||||
:caption="getImageDisplayCaption(block)"
|
||||
:variant="block.width"
|
||||
expandable
|
||||
@activate="openContentLightbox(block.id)"
|
||||
/>
|
||||
</section>
|
||||
<ProseImage
|
||||
v-else-if="block.type === 'image'"
|
||||
:src="block.url"
|
||||
:src="getContentDisplayImageUrl(block.url)"
|
||||
:fallback-src="block.url"
|
||||
:alt="getImageAltAttribute(block)"
|
||||
:caption="getImageDisplayCaption(block)"
|
||||
:variant="block.width"
|
||||
expandable
|
||||
@activate="openContentLightbox(block.id)"
|
||||
/>
|
||||
<ContentMarkdownCalloutEditor
|
||||
v-else-if="block.type === 'callout' && interactive"
|
||||
@@ -3334,13 +3409,17 @@ onBeforeUnmount(() => {
|
||||
<button
|
||||
class="content-markdown-renderer__gallery-button w-full overflow-hidden rounded-[10px] border border-[var(--site-line)] bg-[var(--site-panel)]"
|
||||
type="button"
|
||||
@click="openLightbox(block.images, row.startIndex + rowImageIndex)"
|
||||
aria-label="이미지 크게 보기"
|
||||
@click="openContentLightbox(`${block.id}:${row.startIndex + rowImageIndex}`)"
|
||||
>
|
||||
<img
|
||||
class="content-markdown-renderer__gallery-image h-full w-full object-cover transition-transform hover:scale-[1.02]"
|
||||
:src="image.url"
|
||||
:src="getContentDisplayImageUrl(image.url)"
|
||||
:alt="getImageAltAttribute(image)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
@load="onGalleryImageLoad($event, block.id, row.startIndex + rowImageIndex, image.url)"
|
||||
@error="onGalleryImageError($event, image.url)"
|
||||
>
|
||||
</button>
|
||||
<figcaption
|
||||
|
||||
Reference in New Issue
Block a user