외부 파비콘을 faviconV2 origin 방식으로 수정해 서브도메인 아이콘이 올바르게 표시되도록 한다.
uniare.sori.studio처럼 domain 기반 API가 기본 지구본만 반환하던 문제를 해결하고, Recommended 썸네일 실패 fallback을 추가한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
<script setup>
|
||||
import { getExternalFaviconUrl } from '~/lib/external-favicon-url.js'
|
||||
|
||||
const props = defineProps({
|
||||
url: {
|
||||
type: String,
|
||||
@@ -34,13 +36,7 @@ const displayHost = computed(() => {
|
||||
* 썸네일이 비었을 때 파비콘 보조 URL을 만든다.
|
||||
* @returns {string} favicon 요청 URL
|
||||
*/
|
||||
const faviconUrl = computed(() => {
|
||||
if (!displayHost.value) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return `https://www.google.com/s2/favicons?domain=${encodeURIComponent(displayHost.value)}&sz=128`
|
||||
})
|
||||
const faviconUrl = computed(() => getExternalFaviconUrl(props.url, 128))
|
||||
|
||||
/**
|
||||
* 실제로 표시할 이미지 주소
|
||||
|
||||
@@ -55,14 +55,55 @@ const getRecommendedDisplayText = (item) => {
|
||||
return String(item?.descriptionText || '').trim() || String(item?.url || '').trim()
|
||||
}
|
||||
|
||||
/** 추천 사이트 이미지 로드 실패 단계 (`thumbnail` → `favicon` → `letter`) */
|
||||
const recommendedImageStage = ref({})
|
||||
|
||||
/**
|
||||
* 추천 사이트 파비콘 URL을 반환한다.
|
||||
* @param {Object} item - 추천 사이트 항목
|
||||
* @returns {string} 파비콘 URL
|
||||
*/
|
||||
const getRecommendedFaviconUrl = (item) => getExternalFaviconUrl(item?.url, 64)
|
||||
|
||||
/**
|
||||
* 추천 사이트 이미지 URL을 반환한다.
|
||||
* @param {Object} item - 추천 사이트 항목
|
||||
* @returns {string} 이미지 URL
|
||||
*/
|
||||
const getRecommendedImageUrl = (item) => {
|
||||
const id = String(item?.id || '')
|
||||
const stage = recommendedImageStage.value[id] || 'thumbnail'
|
||||
const thumbnailUrl = String(item?.thumbnailUrl || '').trim()
|
||||
return thumbnailUrl || getExternalFaviconUrl(item?.url, 64)
|
||||
const faviconUrl = getRecommendedFaviconUrl(item)
|
||||
|
||||
if (stage === 'letter') {
|
||||
return ''
|
||||
}
|
||||
if (stage === 'favicon') {
|
||||
return faviconUrl
|
||||
}
|
||||
return thumbnailUrl || faviconUrl
|
||||
}
|
||||
|
||||
/**
|
||||
* 추천 사이트 이미지 로드 실패 시 다음 단계로 넘긴다.
|
||||
* @param {Object} item - 추천 사이트 항목
|
||||
* @returns {void}
|
||||
*/
|
||||
const onRecommendedImageError = (item) => {
|
||||
const id = String(item?.id || '')
|
||||
if (!id) {
|
||||
return
|
||||
}
|
||||
const thumbnailUrl = String(item?.thumbnailUrl || '').trim()
|
||||
const faviconUrl = getRecommendedFaviconUrl(item)
|
||||
const stage = recommendedImageStage.value[id] || 'thumbnail'
|
||||
|
||||
if (stage === 'thumbnail' && thumbnailUrl && faviconUrl) {
|
||||
recommendedImageStage.value = { ...recommendedImageStage.value, [id]: 'favicon' }
|
||||
return
|
||||
}
|
||||
recommendedImageStage.value = { ...recommendedImageStage.value, [id]: 'letter' }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,6 +284,7 @@ onMounted(() => {
|
||||
:alt="item.thumbnailUrl ? item.label : ''"
|
||||
loading="lazy"
|
||||
referrerpolicy="no-referrer"
|
||||
@error="onRecommendedImageError(item)"
|
||||
>
|
||||
<span v-else class="px-1 text-center leading-none">{{ (item.label || '?').slice(0, 1) }}</span>
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user