HTML
Go
静的サイトジェネレーター
Hugo
JSON-LD

HUGOで作れるCMSっぽいパーツ:関連記事・目次・JSON-LDなど

More than 1 year has passed since last update.

超爆速でコンパイルができる、Go言語製の静的サイトジェネレーターHUGO

当然、HUGOでは静的HTMLサイトしか作ることができない。しかし、テンプレート機能をうまく作ればWordPressにも負けないようなパーツが結構作れてしまう。この記事では、HUGOで構築した自分のブログを例に、いくつかのCMSっぽいパーツ見本集をまとめる。

テンプレート見本

  • バージョン0.16で動作確認
    • Hugo Static Site Generator v0.16 BuildDate: 2016-06-06T21:37:59+09:00
  • テンプレート機能の見本なので、CSSについては言及しない

HUGOのページの種類とVariablesの関係

HUGOでは、ページの種類によってテンプレートから参照できる変数に違いがある。

名称 説明
Node Variables ホームページやタグ一覧ページなど、一覧系ページでしか参照できない変数
Page Variables Markdownからコンパイルされた記事ページでしか参照できない変数
Site Variables サイトのどのページからも参照できる変数

Node Variablesに分類される変数を記事ページからは使用できないし、Page Variablesに分類されているものを一覧系のページで呼び出すこともできない。(ビルド時にエラーが出る)

このため、サイドバーなどのサイト全体で使うパーツに対しては、どの場所からも参照できるSite Variablesで完結させる必要がある。

各見本の冒頭部には、そのテンプレートが依存する変数がどれに分類されるかを記載する。

アイキャッチとタグ付きの新着順記事一覧

[Node Variables]

この例では、記事のMarkdownへアイキャッチ画像用のURLをfront-matterのimageプロパティを記述し、項目が存在する場合はHTMLに出力するようにしている。

存在の有無でclassも変化する為、レイアウトをそれぞれ適当なものに変えることができる。

ちなみに、.Summaryconfig.tomlHasCJKLanguage = trueを設定しないとおかしな表示になってしまうので、日本語のブログを作るときは必ず設定しておこう。

新着記事の一覧.png

HTML

  • ページネーションなしで全件出力
テーマ/layouts/index.html
<!-- article-list -->
<section class="article-list">
  <h2 class="article-list__head" itemprop="name">記事一覧</h2>
  <ol class="article-list__list">
    {{ range .Data.Pages.ByDate.Reverse }}
      {{ .Render "li" }}
    {{ end }}
  </ol>
</section>
<!-- /article-list -->
テーマ/layouts/_default/li.html
<li class="article-list__item">
  <!-- article-sneak -->
  <article class="article-sneak {{ if .Params.image }}article-sneak--thumb{{ end }}">
    <div class="article-sneak__link" onclick="location.href='{{ .RelPermalink | safeJS }}'">
      <div class="article-sneak__text article-sneak__wrapper">
        <div class="article-sneak__inner">
          <p class="article-sneak__date">
            <a href="{{ .RelPermalink }}"><time datetime="{{ .Date.Format " 2006-01-02T15:04:05Z07:00" | safeHTML }}">{{ .Date.Format "2006.01.02" }}</time></a>
          </p>
          <h3 class="article-sneak__head">
            <a href="{{ .RelPermalink }}">{{ .Title }}</a>
          </h3>
          {{ if .Params.tags }}
          <dl class="article-sneak__tags">
            <dt><i class="icon icon-tag"></i></dt>
            <dd>
              {{ range .Params.categories }}
              <a href="/categories/{{ . | urlize }}/">{{ . }}</a>
              {{ end }}
            </dd>
            <dd>
              {{ range .Params.tags }}
              <a href="/tags/{{ . | urlize }}/">{{ . }}</a>
              {{ end }}
            </dd>
          </dl>
          {{ end }}
          <p class="article-sneak__body"><a href="{{ .RelPermalink }}">{{ .Summary }}</a></p>
        </div>
      </div>
      {{ if and (.Params.image) (ne .Params.image "") }}
      <div class="article-sneak__figure article-sneak__wrapper">
        <div class="article-sneak__inner">
          <a href="{{ .RelPermalink }}"><p class="article-sneak__thumb" style="background-image: url({{ .Params.image }});">
            <img style="display:none" src="{{ .Params.image }}" alt=""/>
          </p></a>
        </div>
      </div>
      {{ end }}
    </div>
  </article>
  <!-- /article-sneak -->
</li>

Markdown

アイキャッチ画像がある場合はimageプロパティにパスを記載する。

+++
image = "/blog/makeowndigitalbook/stackroom.png"
+++

なお.Summaryの内容を制御する方法はこちらの記事が詳しい。

Hugoにおける記事要約の仕組み - Qiita

ページネーション付の記事一覧と操作UI

[Node Variables]

前項とほぼ一緒だが、ボタン部分に加えて、一覧の抽出条件の書き方が違ってくる。

HTML(一覧)

この書き方だと、出力される記事件数はデフォルトの件数となる。ページネーションのデフォルト件数はconfig.tomlに設定できる。liパーシャルの中身は前項ママでそのまま使えるので省略する。

テーマ/layouts/_default/list.html
<!-- article-list -->
<section class="article-list ">
  <h2 class="article-list__head">{{ .Title }}の記事一覧</h2>
  <ul class="article-list__list">
    {{ range .Paginator.Pages }}
      {{ .Render "li" }}
    {{ end }}
  </ul>
  {{ partial "pagination-nav.html" . }}
</section>
<!-- /article-list -->

config.toml

1ページあたり20件の表示としたい場合はこのように書く。

paginate = 20

HTML(ボタン部分)

スクリーンショット 2016-06-08 12.05.36.png

ページネーションの操作UIは、次のように実装した。

<nav role="pagination" class="pagination-nav">

  <p class="pagination-nav__btn pagination-nav__btn--prev">
    <a class="pagination-nav__item pagination-nav__item--link" {{ if .Paginator.HasPrev }} href="{{.Paginator.Prev.URL}}" {{ end }}>
      <i class="icon icon-arrow-left"></i>前のページへ
    </a>
  </p>

  <p class="pagination-nav__btn pagination-nav__btn--summary">
    <span class="pagination-nav__item">
      {{.Paginator.PageNumber}}/{{.Paginator.TotalPages}}
    </span>
  </p>

  <p class="pagination-nav__btn pagination-nav__btn--next">
    <a class="pagination-nav__item pagination-nav__item--link" {{ if .Paginator.HasNext }} href="{{.Paginator.Next.URL}}" {{ end }}>
      次のページへ<i class="icon icon-arrow-right"></i>
    </a>
  </p>
</nav>

押せない時に薄くなる表現はCSSで実装している。

本文の途中に挿入する目次

[Page Variables]

標準の機能では記事の内部に目次を混ぜることはできない。

そこで、あらかじめ本文中に空のHTML構造を挿入しておき、目次のパーツをJavaScriptで移動させる。これで、外観上は目次が途中に挿入されているように見える。

本文の途中の目次.png

HTML

テーマ/layouts/_default/single.html
<!-- single.htmlの一部 -->
<section>
  <div class="body">
    {{ if eq .Params.usetoc true }}
      {{ partial "toc.html" . }}
    {{ end }}
    {{ .Content }}
  </div>
</section>
テーマ/layouts/partials/toc.html
<section class="js-toc">
  <h2>目次</h2>
  <div class="toc">
  {{ .TableOfContents }}
  </div>
</section>

JavaScript

var $tocPlace = $('#js-toc-place');
if ($tocPlace.length === 1) {
  $('.js-toc').appendTo($tocPlace);
}

Markdown

front-matter内でusetocフラグを使い、必要な記事にだけ目次を挿入できるようにしている。

+++
usetoc = true
+++
それでもメリットはかなり大きい。

<!-- この部分に目次を挿入 -->
<div id="js-toc-place"></div>

## 必要機材

本を自炊するためにはどうしても機材が必要になる。

独自デザインの共有ボタン

[Page Variables]

facebook, twitter, はてブ, メール送信に対応したリンク要素を生成する。本来の用途と異なるかもしれないが、safeJSフィルターが良好に機能した。

SNS共有ボタン.png

<!-- content-footer -->
<div class="content-footer ">
  <p class="content-footer__text">最後までお読みいただきありがとうございます!<i class="icon icon-share"></i></p>
  <ul class="content-footer__sns-list">
    <li class="content-footer__sns-item ">
      <p class="button button--sns button--sns--fb">
        <a class="button__link" href="https://www.facebook.com/sharer/sharer.php?u={{ .Permalink | safeJS }}"><i class="icon icon-facebook"></i>Facebookで共有</a>
      </p>
    </li>
    <li class="content-footer__sns-item ">
      <p class="button button--sns button--sns--tw">
        <a class="button__link" href="http://twitter.com/intent/tweet?text={{ .Title | safeJS }}%20%7C%20{{ .Site.Title }}%20{{ .Permalink | safeJS }}%20%40{{ .Site.Params.twitter }}"><i class="icon icon-twitter"></i>Twitterで共有</a>
      </p>
    </li>
    <li class="content-footer__sns-item ">
      <p class="button button--sns button--sns--hb">
        <a class="button__link" href="http://b.hatena.ne.jp/entry/{{ .Permalink | safeJS }}"><i class="icon icon-hatebu"></i>はてなブックマークで共有</a>
      </p>
    </li>
    <li class="content-footer__sns-item">
      <p class="button button--sns button--sns--mail">
        <a class="button__link" href="mailto:?subject={{ .Title }}&amp;body={{ .Permalink | safeURL }}">メールで共有</a>
      </p>
    </li>
  </ul>
</div>
<!-- /content-footer -->

関連記事

[Page Variables]

表示中の記事に含まれるタグを持つ、自分自身を含まない他の記事の一覧を出力する。

関連記事の一覧.png

HTML

残念ながら、この書き方だと関連記事が0件の時にもh2の見出しが出力されてしまう。色々試したものの、テンプレートのレベルでは解消できなかった。もし解消できたらここへ追記する。

<!-- related-articles -->
{{ if .Params.tags }}
<nav class="related-articles js-related-articles">
  <h2 class="content-footer__text">関連記事</h2>
  <ul class="related-articles__links">
   {{ $currentTitle := .Title }}
    {{ $page_link := .RelPermalink }}
    {{ $tags := .Params.tags }}
    {{ range .Site.Pages }}
    {{ $page := . }}
    {{ $has_common_tags := intersect $tags .Params.tags | len | lt 0 }}
    {{ if and $has_common_tags (ne $page_link $page.RelPermalink) }}
    <li class="related-articles__item js-items">
      <article class="related-article">
        <a class="related-article__link" href="{{ $page.Permalink }}">
          <p class="related-article__stock">{{ $page.Date.Format "2006.01.02." }}</p>
          <h3 class="related-article__title">{{ $page.Title }}</h3>
          <p class="related-article__tags">
            {{ range $page.Params.tags }}
            <span class="related-article__tag">
            {{ . }}
            </span>
            {{ end }} </p>
        </a>
      </article>
    </li>
    {{ end }}
    {{ end }}
  </ul>
</nav>
{{ end }}
<!-- /related-articles -->

JavaScript

……こういった訳で、見出しはJavaScript側で除去する実装。

function removeEmptyRelated() {
    let $target = $('.js-related-articles');
    let items = $target.find('.js-items');

    if (items.length !== 0) {
      return false;
    }

    $target.remove();
  }

前の記事/次の記事へのナビゲーション

[Page Variables]

同一セクションに限定し、前後の投稿がある場合はそれを出力する。

前後の記事へのナビゲーション.png

<!-- content-nav -->
<nav class="content-nav ">
  <ol class="content-nav__links">
    {{ if .PrevInSection }}
    <li class="content-nav__item">
      <p class="content-nav__label">前の投稿</p>
      <p class="button button--article-nav">
        <a class="button__link" href="{{.PrevInSection.RelPermalink}}"><i class="icon icon-arrow-left"></i>{{ .PrevInSection.Title }}</a>
      </p>
    </li>
    {{ end }}
    {{ if .NextInSection }}
    <li class="content-nav__item">
      <p class="content-nav__label">次の投稿</p>
      <p class="button button--article-nav">
        <a class="button__link" href="{{.NextInSection.RelPermalink}}"><i class="icon icon-arrow-right"></i>{{ .NextInSection.Title }}</a>
      </p>
    </li>
    {{ end }}
  </ol>
  <div class="content-nav__menu">
    <p class="button button--article-nav button--article-nav--menu">
      <a class="button__link" href="/"><i class="icon icon-menu"></i>記事一覧へ戻る</a>
    </p>
  </div>
</nav><!-- /content-nav -->

特別な記事だけを抽出して一覧

[Site Variables]

pickupフラグがtrueの記事だけを限定して抽出してアイキャッチ画像を並べる。
あらかじめ各記事のfront-matterにpickuptypeimageを記述しておく。

固定された記事の表示枠.png

HTML

  • 「project」タイプで「pickup」パラメーターがtrueの記事を時系列の逆順に3件まで表示
  • 「docs」タイプで「pickup」パラメーターがtrueの記事を時系列順に2件まで表示
<!-- gallery-sneak -->
<div class="gallery-sneak site-hero--footer">
  <div class="gallery-sneak__inner">
    <ul class="gallery-sneak__list">
      {{ range first 3 (where (where .Site.Pages.Reverse ".Params.pickup" "true" ) "Type" "project") }}
      <li class="gallery-sneak__item">
        <a href="{{ .RelPermalink }}" style="background-image: url({{ .Params.image }});">
          <img src="{{ .Params.image }}" alt=""/>
        </a>
      </li>
      {{ end }}
      {{ range first 2 (where (where .Site.Pages ".Params.pickup" "true" ) "Type" "docs") }}
      <li class="gallery-sneak__item">
        <a href="{{ .RelPermalink }}" style="background-image: url({{ .Params.image }});">
          <img src="{{ .Params.image }}" alt=""/>
        </a>
      </li>
      {{ end }}
    </ul>
  </div>
</div>
<!-- /gallery-sneak -->

Markdown

上記の抽出条件にマッチさせるには、front-matter内へ次を記載する。

+++
type = "docs"
pickup = "true"
image = "/path/to/image.png"
+++

メタ情報

[汎用]

Facebook, Twitter cardに対応したメタタグ。OGPの内容にこだわると結構条件分岐が増える。パーシャル化して運用した方がよいだろう。

HTML

<meta charset="UTF-8">
<!--
トップページだけ特別ルールにする
-->
{{ if .IsHome }}
<title>{{ .Site.Title }}</title>
{{ else }}
<title>{{ .Title }} | {{ .Site.Title }}</title>
{{ end }}
<meta name="generator" content="{{ .Hugo.Generator }}">
<meta name="author" content="{{ .Site.Author.name }}">
<meta property="og:locale" content="{{ .Site.Params.localeOgp }}">
<meta property="fb:app_id" content="{{ .Site.Params.fbAppId }}">
<meta property="og:title" content="{{ .Title }}">
<meta property="og:url" content="{{ .Permalink }}">
<meta property="og:site_name" content="{{ .Site.Title }}">
<!--
1. `.Description`がある場合はそれを使用
2. 「1」が存在せず、nodeの場合は`.Summary`を使用
3. 「1」「2」が存在しない場合は共通の説明文を使用
-->
{{ if .Description }}
<meta name="description" content="{{ .Description }}">
<meta property="og:description" content="{{ .Description }}">
<meta name="twitter:description" content="{{ .Description }}">
{{ else }}
{{ if .IsPage }}
<meta name="description" content="{{ .Summary }}...">
<meta property="og:description" content="{{ .Summary }}...">
<meta name="twitter:description" content="{{ .Summary }}...">
{{ else }}
{{ if .IsHome }}
<meta name="description" content="{{ .Site.Params.description }}">
<meta property="og:description" content="{{ .Site.Params.description }}">
<meta name="twitter:description" content="{{ .Site.Params.description }}">
{{ else }}
<!-- 同じdescriptionのページが重複することを避ける -->
<meta name="description" content="{{ .Title }}に関連する記事の一覧です。{{ .Site.Params.description }}">
<meta property="og:description" content="{{ .Title }}に関連する記事の一覧です。{{ .Site.Params.description }}">
<meta name="twitter:description" content="{{ .Title }}に関連する記事の一覧です。{{ .Site.Params.description }}">
{{ end }}
{{ end }}
{{ end }}
<!--
記事にアイキャッチ画像がある場合はそれをOGP:imageに指定する。
存在しない場合はサイトデフォルトの画像を指定する。
-->
{{ if and (.Params.image) (ne .Params.image "") }}
<meta property="og:image" content="{{ .Params.image | absURL }}">
<meta property="twitter:image" content="{{ .Params.image | absURL }}">
{{ else }}
<meta property="og:image" content="{{ .Site.Params.ogpimage | absURL }}">
<meta property="twitter:image" content="{{ .Site.Params.ogpimage | absURL }}">
{{ end }}
<!--
記事ページはog:typeをarticleにする。公開日時、タグもキーワードとして出力
-->
{{ if .IsPage }}
<meta property="og:type" content="article">
<meta property="og:article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05Z07:00" | safeHTML }}">
{{ range .Params.tags }}<meta property="og:article:tag" content="{{ . }}" />{{ end }}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@{{ .Site.Params.twitter }}">
<meta name="twitter:creator" content="@{{ .Site.Params.twitter }}">
<meta name="twitter:title" content="{{ .Title }}">
<meta name="twitter:url" content="{{ .Permalink }}">
{{ else }}
<meta property="og:type" content="website">
{{ end }}
<!--
  トップでなければホームページへのリンクを出力
-->
{{ if ne .IsHome true }}
<link rel="index" href="/"/>
{{ end }}
<!--
  ページネーションがある場合は、next/prevを出力
-->
{{ if .IsNode }}
{{ if .Paginator.HasPrev }}
<link rel="prev" href="{{.Paginator.Prev.URL}}"/>
{{ end }}
{{ if .Paginator.HasNext }}
<link rel="next" href="{{.Paginator.Next.URL}}"/>
{{ end }}
{{ end }}
<!--
  前後の記事がある場合は、next/prevを出力
-->
{{ if .IsPage }}
{{if .PrevInSection}}<link rel="prev" href="{{ .PrevInSection.RelPermalink }}">{{end}}
{{if .NextInSection}}<link rel="next" href="{{ .NextInSection.RelPermalink }}">{{end}}
{{ end }}
<!-- HUGOが生成するAtomフィード -->
<link href="{{ .Site.RSSLink }}" rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}">

意味情報(JSON-LD)

バージョン0.16からjsonifyフィルタや、記事からプレーンテキストだけを取得できる.Plain変数が追加され、JSON-LDのテンプレートがかなり作成しやすくなった。

記事ページのJSON-LD

[Page Variables]

記事ページをBlogPostingとしてマークアップするためのJSON-LDを記載する。

注意が必要な点として、BlogPostingタイプでは、記事の画像(image)、著者(author)、出版元(publisher)フィールドが必須となっている。しかも、上の3つはそれぞれImageObjectPersonOrganizationのタイプでなければならない。

そのため、画像のない記事には、あらかじめ適当なデフォルト画像をあてがう必要がある。OGP対応のためのデフォルト画像を流用するのが適当だろう。

さらにImageObjectタイプはwidthheightの値が必須となるので、画像の縦横ピクセル値をFront-matterへ記載する必要もある。

テーマ/layouts/partial/json-ld-single.html
<!-- ブログ記事の情報 -->
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "BlogPosting",
  "@id": "{{ .Permalink }}",
  "name": {{ .Title | jsonify }},
  "headline": {{ .Title | jsonify }},
  "description": {{ .Summary | jsonify }},
  "dateModified": "{{ .Lastmod.Format "2006-01-02" }}",
  "datePublished": "{{ .Date.Format "2006-01-02" }}",
  "mainEntityOfPage": "{{ .Permalink }}",
  "url": "{{ .Permalink }}",
  {{ /* 字数 */ }}
  "wordCount": "{{ .WordCount }}",
  {{ /* プレーンテキストの本文 */ }}
  "articleBody": {{ .Plain | jsonify }},
  "articleSection": {{ .Section | jsonify }},
  {{ /* カテゴリをジャンルとして使用 */ }}
{{if .Params.categories }}  "genre": "{{ range .Params.categories }}{{ . }}{{ end }}",{{ end }}
  {{ /* タグをキーワードとして使用 */ }}
{{if .Params.tags }}  "keywords": "{{ range .Params.tags }}{{ . }}{{ end }}",{{ end }}
  "inLanguage": "{{ .Site.LanguageCode }}",
  "image": {
    "@type": "ImageObject",
    {{ if and (.Params.image) (ne .Params.image "") }}
    "url": "{{ .Params.image | absURL }}",
    "width": "{{ .Params.imagewidth  }}",
    "height": "{{ .Params.imageheight }}"
    {{ else }}
    "@id": "{{ .Permalink }}#ogp"
    {{ end }}
  },
  "author": { "@id": "{{ .Permalink }}#author" },
  "publisher": { "@id": "{{ .Permalink }}#org" }
}
</script>

<!-- 著者の情報 -->
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "Person",
  "@id": "{{ .Permalink }}#author",
  "name": "{{ .Site.Author.author }}",
  {{ /* この人物の説明 */ }}
  "description": {{ .Site.Author.profile | jsonify }},
  {{ /* プロフィール画像 */ }}
  "image": "{{ .Site.Author.image | absURL }}"
}
</script>

<!-- 記事にimageが設定されていない場合のデフォルト画像。OGPのデフォルト画像を流用している -->
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "ImageObject",
  "@id": "{{ .Permalink }}#ogp",
  "url": "{{ "/images/ogp.png" | absURL }}",
  "width": "{{ .Site.Params.ogpimagewidth }}",
  "height": "{{ .Site.Params.ogpimageheight }}"
}
</script>

<!-- 出版元となる組織。個人ならサイト名とかにしておけば妥当か -->
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "Organization",
  "@id": "{{ .Permalink }}#org",
  "name": "{{ .Site.Title }}",
  {{ /* logoは必須。ここにもOGP画像を使用 */ }}
  "logo": { "@id": "{{ .Permalink }}#ogp" }
}
</script>

Markdown

上のテンプレートを使うには、front-matterに次の設定が必要となる。

# メイン画像へのパス
image = "/path/to/image.png"
# メイン画像のサイズ(メイン画像がない場合は不要)
imagewidth = 1024
imageheight = 768

config.toml

前項のメタ情報・意味情報を使うための設定ファイルサンプル。

サイト全体で使用するメタ情報は、config.tomlの[params]下へ自由に増やせる。テンプレートからは.Site.Params.xxxでアクセスできる。

baseurl = "http://hogehoge.com"
languageCode = "ja"
title = "サイト名を入れる"
HasCJKLanguage = true

[author]
  author = "名前"
  profile = "自己紹介"
  image = "path/to/profile/image.png"

[params]
  localeOgp = "ja"
  description = "トップページ用の説明文"
  fbAppId = "facebookのAppIDを入れる"
  ogpimage = "images/ogp.png"
  ogpimagewidth = "1200"
  opgimageheight = "620"
  twitter = "twitterCard用のユーザー名を入れる"

記事冒頭だけを配信するRSS/Atomフィード

[Site Variables]

デフォルトのテンプレートだと記事の全文が配信されてしまう。新着20件の.Summary部分だけが出力されるテンプレートにするにはlayouts/_default/rss.xmlを作成して以下の様にする。

XML

テーマ/layouts/_default/rss.xml
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}</title>
    <link>{{ .Permalink }}</link>
    <description>Recent content {{ with .Title }}in {{.}} {{ end }}on {{ .Site.Title }}</description>
    <generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
    <language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
    <managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
    <webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
    <copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
    <lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
    <atom:link href="{{.URL}}" rel="self" type="application/rss+xml"/>
    {{ range first 20 .Data.Pages }}
    <item>
      <title>{{ .Title }}</title>
      <link>{{ .Permalink }}</link>
      <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
      {{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
      <guid>{{ .Permalink }}</guid>
      <description>
        <p>{{ .Summary }}...</p>
        <p><a href="{{ .Permalink }}">Read More</a></p>
      </description>
    </item>
    {{ end }}
  </channel>
</rss>

参考サイト