Skip to content
Go back

やっぱりHugoでWikilink形式のリンクを使いたい

  <div class="post-content">
    {{- if not (.Param "disableAnchoredHeadings") }}
    {{- . | partial "post_content.html" | partial "anchored_headings.html" -}}
    {{- else }}{{ . | partial "post_content.html" }}{{ end }}
  </div>
  • post_content.htmlを以下の内容で作って、.Contentを置換する
    • replace-japanese-novel-ruby.html以前作ったやつを流用する
{{ $content := .Content }}
{{ $content = partial "replace-japanese-novel-ruby.html" $content }}
{{ $content = partial "replace-wikilinks.html" (dict "Content" $content "Page" .Page) }}
{{ $content }}
  • replace-wikilinks.htmlを以下の内容で作る
    • 0が全体、1が名前とID、2が名前、3がID、4がタイトルにマッチする
      • マッチしなかったのか空欄だったのかは区別できない?
    • リンク先が見つからなければ、リンクを置き換えないようにしている
    • ファイル名でないものはリンク先に指定できないので、とりあえず、紛れ込みやすい<>をマッチ候補から除外している
{{$content := .Content}}

{{range ((findRESubmatch `\[\[(([^#\|\n<>]*)(?:#([^\|\n]*))?)(?:\|([^\n]*))?\]\]` $content) | uniq)}}
{{$url := ""}}

{{/* リンク先のパスが指定されていれば、それをURLに変換する */}}
{{$name := (index . 2)}}
{{if $name}}
{{$url = print (relref $.Page $name)}}
{{if eq $url ""}}
{{/* 指定のリンク先が存在しなければ、リンクを置き換えない */}}
{{continue}}
{{end}}
{{end}}

{{/* リンク先のIDが指定されていれば、それをURLに変換する */}}
{{$id := (index . 3)}}
{{if $id}}
{{$url = print $url "#" (anchorize $id)}}
{{end}}

{{$content = replace $content (index . 0) (print "<a href=\"" $url "\">" (or (index . 4) (index . 1)) "</a>")}}
{{end}}

{{$content | safeHTML}}
  • hugo.tomlに以下を加えると、relrefが失敗しても処理を継続するようになる
    • リンクの置き換え失敗をエラーにしたくないので必要
    • ただし、警告ログは出る
refLinksErrorLevel = 'WARNING'
refLinksNotFoundURL = ''
  • ルビのときもそうだったが、このやり方だと、文脈を考慮しないため、コードブロック内でもエスケープしていても置換してしまう
    • 今回は[ [ ] ]なので、不意にぶつかりやすい
    • 同名ファイルが存在したり括弧が連続したりしなければ良いので、回避しやすい部類ではある

おまけ

  • partialでは、引数はひとつだけしか渡せない
    • 引数は.でアクセスできる
    • 2つ以上渡したいときは、辞書型にまとめて渡す
      • 受取先では.keyで各値にアクセスできる
  • replaceはパイプで書けない
  • トップレベルの.には$でいつでもアクセスできる
    • rangeなどでは.の参照先がそのアイテムに変わるので
  • 文字列の連結はprintprintfでできる

+記号と 空白

参考文献