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>


参考サイト