Hugo 上で何かのリンクを貼ると↓のようになります。
https://github.com/a2-ito/cf-db-test
これだと殺風景なので、Zenn などで自動作成されるブログカードのように装飾してみます。
実際に作ったものがこちら↓
a2-ito/cf-db-test
This repository is a minimal and practical example of running Next.js App Router on Cloudflare Workers and using D1 Database with Drizzle ORM. - a2-ito/cf-db-test
GitHub
基本的に AI に作ってもらったのですが、いくつか微調整しました。
- OGP 画像は 160x120 の領域に拡大して収めています。(比率が違う画像の場合、引き伸ばされた感で微妙です、、、)
- GitHub リポジトリの場合、ogp:title にリポジトリ名と説明が含まれるようで、リポジトリ名だけを title として抽出・表示しています。
- description が長い場合、カードが縦に伸びてしまうので、2行を超えないよう3行目以降は … と表示されるようにしています。
使い方としては、以下の2ファイルをコピペで配置してもらえればOKです。
assets/css/linkcard.csslayouts/_shortcodes/linkcard.html
a.link-card {
box-shadow: none !important;
}
.link-card {
display: flex;
gap: 8px;
border-radius: 12px;
background: #0b2a4a;
color: #fff;
text-decoration: none;
margin: 1.5em 0;
}
.link-card:hover {
opacity: 0.9;
}
.link-card__body {
flex: 1;
min-width: 0;
padding: 12px;
}
.link-card__title {
font-weight: 700;
font-size: 1.05rem;
margin-bottom: 4px;
}
.link-card__desc {
font-size: 0.9rem;
opacity: 0.85;
margin-bottom: 6px;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.link-card__site {
font-size: 0.75rem;
opacity: 0.6;
}
.link-card__image {
width: 160px;
height: 120px;
overflow: hidden;
flex-shrink: 0;
background: #0a1e33; /* 余白用 */
display: flex;
align-items: center;
justify-content: center;
}
.link-card__image img {
width: 100%;
height: 100%;
display: block;
border-radius: 0px 8px 8px 0px;
}
layouts/_shortcodes/linkcard.html
{{- $url := .Get 0 -}}
{{- $res := resources.GetRemote $url -}}
{{- if not $res -}}
<a href="{{ $url }}" target="_blank" rel="noopener">{{ $url }}</a>
{{- else -}}
{{- $html := $res.Content | safeHTML -}}
{{- $title := "" -}}
{{- $desc := "" -}}
{{- $image := "" -}}
{{- $site := "" -}}
{{- with (replaceRE `(?s).*<meta[^>]+property=["']og:title["'][^>]+content=["']([^"']+)["'][^>]*>.*` `$1` $html) -}}
{{- if ne . $html }}{{ $title = . }}{{ end -}}
{{- end -}}
{{- with (replaceRE `(?s).*<meta[^>]+property=["']og:description["'][^>]+content=["']([^"']+)["'][^>]*>.*` `$1` $html) -}}
{{- if ne . $html }}{{ $desc = . }}{{ end -}}
{{- end -}}
{{- with (replaceRE `(?s).*<meta[^>]+property=["']og:image["'][^>]+content=["']([^"']+)["'][^>]*>.*` `$1` $html) -}}
{{- if ne . $html }}{{ $image = . }}{{ end -}}
{{- end -}}
{{- with (replaceRE `(?s).*<meta[^>]+property=["']og:site_name["'][^>]+content=["']([^"']+)["'][^>]*>.*` `$1` $html) -}}
{{- if ne . $html }}{{ $site = . }}{{ end -}}
{{- end -}}
{{- if in $url "github.com" -}}
{{- $title = replaceRE `^GitHub - ([^:]+):.*$` `$1` $title -}}
{{- end -}}
<a
href="{{ $url }}"
target="_blank"
rel="noopener"
class="link-card"
>
<div class="link-card__body">
<div class="link-card__title">
{{ if $title }}{{ $title }}{{ else }}{{ $url }}{{ end }}
</div>
{{ if $desc }}
<div class="link-card__desc">{{ $desc }}</div>
{{ end }}
{{ if $site }}
<div class="link-card__site">{{ $site }}</div>
{{ end }}
</div>
{{ if $image }}
<div class="link-card__image">
<img src="{{ $image }}" alt="" loading="lazy" />
</div>
{{ end }}
</a>
{{- end -}}