ブログというより、どちらかといえばこのページはWiki的に使いたいので、Wikiのサイドバーのようなメニューの作り方を調べた。
参考
まず本家Jekyll Docsのメニューバーはどうやっているのか調べた。
The Data Folder
As explained on the directory structure page, the
_datafolder 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,.jsonor.csvextension), 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.ymlfile, replacingmy_collectionwith 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’scontentattribute. 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
outputkey totruein your collection metadata in your_config.yml:collections: my_collection: output: trueThis 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
sitevariable. For example, if you want to access thealbumscollection 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 %}
うまくいっているようだ。