SNS 링크 설정 추가 v1.5.39

This commit is contained in:
2026-06-02 17:06:02 +09:00
parent e3b8087b09
commit 4da1ade2cf
15 changed files with 411 additions and 20 deletions

View File

@@ -1,5 +1,6 @@
<script setup>
import { getExternalFaviconUrl } from '~/lib/external-favicon-url.js'
import { getVisibleSocialLinks } from '~/lib/social-links.js'
const route = useRoute()
const postToc = useState('post-detail-toc', () => [])
@@ -7,21 +8,13 @@ const tocNavRef = ref(null)
const activeTocId = ref('')
let tocScrollFrame = 0
const followLinks = [
{ id: 'facebook', label: 'Facebook', href: 'https://facebook.com', icon: 'facebook' },
{ id: 'x', label: 'X', href: 'https://x.com', icon: 'x' },
{ id: 'github', label: 'Github', href: 'https://github.com', icon: 'github' },
{ id: 'instagram', label: 'Instagram', href: 'https://instagram.com', icon: 'instagram' },
{ id: 'linkedin', label: 'Linkedin', href: 'https://linkedin.com', icon: 'linkedin' },
{ id: 'rss', label: 'RSS', href: '/rss/', icon: 'rss' }
]
const { data: siteSettings } = await useFetch('/api/site-settings', {
default: () => ({
title: 'sori.studio',
description: 'sori.studio 개인 블로그',
logoText: '井',
logoUrl: '',
socialLinks: [],
copyrightText: '©2026 sori.studio'
})
})
@@ -47,6 +40,7 @@ const recommendedSites = computed(() => {
})
const isPostDetailRoute = computed(() => route.path.startsWith('/post/'))
const postTocItems = computed(() => Array.isArray(postToc.value) ? postToc.value : [])
const followLinks = computed(() => getVisibleSocialLinks(siteSettings.value?.socialLinks || []))
/**
* 고정 상단 영역을 고려한 TOC 판정 기준선을 반환한다.
@@ -267,7 +261,7 @@ watch([postTocItems, () => route.fullPath], async () => {
</div>
</div>
<div class="right-sidebar__block site-sidebar-section py-5 pl-5 pr-0">
<div v-if="followLinks.length" class="right-sidebar__block site-sidebar-section py-5 pl-5 pr-0">
<div class="right-sidebar__row flex items-center justify-between">
<p class="right-sidebar__eyebrow text-xs font-semibold uppercase site-muted">
Follow
@@ -279,8 +273,8 @@ watch([postTocItems, () => route.fullPath], async () => {
class="site-interactive p-0.5 hover:opacity-75"
:href="item.href"
:aria-label="item.label"
target="_blank"
rel="noreferrer"
:target="item.external ? '_blank' : undefined"
:rel="item.external ? 'noreferrer' : undefined"
>
<svg
v-if="item.icon === 'facebook'"
@@ -353,7 +347,21 @@ watch([postTocItems, () => route.fullPath], async () => {
<circle cx="4" cy="4" r="2" />
</svg>
<svg
v-else
v-else-if="item.icon === 'youtube'"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="h-4 w-4"
>
<path d="M2.5 17a24.1 24.1 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.6 49.6 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.1 24.1 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.6 49.6 0 0 1-16.2 0A2 2 0 0 1 2.5 17" />
<path d="m10 15 5-3-5-3z" />
</svg>
<svg
v-else-if="item.icon === 'rss'"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
@@ -367,6 +375,20 @@ watch([postTocItems, () => route.fullPath], async () => {
<path d="M4 4a16 16 0 0 1 16 16" />
<path d="M4 11a9 9 0 0 1 9 9" />
</svg>
<svg
v-else
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="h-4 w-4"
>
<path d="M10 13a5 5 0 0 0 7.54.54l2-2a5 5 0 0 0-7.07-7.07l-1.15 1.15" />
<path d="M14 11a5 5 0 0 0-7.54-.54l-2 2a5 5 0 0 0 7.07 7.07l1.15-1.15" />
</svg>
<span class="sr-only">{{ item.label }}</span>
</a>
</nav>