QiitaやGitHubにある強調表示みたいな機能をHugoのshortcodeを使って実装した。


Qiitaには:::noteと書くと、GitHub1ではblockquoteの中で**Note**, **Warning**みたいに書くことで、 強調表示される機能がある。使い勝手の良い機能なので、Hugoのshortcodeを使って実装してみることにした。

できたもの

これはinfoです。

これはsuccessです。

これはwarningです。

これはdangerです。

上の例は以下をレンダリングしたものだ。2

{{< alert info >}}これはinfoです。{{< /alert >}}
{{< alert success >}}これはinfoです。{{< /alert >}}
{{< alert warning >}}これはwarningです。{{< /alert >}}
{{< alert danger >}}これはdangerです。{{< /alert >}}

作り方

shortcodeを作る

layouts/shortcodes/alert.html
{{- $type := .Get 0 | default "info" -}}
{{- $icon := "" -}}
{{- if eq $type "info" -}}{{- $icon = "information-circle-outline" -}}
{{- else if eq $type "warning" -}}{{- $icon = "warning-outline" -}}
{{- else if eq $type "success" -}}{{- $icon = "checkmark-circle-outline" -}}
{{- else if eq $type "danger" -}}{{- $icon = "alert-circle-outline" -}}
{{- else -}}{{- errorf "unknown type of alert %s" $.Params -}}
{{- end -}}
<div class="alert {{ $type }}">
  <div><ion-icon size="large" name="{{ $icon }}"></ion-icon><div>{{ .Inner | markdownify }}</div></div>
</div>

処理の概要

まず1番目の位置引数を$typeに代入して、その値に応じてIoniconsのアイコン名にマップ後、 class属性にalertを持つブロック要素を生成する。

引数が["info", "warning", "success", "danger"]のいずれでもない場合はエラーログを吐く。

見た目の調整

assets/style.scss
.alert {
  position: relative;
  text-align: left;
  padding: 10px 15px;
  min-height: 30px;
  margin: 1.5em 0 1.5em;
  border: none;
  border-left: 3px solid;
  word-break: break-word
}

.alert div:first-child {
  display: flex;
  align-items:center;
  gap: 15px
}

.alert div > div {
  flex-flow: column;
}

.alert ion-icon {
  flex-shrink: 0;
}

.alert p {
  margin: 0 0 0
}

.alert p:first-child {
  margin: 0
}

.alert.info {
  border-color: #349ef3;
  background-color: var(--background-secondary);
}

.alert.success {
  border-color: #4dc657;
  background-color: var(--background-secondary);
}

.alert.warning {
  border-color: #f5aa0a;
  background-color: var(--background-secondary);
}

.alert.danger {
  border-color: #f5311d;
  background-color: var(--background-secondary);
}

生成された要素に適当に色付けする。 bootstrap53のflex-boxの実装を参考にさせてもらった。

ハイライトされた部分は、ライト・ダークテーマ両方に対応するため、利用しているテーマで設定しているカスタムプロパティを参照しているだけなので、適宜読み替えてほしい。

まとめ

shortcodeで簡単に再利用性の高いパーツが作れる。

shortcodeは応用範囲も広く、たとえば何らかの外部サービスを利用したパーツをShortcodeで実装しておけば、たとえ利用しているサービスが終了しても、 Shortcodeの中身だけ差し替えればすぐに他のサービスに移行が可能だ。

そのためにも、shortcodeのインターフェースはきちんと設計したほうが、後々自分のためになると思った。

参考文献


  1. 最近実装されたhttps://github.com/community/community/discussions/16925 ↩︎

  2. コードブロックの中に入れたshortcodeがhtmlとして展開されないようにするには、{{< shortcode >}}~~~{{< /shortcode >}}のようにする必要があった。 https://digitaldrummerj.me/hugo-show-shortcode-markdown-in-code-block/ ↩︎

  3. https://getbootstrap.jp/docs/5.0/components/alerts/#icons ↩︎