Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listing all Collections in Jekyll

Tags:

jekyll

I'm building a magazine site with Jekyll (v2.5.3). The docs on the Jekyll site led me to believe that I could list all the collections on my site, and embed YAML data for each collection in my _config.yml.

_config.yml:

collections:
  issue_001:
    output: true
    permalink: /:title/:path
    title: Rebirth
    date: 2015-07-01
  issue_002:
    output: true
    permalink: /:title/:path
    title: Talking Heads
    date: 2015-08-01

index.html:

{% for issue in site.collections %}
  <li>
    <h6 class="post-meta">Issue {{ issue.name }} &mdash; {{ issue.date | date: "%b %-d, %Y" }}</h6>

    <h2>
      {{ issue.title }}
    </h2>
  </li>
{% endfor %}

I get two issues appearing on the homepage, but none of the data I'm accessing for each issue (name, date, title etc.) is appearing. I appreciate this is a beta feature, so just wanted to ask is this broken, or am I doing it wrong?

like image 779
James Dinsdale Avatar asked Jul 01 '15 20:07

James Dinsdale


People also ask

What are collections in Jekyll?

Collections in Jekyll provide an easy way to create your own taxonomies around content of the same type. This is great for pieces that belong in a group, but that are not really posts and shouldn't be chronologically organized.

What is front matter in Jekyll?

Front matter is a snippet of YAML placed between two triple-dashed lines at the start of a file. You can use front matter to set variables for the page: --- my_number: 5 --- You can call front matter variables in Liquid using the page variable.


2 Answers

Second first; that answer from @sparanoid is fantastic! And between that and the source code from the default Jekyll Theme (Minima), I was able to bodge some of what follows together.

First second; excellent question and how both are not up-voted more is a bit baffling.

And third of many other related points; I'm not on a identical path as the question's poster but the following code may be of use to readers. My use case was wanting a way of listing the continence of a collection similar to the default Jekyll home layout.

_layouts/named_collection.html

Note the source links are downloadable via, clicking on the Raw link/button then Ctrl s to save as a regular text file, however, these links have been frozen in time so be sure to check the gh-pages branch for updates. And output examples are intended in this case to be just examples of possible content, eg. it could be Lorem strings for all that it matters to demonstrate what's to follow.

---
layout: default
---
{% comment %}
License note from S0AndS0; an editor in this context.

Minima (where the following code is sourced from), is shared under the
 MIT Lisense, https://github.com/jekyll/minima/blob/master/LICENSE.txt

Thus any alterations to Minima source code is re-shared under the MIT Lisense
{% endcomment %}
{% capture workspace_collections %}
  {% assign collection_name = page.collection_name | default: include.collection_name | default: nil %}
  {% assign target_collection = site[collection_name] %}

  <div class="home">
    {%- if page.title -%}
      <h1 class="page-heading">{{ page.title }}</h1>
    {%- endif -%}

    {{ content }}

    {% assign has_output = False %}
    {%- if target_collection.size > 0 -%}
      {% capture workspace_collection %}
        <h2 class="post-list-heading">{{ page.list_title | default: "Posts" }}</h2>
        <ul class="post-list">
          {%- for post in target_collection -%}
            {%- if page.relative_path == post.relative_path -%}
              {%- continue -%}
            {%- else -%}
              {% assign has_output = True %}
            {%- endif -%}

            <li>
              {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
              <span class="post-meta">{{ post.date | date: date_format }}</span>
              <h3>
                <a class="post-link" href="{{ post.url | relative_url }}">
                  {{ post.title | escape }}
                </a>
              </h3>
              {%- if site.show_excerpts -%}
                {{ post.excerpt | markdownify | remove: '<p>' | remove: '</p>' }}
              {%- endif -%}
            </li>
          {%- endfor -%}
        </ul>
      {% endcapture %}

      {%- if has_output == True -%}
        {{- workspace_collection -}}{% assign workspace_collection = nil %}
      {%- endif -%}

    {%- endif -%}
  </div>
{% endcapture %}{{ workspace_collections | strip }}{% assign workspace_collections = nil %}

Side note, I can't remember where I picked up that capture some workspace_ trick, but it's pretty sweat for stripping new lines and other formatting shenanigans. If a reader figures out who started such fanciness, please edit or leave a comment.


Usage of this layout is much like the usage of Minima's home.html layout.

administration.md

... Front-Matter selecting from the _administration collection looks like...

layout: named_collection
collection_name: administration
title: Administration
list_title: Usage Examples
permalink: /admin/

... resulting in a <base-url>/admin/ collection listing being output.

git_shell_commands.md

... Front-Matter selecting from the _git_shell_commands collection looks like...

layout: named_collection
collection_name: git_shell_commands
title: Git Shell Commands
list_title: Usage Examples
permalink: /git_shell_commands/

... resulting in a <base-url>/git_shell_commands/ collection listing being output.


Even more notes on collections

If I'm reading the latest Jekyll Collections documentation correctly, as of version 3.7.0 it could be possible to have a custom collections directory, in the case of this question that might look like...

ls ~/git/magazine-name/
# ... other files and/or directories
#   issues/
# ... other files and/or directories
#   _config.yml

... where the issues/ directory contains sub-directories such as...

ls ~/git/magazine-name/issues/
#   _001/
#   _002/
#   _003/
# ...

... and the _config.yml file has...

collections_dir: issues
collections:
  001:
    output: True
    # ...

... the magic sauce was collections_dir and not using an under-scored prefixed base directory. The documentation was loud about that last bit, eg. _issues/ would make for a bad time.

I'm not sure if there'd be any other adjustments needed to the previously posted Liquid code (I don't think so, but probably); so maybe try'em out individually first.

Warning/Update

Jekyll does not take kindly to numbered collections, eg. _000 will cause errors! To mitigate such issues be sure to trick Jekyll into treating collection names as strings, eg. _i000

The reason I suggest using a collections_dir, is because in the case of @James Dinsdale's question it may help in organizing things a bit more. Personally I wanted my gh-pages branch collection to mirror some of the same paths as my project's master branch, so didn't pursue testing collections_dir suggestions.


Notes about my Liquid coding choices

Because I'm using the Minima theme I placed the files that used the named_collection theme in my project's root directory; default behavior is to link to such pages at the top of every page. Cheap navigation.

Because readers might place pages that use the named_collection within the same directory as what is being listed, eg...

ls Jekyll_Admin/_administration/
#   _administration/administration.md
# ...

... I've written the Liquid for some of the edge-cases, but may not have covered all of'em. Be sure to test privately before unleashing something like it on production.


Updates

After some testing with collections_dir it looks like when used the _posts directory must be moved to that directory too, eg...

_config.yml (Snip)

collections_dir: misc

Bash commands

mkdir misc
mv _posts misc/

... though that's only applicable if using a _posts directory.


Between the time of the last edit and when you're now reading this I've published liquid-utilities/collection-home on GitHub; might be of use to those that want a version tracked solution and is what I'm currently using in any projects that require this feature.

like image 187
S0AndS0 Avatar answered Oct 06 '22 23:10

S0AndS0


In case for someone still has this request here's how it works in latest Jekyll (v3.8.3):

Update: tested it still works in v4.2.0

{% for collection in site.collections %}
  <h2>Items from {{ collection.label }}</h2>
  <ul>
    {% for item in site[collection.label] %}
      <li><a href="{{ item.url }}">{{ item.title }}</a></li>
    {% endfor %}
  </ul>
{% endfor %}
like image 31
sparanoid Avatar answered Oct 06 '22 22:10

sparanoid