Article:

最近、日記を書くようにしました。せっかくなら公開しようかなという気持ちと、 ここでそんなものを配信し始めたら、一瞬で有用コンテンツの割合が消えてしまうという気持ちの折衷案として、 このサイトで 隠しコンテンツ として配信することにしました。

ここで言う 隠しコンテンツ の要件は次の4つです。

  • サイト内リンク一覧に出現しない
  • RSS配信されない
  • サイトマップ登録されない
  • クローラにインデックスされない

今回は、この4つの要件を満たすセクションができるようにHugoをカスタマイズしようと思います。

0. 事前準備

事前準備として、config.tomlのparamsセクションに次の設定を追加しておきます。

1
2
3
4
[params]
mainSections = ["blog", "works"]
inhibitSections = ["tags", "categories", "trash"]
inhibitPaths = ["about/about.md", "contact/contact.md", "link/link.md"]

mainSectionsがサイト内リンク一覧に表示したり、RSS配信したい「記事」のカテゴリで、inhibitSections、inhibitPathsがrssやsitemapに表示 しない 項目の設定となっています。

1. サイト内リンク一覧に出現しない

このサイトでは、ホームページに「What’s new」として最新記事をいくつかリンクするようにデザインしていますが、 ここに隠しコンテンツが表示されないようにします。 ここで使う設定項目は「mainSections」で、このリストに該当するセクション内の記事だけを表示するようにします。 inhibit系のブラックリストを流用しても良かったのですが、今後の拡張のことを考えてここでは別途設定項目を用意して使いました。

表示する部分のコードとしてはこんな感じです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<div class="windowBody">
	<ul>
		{{ range first 10 (where .Site.RegularPages.ByDate.Reverse ".Section" "in" $.Site.Params.MainSections) }}
		<li>
			<b><a href="{{.RelPermalink}}">{{.Title}}</a></b>
			<time>{{.Date.Format "2006-01-02"}}</time>
		</li>
		{{ end }}
	</ul>
</div>

“where"構文を使ってフィルターしています。

2. RSS配信されない

前回の記事ではRSSテンプレートを公式からコピーしてカスタマイズしました。 今回もこのファイルを編集して実装します。

このテンプレートでは先頭部分で変数$pagesを定義し、それをフィルターすることで公開するページの一覧を管理していますが、 ここにセクション1と同じフィルターをかけてあげることで実装できます。

RSS本体の出力を始めるまでの先頭部分だけを掲載します。

1
2
3
4
5
6
7
8
{{- $pages := $.Site.RegularPages.ByDate.Reverse -}}
{{- $pages = where $pages ".Section" "in" $.Site.Params.MainSections -}}
{{- $limit := .Site.Config.Services.RSS.Limit -}}
{{- if ge $limit 1 -}}
{{- $pages = $pages | first $limit -}}
{{- end -}}
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">

3. サイトマップ登録されない

サイトマップも前回と同じく、内部のデフォルトテンプレートが使われて自動生成されているので、 自分でカスタマイズするには前回紹介したhugoのレポジトリからsitemap.xmlをダウンロードしてきて、_default下に配備する必要があります。

サイトマップではレギュラーページだけでなく、セクションページも考慮する必要があるので、より厳しいフィルターが必要です。 具体的に言うと、セクション用のフィルタ と、 ページ単体用のフィルタ が必要になると考えました。 設定項目としては、inhibitSectionsinhibitPathsがそれぞれに対応している設計です。

こちらもファイル先頭で出力ページ一覧をフィルターしてあげれば良いので、XML本体の出力を始めるまでの先頭部分だけを掲載します。

1
2
3
4
5
{{- $pages := .Data.Pages -}}
{{- $pages = where $pages ".Section" "not in" $.Site.Params.InhibitSections -}}
{{- $pages = where $pages ".File.Path" "not in" $.Site.Params.InhibitPaths -}}
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"

4. クローラにインデックスされない

最初僕はrobots.txtでDisallowすればインデックスされないのだと思っていましたが、最近だとどうも違うらしいですね(知識が古い)。 クローラにページをインデックスしないように伝えるには、metaタグを利用する方法が確実らしいです。

というわけで、僕は<HEAD>部分をpartialsとして抜き出しているので、layouts/partials/head.htmlに次の項目を加えました。

1
2
3
{{ if or (in $.Site.Params.InhibitSections .Section) (in $.Site.Params.InhibitPaths .File.Path) }}
	<meta name="robots" content="noindex">
{{ end }}

これでインデックスしたくないページにはnoindexのメタタグが挿入されるはずです。


設定のサンプルのせいで隠しコンテンツのリンクがバレバレですね。