ブログカードって何?

「ブログカード」とは、ブログに掲載したい記事のタイトルや概要、アイキャッチ画像などを読みやすくまとめて表示する埋め込み形式です。

実際にはこんな感じです。

時間が溶ける

C++、Python、TypeScriptをよく使います。取り留めのない内容を振り返れるように残します。

ZennやQiitaではリンクを貼り付けると自動で作ってくれますが、 Hugoにはその機能はありません。

Hugoで実装を考える

今回はこちらのサイトを参考にさせていただきました。
HugoにはShortCodeという仕組みが用意されています。
PaperModではTwitterやYouTubeなど簡単に埋め込めるよう、用意されています。
このShortCodeは自分で拡張することも可能なので、この仕組みを使ってブログカードを実装するのが良さそうです。

実装手順

  1. layouts/shortcodesbolog-card.html を作る
$ mkdir -p layouts/shortcodes
$ touch layouts/shortcodes/blog-card.html
  1. blog-card.htmlの中身
{{- $url := (.Get 0) -}}
{{- with $result := resources.GetRemote $url -}}
    {{- with $result.Err -}}
        {{- warnf "%s" . -}}{{- . -}}
    {{- else -}}
        {{- $title := "" -}}
        {{- $description := "" -}}
        {{- $image := "" -}}
        {{- with $findHead := index (findRE "<head>(.|\n)*?</head>" $result.Content) 0 -}}
            {{- range $meta := findRE "<meta.*?>" $findHead -}}
                {{- $name := replaceRE "<.*name=\"(.*?)\".*>" "$1" $meta -}}
                {{- $property := replaceRE "<.*property=\"(.*?)\".*>" "$1" $meta -}}
                {{- $content := replaceRE "<.*content=\"(.*?)\".*>" "$1" $meta -}}
                {{- if eq $property "og:title" -}}
                    {{- $title = $content -}}
                {{- else if eq $property "og:description" -}}
                    {{- $description = $content -}}
                {{- else if eq $property "og:image" -}}
                    {{- $image = $content -}}
                {{- end -}}
                {{- if and (eq $description "") (eq $name "description") -}}
                    {{- $description = $content -}}
                {{- end -}}
            {{- end -}}
            {{- if eq $title "" -}}
                {{- with index (findRE "<title>(.*?)</title>" $findHead) 0 -}}
                    {{- $title = replaceRE "<title>(.*?)</title>" "$1" . -}}
                {{- end -}}
            {{- end -}}
        {{- end -}}

        {{- $thumbnail_url := "" -}}
        {{- if $image -}}
            {{- with $thumbnail := resources.GetRemote $image -}}
                {{- with $thumbnail.Err -}}
                    {{- warnf "%s" . -}}{{- . -}}
                {{- else -}}
                    {{/*  {{- $thumbnail_url = ($thumbnail.Fit (printf "200x200 center q%d webp" $.Site.Params.imageQuality)).Permalink -}}  */}}
                    {{- $thumbnail_url = ($thumbnail.Fit (printf "200x200 center q80 webp" )).Permalink -}}
                {{- end -}}
            {{- end -}}
        {{- else -}}
            {{/*  {{- $thumbnail := resources.Get $.Site.Params.dafaultNoimage -}}  */}}
            {{/*  {{- $thumbnail_url = ($thumbnail.Fit (printf "200x200 center q%d webp" $.Site.Params.imageQuality)).Permalink -}}  */}}
            {{- $thumbnail := resources.GetRemote "https://1.bp.blogspot.com/-D2I7Z7-HLGU/Xlyf7OYUi8I/AAAAAAABXq4/jZ0035aDGiE5dP3WiYhlSqhhMgGy8p7zACNcBGAsYHQ/s400/no_image_square.jpg" -}}
            {{- $thumbnail_url = ($thumbnail.Fit (printf "200x200 center q80 webp" )).Permalink -}}
        {{- end -}}

        <a href="{{- $url -}}" style="padding: 12px;border: solid 1px #eee;display: flex;text-decoration: none;color: #000;" onMouseOver="this.style.opacity='0.9'">
            <div style="flex-shrink: 0;">
                <img src="{{- $thumbnail_url -}}" alt="" width="100" height="100" style="object-fit: contain;">
            </div>
            <div style="margin-left: 10px;">
                <h2 style="margin: 0;padding-bottom: 13px;border: none;font-size: 16px;">
                    {{- $title -}}
                </h2>
                <p style="margin: 0;font-size: 13px;word-break: break-word;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 3;overflow: hidden;">
                    {{- $description | plainify | safeHTML -}}
                </p>
            </div>
        </a>
    {{- end -}}
{{- end -}}

使い方

{{ blog-card "URL"}} でURLを指定することで、<meta>タグのog:titleog:descriptionog:imageを取得してカード表示してくれるようです。
画像が取得できなかった場合は、イラストやさんの「NO IMAGE」を使わせていただきました。

おわりに

結構簡単にブログカードを作ることができました。
HugoのShortCodeという仕組みや、layouts以下の実装拡張などすごく綺麗かつ簡単で感動があります。