diff --git a/src/components/news/NewsCard.tsx b/src/components/news/NewsCard.tsx index 22c4c1a..8a76358 100644 --- a/src/components/news/NewsCard.tsx +++ b/src/components/news/NewsCard.tsx @@ -9,18 +9,35 @@ import type { NewsItem } from "@/types/news"; const stripTags = (html?: string | null) => (html ? html.replace(/<[^>]+>/g, "") : ""); +// HTMLエンティティをデコード +const decodeEntities = (text: string) => { + const textarea = document.createElement("textarea"); + textarea.innerHTML = text; + return textarea.value; +}; + export default function NewsCard({ item }: { item: NewsItem }) { const summary = useMemo(() => { if (!item.content) return ""; - const plain = stripTags(item.content); + const plain = decodeEntities(stripTags(item.content)); return plain.length > 80 ? plain.slice(0, 80) + "…" : plain; }, [item.content]); - const href = - item.linkurl && item.linkurl !== "" - ? item.linkurl - : item.content - ? `/news/${item.id}` - : null; + const href = (() => { + const url = item.linkurl?.trim(); + + // リンクなし(none/空)の場合は詳細ページへ + if (!url || url.toLowerCase() === "none") { + return `/news/${item.id}`; + } + + // 外部URLはそのまま + if (/^https?:\/\//i.test(url)) { + return url; + } + + // 内部スラッグ(相対指定)の場合 + return `/news/${url}`; + })(); const target = item.link_target === "_blank" ? "_blank" : "_self"; const isExternal = href?.startsWith("http");