--- // 4コマのページ(日本語・英語版で共通)。下に関連する記録(Studio と同じく HRI の新しい6件+Load more) import Base from '../layouts/Base.astro'; import RecordCard from './RecordCard.astro'; import LoadMore from './LoadMore.astro'; import MangaSwipe from './MangaSwipe.astro'; import { ymd } from '../lib/format'; import { media, mediaHtml } from '../lib/media'; import { seriesCards, allManga, allEnglish } from '../lib/records'; import { textOf, abs, AUTHOR, PUBLISHER, SITE, SITE_NAME } from '../lib/seo'; interface Props { m: any; path: string } const { m, path } = Astro.props; const related = await seriesCards('HRI'); // 英語版は本文が英語なので、説明文も英語の本文から作る(Studio から移した説明文は日本語のままのため) const isEn = path.startsWith('/english-4-koma'); const description = (isEn ? textOf(m.body, 150) : m.description) || textOf(m.body, 120); const pairList = isEn ? allManga : allEnglish; const alternates = pairList.some((x) => x.slug === m.slug) ? [{ lang: isEn ? 'ja' : 'en', path: `${isEn ? '/manga' : '/english-4-koma'}/${m.slug}` }] : []; // 前の話・次の話(話の番号の順。記事の「前の記事・次の記事」と同じカード。2026-10-31) const epNo = (x: any) => Number((x.slug.match(/^ep(\d+)$/) || [])[1]); const seq = (isEn ? allEnglish : allManga).filter((x: any) => !Number.isNaN(epNo(x))).sort((a: any, b: any) => epNo(a) - epNo(b)); const at = seq.findIndex((x: any) => x.slug === m.slug); const prevEp = at > 0 ? seq[at - 1] : null; const nextEp = at >= 0 && at < seq.length - 1 ? seq[at + 1] : null; const base = isEn ? '/english-4-koma' : '/manga'; const epLabel = (x: any) => isEn ? `Episode ${epNo(x)}` : `第${epNo(x)}話`; // 一覧へ戻る(話のページから一覧に戻る道がヘッダーしかなく迷うため。2026-10-31) const archive = isEn ? { href: '/manga-archive-en', label: 'All episodes' } : { href: '/manga-archive', label: '4コママンガ一覧' }; const title = isEn ? `${m.title} | 4-Koma Manga | ${SITE_NAME}` : `${m.title} | 4コママンガ | ${SITE_NAME}`; const jsonLd = { '@context': 'https://schema.org', '@type': 'Article', headline: m.title, description, url: SITE + path, mainEntityOfPage: SITE + path, inLanguage: isEn ? 'en' : 'ja', datePublished: m.published, dateModified: m.published, image: (m.panels ? m.panels.map((p: string) => abs(media(p))) : [abs(media(m.comic)), abs(media(m.cover))]).filter(Boolean), genre: isEn ? '4-panel comic' : '4コママンガ', author: AUTHOR, publisher: PUBLISHER, }; ---
{archive.label}
{m.label}{m.character}{ymd(m.published)}
{m.panels ? : m.cover && {m.cover_alt} {!m.panels && m.comic && {m.comic_alt}

{m.title}