ブログというより、どちらかといえばこのページはWiki的に使いたいので、Wikiのサイドバーのようなメニューの作り方を調べた。
参考
まず本家Jekyll Docsのメニューバーはどうやっているのか調べた。
The Data Folder
As explained on the directory structure page, the
_data
folder is where you can store additional data for Jekyll to use when generating your site. These files must be YAML, JSON, or CSV files (using either the.yml
,.yaml
,.json
or.csv
extension), and they will be accessible viasite.data
.
まず _data ディレクトリについて知らないといけないようだ。
_data ディレクトリに入っているYAMLファイル等の情報に、site.data.*
でアクセスができる。
*
の部分にはまずファイル名が入る。ファイル名の後はデータ構造による。
引用したソースの Getting Started を手に入れたい場合は、
{{ site.data.docs[0].title }}
となる。
- title: Getting Started docs: - home - quickstart - installation - usage - structure - configuration - title: Your Content docs: - frontmatter …
ぐったりしながらソースを眺めてみると、この docs.yml を元に作成しているようだ。 そりゃそうだよなぁ。 で調べた限り、 デフォルトだとただページ一覧とかの情報しかない。これだけだときつい。
じゃあこの docs.yml からどうやってジェネレートしているのか。
<div class="unit one-fifth hide-on-mobiles"> <aside> {% for section in site.data.docs %} <h4>{{ section.title }}</h4> {% include docs_ul.html items=section.docs %} {% endfor %} </aside> </div>
docs.yml を走査しているfor
があって、まずtitle
のデータを用いてヘッダを作っているのが分かる。
その後
{% include docs_ul.html items=section.docs %}
している。include
にitems
でページ配列を渡しているぞ?
include
で引数を渡すPassing in parameters
If you need to pass in parameters you can do that too. The fragment below shows how you might pass in a string
"a value"
and a variablevariable_name
.{% include your_function.html some_parameter="a value" another_parameter=variable_name %}
Within the file you can access those parameters using
{{ include.some_parameter }}
and{{ include.another_parameter }}
respectively.
_includes ディレクトリ下のファイルをインクルードする際、引数名と値をセットすることで引数を渡すことができる。
渡された引数にはinclude.value
といった形式でアクセスできるとのこと。
<ul> {% for item in include.items %} {% assign item_url = item | prepend:"/docs/" | append:"/" %} {% assign p = site.docs | where:"url", item_url | first %} <li class="{% if item_url == page.url %}current{% endif %}"><a href="{{ p.url }}">{{ p.title }}</a></li> {% endfor %} </ul>
{% assign item_url = item | prepend:"/docs/" | append:"/" %}
受け取った配列からURLを作っている。item_url
は/docs/item/
の形の文字列になる。
{% assign p = site.docs | where:"url", item_url | first %}
え、site.directory
でディレクトリ指定できるの?
Collections
Not everything is a post or a page. Maybe you want to document the various methods in your open source project, members of a team, or talks at a conference. Collections allow you to define a new type of document that behave like Pages or Posts do normally, but also have their own unique properties and namespace.
Add the following to your site’s
_config.yml
file, replacingmy_collection
with the name of your collection:collections: - my_collection
Step 2: Add your content
Create a corresponding folder (e.g.
<source>/_my_collection
) and add documents. YAML front matter is processed if the front matter exists, and everything after the front matter is pushed into the document’scontent
attribute. If no YAML front matter is provided, Jekyll will not generate the file in your collection.
Step 3: Optionally render your collection’s documents into independent files
If you’d like Jekyll to create a public-facing, rendered version of each document in your collection, set the
output
key totrue
in your collection metadata in your_config.yml
:collections: my_collection: output: true
This will produce a file for each document in the collection. For example, if you have
_my_collection/some_subdir/some_doc.md
, it will be rendered using Liquid and the Markdown converter of your choice and written out to<dest>/my_collection/some_subdir/some_doc.html
Collections
Each collection is accessible as a field on the
site
variable. For example, if you want to access thealbums
collection found in_albums
, you’d usesite.albums
.
これを使っているのか。Collectionは関連するデータをまとめて入れておく場所という認識でよいかな。
使い方は _config.yml に
collections:
- collectionname
とCollectionを列挙。それに対応するディレクトリが _collectionname と
先頭に_
をつけた同名のディレクトリ。
コンテンツをページとして出力したい場合、
collections:
collectionname:
output : true
とoutput: true
オプションをつける必要がある。
output: true
にすると、デフォルトでは
_collectionname/test.md
は
collectionname/test.html
に展開される。
ここまで定義しておくと、
site.collectionname
で中の要素にアクセスできる。データまとめるのに便利だからこれから使っていこうかな。
話を戻してさっき見ていた行をみる
{% assign p = site.docs | where:"url", item_url | first %}
docs
Collectionからwhere
でフィルタリングしている。
- Where
- Select all the objects in an array where the key has the given value.
{{ site.members | where:"graduation_year","2014" }}
引用した例ではsite.members
配列の内、graduation_year
の要素が2014
のもののみを抽出しているということになる。
ソース側に当てはめると、url
要素がitem_url
と合致するもののみを抽出している。
合致したデータが1つだけであろうと抽出したデータは配列として返ってくるので、さらにfirst
でフィルタリングして1つだけを取り出し、
p
に割り当てているということらしい。
つまり、urlを検索キーに使ってページオブジェクトを取得しているようだ。 それ以下のコードは取得したオブジェクトからタイトルとかを取り出している。
_config.yml
を編集する
collections :
Jekyll:
output: true
Jekyll系の記事のメニューを作ってみる。
_Jekyll ディレクトリを作成し、Jekyll関連のページを移動する。
|--_Jekyll
| |--Ruby-research.md
| |--bundle-usage.md
| |--display-value.md
| |--github-pages-debug.md
| |--github-pages-generator.md
| |--jekyll-usage.md
| |--liquid-raw.md
| |--page-menu.md
| |--rbenv-install.md
| |--rbenv-usage.md
| |--site-variables.md
| |--worth-bundle-install.md
site.collection
の中からwhere
でフィルタリングしてページオブジェクトを手に入れて、
title
やurl
を引っ張ってくるのがスマートな気がする。
ので、まずどんなデータが入っているのか調べる。
{{ site.Jekyll | inspect | jsonfy }}
nil
{{ site.Jekyll[0].title | inspect }}
{{ site.Jekyll[0].url | inspect }}
{{ site.Jekyll[0].path | inspect }}
nil nil nil
データが多すぎるので抜粋した。この辺りをキーにしてオブジェクトを引っ張ってくるのがよさそう。
メニューに必要なものを考える。
ページオブジェクトを取得する必要がありそうなので、
コンパイル前の、こちらでパスを把握しているpath
をキーにしてページオブジェクトを取得する。
そのためにファイル名の一覧をメニュー構成用データに使う。
- title : github pages & Jekyll
prefix : Jekyll
pages :
- Ruby-research
- bundle-usage
- github-pages-debug
- github-pages-generator
- jekyll-usage
- rbenv-install
- rbenv-usage
- worth-bundle-install
- site-variables
- liquid-raw
- display-value
複数のカテゴリを横断する記事はファイル名以下に何かプロパティをぶら下げて区別しようかな。 _data/pages.yml として保存した。
path
を生成する。Combining multiple strings into one variable:
{% capture full-name %}{{ name }} {{ surname }}{% endcapture %}
これを使うとパスを作るのが簡単そうだった。
ページ一覧をfor
で走査してcapture
でパスを作り出す。
{% for section in site.data.pages %}
{% for page in section.pages %}
{% capture path %}_{{ section.prefix }}/{{page}}.md{% endcapture %}
{{path}}
{% endfor %}
{% endfor %}
では、パスをキーにしてオブジェクトを取得、タイトルとURLを取得してみる。
{% for section in site.data.pages %}
{% for page in section.pages %}
{% capture path %}_{{ section.prefix }}/{{page}}.md{% endcapture %}
<p>
{% assign content = site.Jekyll | where:"path", path | first %}
{{content.title}}
</p>
<p>
{{content.url}}
</p>
{% endfor %}
{% endfor %}
うまくいっているようだ。