BlogカードShortcodeを実装した
例えば、はてなブログだとブログカードと呼ばれるこういうの: が有ったり、wordpressだとプラグインでこういうの: が有り、リンクをなんだか良い感じに表示してくれます。このブログでつい先日まで使っていたGhostでも、こういうの: が有りました。 一方、現在使っているHugoには標準機能でこういったものを表示する機能はありません(twitterとかYoutubeはあるんですけど・・・)。しかし、無ければ作れば良いじゃない、ができるのがHugoの良いところです。 Hugoにはshortcode という機能があり、例えば標準のtwitter shortcodeだと、 {{< tweet user="nasa9084" id="1519598305554362370" >}} と書くと 牛乳はさ、牛乳-like飲物よりうまいんだよな — nasa9084@某某某某(0x1e) (@nasa9084) April 28, 2022 の様に展開されます。なので今回は {{< web-embed url="https://example.com" >}} というshortcodeを作ってみようと思います。調べてみると同様の実装をしている人もいましたので、それを参考にしつつ実装していきます。 まず、URLからデータを取得してくるにはHugoのgetJSON を使うと良さそうです。残念ながらOGP情報などを取得する方法は用意されていないようなので、指定したURLからOGP情報をとってきてJSONとして返す様なプロキシ的なサーバが必要そうです。cloud functions for firebase + javascript で実装している人もいれば、Netlify Functions + javascript でやっている人もいるという感じでしたが、やはり個人的にはGoがシュッと読み書きできて早いし、Cloud Functionsなどで常時稼働させておくには認証とかのことも考える必要がありありそう(まぁ無くてもいいっちゃいいけど、よくわからん踏み台にされても面白くない)で面倒だな、ということでちょっと困ったんですが、OGPプロキシサーバは特に状態を持っておらず、hugo buildする間だけ存在してくれればいいので、GitHub Actionsのサービスコンテナとしてプロキシを動かすことにしました。ローカルでテストビルドするときもdocker runすれば良いだけなので簡単です。 ハンドラの実装は次の通りです: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 url := r.URL.Query().Get("url") if url == "" { http.Error(w, `{"message": "url parameter is required"}`, http.StatusBadRequest) return } log.Printf("request URL: %s", url) ogp, err := opengraph.Fetch(url) if err != nil { http.Error(w, fmt.Sprintf(`{"message": "error fetching OGP", "error": "%s"}`, err.Error()), http.StatusInternalServerError) return } if err := ogp.ToAbs(); err != nil { http.Error(w, fmt.Sprintf(`{"message": "error converting relative URLs to absolute URLs", "error": "%s"}`, err.Error()), http.StatusInternalServerError) return } var body bytes.Buffer if err := json.NewEncoder(&body).Encode(ogp); err != nil { http.Error(w, fmt.Sprintf(`{"message": "error encoding OGP info to JSON", "error": "%s"}`, err.Error()), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) body.WriteTo(w) コード全体はここ にあります。リポジトリを作ったときにhugo用のディレクトリをルートディレクトリではなく一段掘ったサブディレクトリにしておいたおかげで気軽にディレクトリを追加できたので良かったですね。 ...