作ったものとか » Hugo テーマ

Hugo テーマ 6. Render Hook

2024-08-16 12:36:24 hugo

#5 の題材を、今度は Render Hook という機能を使って実装します。

この記事では、最初に少しだけまとめを入れて、次にコードを提示し、そのうえで Render Hook の解説(自分が理解したこと)を書いていきます。

Render Hook とは

Markdown から変換する場合にのみ使える、HTML への変換結果を書き換える方法です。

おおむね、Shortcode と同じ感覚で書き換えの記述をすることができます。

今回やること

Markdown で記述できるリンク [text](destination) を、destination の内容に応じて次の2パターンの HTML のいずれかに変換します。

  1. <a href="destination">text</a>
  2. <a href="destination" target="_blank" rel="external noopener noreferer">text</a>

Shortcode との違い

最終形

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{{- $u := urls.Parse .Destination -}}
{{- $siteu := urls.Parse (.Page.Site.BaseURL | absURL) -}}
{{- $outer := (and $u.IsAbs (not (eq $u.Host $siteu.Host)) ) -}}

<a href="{{ .Destination | safeURL }}"
  {{- with .Title }} title="{{ . }}"{{ end -}}
  {{- if $outer }} target="_blank" rel="external noopener noreferer"{{ end -}}
>
  {{- with .Text | safeHTML }}{{ . }}{{ end -}}

  {{- if $outer -}}
  {{- " " -}}<span style="position:relative;">{{- "" -}}
      <span style="">&#x2610;</span>{{- "" -}}
      <span style="position:absolute; top:-0.3em; left:0.2em">&#x2197;</span>{{- "" -}}
  </span>
  {{- end -}}
</a>
{{- /* chomp trailing newline */ -}}

ファイルの配置は以下の通りです。 (関係あるファイルのみ表示)

> tree /a /f
\---themes
    \---cheep
        \---layouts
            \---_default
                \---_markup
                        render-link.html

Render Hook

使える局面

Markdown を HTML に変換する際のルールを変える仕組みです。 そのため、Markdown として記述ができないものには、この仕組みを適用することはできません。

また、適用できるものも限られています。

Hugo 公式のドキュメント Render Hooks Introduction には、上記の内容と、ファイルを配置するべき場所が記載されています。

テンプレートファイルの配置場所

Render Hook もテンプレートとして記述します。

その配置場所は以下の通り。

layouts
\---_default
    \---_markup
            render-blockquote.html
            render-codeblock.html
            render-heading.html
            render-image.html
            render-link.html    

Hugo 公式のドキュメント Render Hooks Introduction には、もう少し細かい内容が記載されています。 また、各 Render Hook 内で利用できる Context (プロパティ) が列挙されています。

注意点

私が使った範囲だと注意点はあまりないのですが、Shortcode と違い、$.Site の形でサイトを参照することはできません。

ただ、どの Render Hook でも .Page.Site として参照できるようですので、さほど困ることは無いと思われます。