astro-notion-blogの記事一覧では、記事タイトルかRead moreをクリックすることによって記事が開きます。
FeaturedImageのクリックでも記事が開くようにしたかったので、FeaturedImageに記事へのリンクを埋め込みます。
記事一覧のページはsrc\pages\index.astro
が司っています。該当部分を探すと、37行目付近にありました。
<div class={styles.post} key={post.Slug}>
<PostDate post={post} />
<PostTags post={post} />
<PostTitle post={post} />
<PostFeaturedImage post={post} />
<PostExcerpt post={post} />
<ReadMoreLink post={post} />
</div>
これは上から順に、投稿日、タグ、タイトル、画像、説明文、Read moreが配置されるというそのままの意味です。
<PostFeaturedImage post={post} />
がFeaturedImageに関する処理部分ですが、これはsrc\components\PostFeaturedImage.astro
で行った処理を引っ張ってきているだけなので、PostFeaturedImage.astro
の方を弄ります。
22行目からのコードがこれです。
HTMLはまだ全然読めませんが、非常にシンプルであることは分かります。
{
image && (
<div class="post-featured-image">
<img src={image} alt="post-featured-image" />
</div>
)
}
ここにaタグで記事へのリンクを埋め込めばいいのですが、肝心の記事へのリンクを”記事ごとに”取得する方法がわかりません。そこで、似たような処理をして記事へのリンクが埋め込まれている記事タイトルを参考にします。見るのはsrc\components\PostTitle.astro
です。
18行目からリンク埋め込みのaタグが書かれていました。
<a href={getPostLink(post.Slug)}>
{post.Icon && post.Icon.Type === 'emoji' ? (
<>
<span>{post.Icon.Emoji}</span>
{title}
</>
) : post.Icon && post.Icon.Type === 'external' ? (
<>
<img src={post.Icon.Url} />
{title}
</>
) : (
title
)}
</a>
getPostLink(post.Slug)
が記事ごとのリンクだと分かりました。これがどこから来ているのか探すと、3行目にimport { getPostLink } from '../lib/blog-helpers.ts'
というのがありました。
つまり、これをPostFeaturedImage.astro
に追加し、リンクを埋め込むように書き換えれば意図した通りに動作するはずです。
📄astro-notion-blogの記事の最初にFeaturedImageを配置する
PostFeaturedImage.astro
の4行目にimport { getPostLink } from '../lib/blog-helpers.ts'
を追加。
---
import { Post } from '../lib/interfaces.ts'
import { filePath } from '../lib/blog-helpers'
import { getPostLink } from '../lib/blog-helpers.ts'
コードの書き換え 旧
22行目からの表示部分のHTMLにaタグを追加する。
{
image && (
<div class="post-featured-image">
<img src={image} alt="post-featured-image" />
</div>
)
}
{
image && (
<a href={getPostLink(post.Slug)}>
<div class="post-featured-image">
<img src={image} alt="post-featured-image" />
</div>
</a>
)
}
リンク埋め込みをオンオフするのをどうするか考えて、コードを眺めていたらすぐ上に<PostTitle post={post} enableLink={false} />
がありました。これはまさにリンク埋め込みをオンオフしています。この処理部が記されているsrc\components\PostTitle.astro
を確認すると、
5行目のところにオンオフの判定用の入れ物が
export interface Props {
post: Post
enableLink: boolean
}
15行目からは条件分岐の記載がありました。
<h3 class="post-title">
{
enableLink ? (
<a href={getPostLink(post.Slug)}>
{post.Icon && post.Icon.Type === 'emoji' ? (
<>
<span>{post.Icon.Emoji}</span>
{title}
</>
) : post.Icon && post.Icon.Type === 'external' ? (
<>
<img src={post.Icon.Url} />
{title}
</>
) : (
title
)}
</a>
) : (
<>
{post.Icon && post.Icon.Type === 'emoji' ? (
<>
<span>{post.Icon.Emoji}</span>
{title}
</>
) : post.Icon && post.Icon.Type === 'external' ? (
<>
<img src={post.Icon.Url} />
{title}
</>
) : (
title
)}
</>
)
}
</h3>
これを真似てPostFeaturedImage.astro
をリンク埋め込みオンオフ可能に書き換えます。
具体的にはenableLink: boolean
を追記して、リンク埋め込みのオンオフを外部から指定できるようにします。
PostFeaturedImage.astro
の6行目のところ
また、const { post, enableLink = true } = Astro.props
としてPostTitle.astro
と同じようにデフォルトではtrueとしておきます。(今後FeaturedImageにはデフォルトでリンクが埋め込まれる。オフにしたければオプションとして指示する必要がある。)(FeaturedImageは記事冒頭に置くもの以外は全て記事本体への誘導の役割になるはずなので、デフォルトオンで問題ないはず。)
export interface Props {
post: Post
}
const { post } = Astro.props
export interface Props {
post: Post
enableLink: boolean
}
const { post, enableLink = true } = Astro.props
次が分岐です。
{
image && (
<div class="post-featured-image">
<img src={image} alt="post-featured-image" />
</div>
)
}
{
enableLink ? (
{
image && (
<a href={getPostLink(post.Slug)}>
<div class="post-featured-image">
<img src={image} alt="post-featured-image" />
</div>
</a>
)
}
</a>
) : (
{
image && (
<div class="post-featured-image">
<img src={image} alt="post-featured-image" />
</div>
)
}
)
}
リンク埋め込みの構文はそのまま旧バージョンのを流用しました。変に弄って壊れても困るので愚直に分岐させています。Chat GPTに聞いてみても問題なさそうだったのでこれで終わりにしていますが、正しい書き方があったら教えてください。(今はコメント欄がないのでTwitterなんかで…)
画像右の余白(メインカラムの横幅の範囲)にも判定が発生していますが、これはdiv要素に対してaタグを付けてるからだと推測します。これは別に気にならないのでそのままにしておきます。
また、FeaturedImageが設定されていない記事で何も表示されないのは変わりありませんでした。下手に手を加えたことで変なものが表示されるのが若干怖かったので安心です。