I have a jekyll collection _persons, with multiple peoples' profiles. Now I want to create multiple layouts for each person, e.g., a "Publications", and a "Bio" subpage for the same person.
How can I associate different layouts with the same person object? I'd also like to use sub-urls, such as:
\personA\publications\
\personA\bio\
Assuming that "bios" are the content type that you will be editing, you might create a symlink in your project root from _bios to _publications:
# Unix/Linux
ln -s _bios _publications
If you use windows, you'll need to check out mklink.
Then set up your config.yml like this:
collections:
bios:
output: true
publications:
output: true
defaults:
-
scope:
path: "_bios"
values:
layout: bio
permalink: /biographies/:title/
-
scope:
path: "_publications"
values:
layout: publication
permalink: /publications/:title/
Edit markdown files for your people in the _bios directory, and do not specify layout or permalink in their frontmatter.
When your site builds, you'll get permalinks like example.com/publications/personA and example.com/bios/personA. You can loop through site.publications and site.bios as usual.
You'll need to define the bio and publication layouts, and these will have access to any data you define in the frontmatter of your bio collection items.
Credit for this idea: https://github.com/jekyll/jekyll/issues/3041#issuecomment-267730851
It might be more semantic to have a collection _persons as a single point of truth and make two symlinks from this collection.
Good luck!
Related
Am porting a doc site from Madcap Flare to GitHub Pages using Jekyll. One thing I'm wondering about is that is there a way of implementing an automatic glossary similar to Flare's:
https://www.madcapsoftware.com/blog/guest-post-madcap-flare-101-7-the-glossary/
In summary: I want to have a glossary file comprised of terms and definitions. Then if a term occurs in a topic, it automatically becomes a link or pop-up link to the definition.
If anyone has done this or knows a way to do it I would appreciate it.
Yes, this is possible. Pop-over elements are also possible but I have chosen the link example.
This plugin can create links to the glossary:
module GlossaryData
def glossary
self['glossary']
end
end
module Jekyll
class GlossaryLinkGenerator < Generator
def generate(site)
site.data.extend(GlossaryData)
glossary_terms = {}
site.data.glossary.each do |entry|
glossary_terms[entry['term'].downcase] = entry['definition']
glossary_terms[entry['term']] = entry['definition']
end
# pages
site.pages.each do |page|
glossary_terms.each do |term, definition|
page.content = page.content.gsub(term) do |match|
"<a href='/glossary.html##{term}'>#{term}</a>"
end
end
end
# posts
site.posts.docs.each do |post|
glossary_terms.each do |term, definition|
post.content = post.content.gsub(term) do |match|
"<a href='/glossary.html##{term}'>#{term}</a>"
end
end
end
# Notes
# For all content, use site.documents instead of the two code blocks for posts and pages above
# The site.documents attribute is an array of all the documents in your site,
# including pages, posts, and any other collections that you have defined in your configuration.
# You can use this attribute if you want to apply the glossary link generator to all types of documents in your site.
# You can also use site.collections[COLLECTION_NAME].docs if you want to apply it to a specific collection of documents.
# Just replace COLLECTION_NAME with the name of the collection you want to use.
# You can also use site.collections['posts'].docs for the posts instead of site.posts.
# site.collections is a hash of all the collections defined in your site's configuration,
# and each collection has a 'docs' attribute that returns an array of all the documents in the collection.
# This is useful if you want to apply the glossary link generator to a collection other than 'posts',
# or if you want to apply it to multiple collections.
end
end
end
Define your glossary in _data/glossary.yml:
- term: Jekyll
definition: A static site generator written in Ruby.
- term: Liquid
definition: A template language used by Jekyll to generate dynamic content.
- term: Markdown
definition: A lightweight markup language used to format plain text.
The test page to see that the glossary is working:
---
layout: post
---
jekyll or Jekyll? Both are matched due to downcasing.
I have some front matter defaults in my _config.yaml file:
defaults:
- scope:
path: "./Articles"
values:
parent: Articles
nav_exclude: true
- scope:
path: "./Books"
values:
parent: Books
nav_exclude: true
Basically, it takes every file in the directory ./Articles and ./Books and makes it a child of the index files in the directory (github repo: https://github.com/Fr06t/reading-notes/). The problem is, it also makes the index files childs of themselves. Is there a way to exempt them?
The front matter defaults fill in the gaps for your front matter from your files targeted. If you want the index files to have a different value, the easiest way would be to add parent: null to those files.
e.g. ./Books/index.md:
---
parent: null
nav_exclude: false
# Existing front matter here as well
---
This null value would be prioritised over the defaults in your _config.yml. Alternatively, you could add another defaults entry for those files, you'd just want to check it's taking priority:
defaults:
- scope:
path: "./Articles/index.md"
values:
parent: null
nav_exclude: false
I need to build a Jekyll collection – events – that has a title, a date, and a few other front matter variables:
---
title: Tournament
date: 2018-03-09 00:00:00
date_end: 2018-03-01 20:00:00
description: A big tournament is coming.
---
My collection is configured as:
collections:
events:
output: true
I want these to exist in the _events folder like
- 2018-03-09-tournament.md
and to be output in _site like:
- /event/2018-03-09-tournament/index.html
I've tried many combinations of things on the permalink attribute in _config.yml, but am unable to get my event to render if it includes a date in the filename.
Is this possible? What am I missing?
You can configure permalink like this :
collections:
events:
output: true
future: true
permalink: "/event/:year-:month-:day-:name/index:output_ext"
I'm creating a blog just to dump my notes in. I love how far I can go with site.tags and site.categories. All I really need now is the ability to have another filter option. Something li site.sublog it would help me create exactly what I need
So here's a post
---
layout: post
title: "Angular.js With Codeschool:part five"
date: 2015-05-14 07:57:01 +0100
category: [Angularjs-codeschool, basics]
tags: [angular with codeschool]
sublog: [web]
---
Basically I want to write notes on everything I am interested in: web, general tech, history ... and sort of create sub blogs
There are ways around it but now that I am here I just wanted to know if such a thing was possible
Categories and tags are treated specially by Jekyll, so you won't find that other front matter entries from a post will be collected into a site-wide variable like site.categories and site.tags are.
The Jekyll documentation has a tutorial on retrieving items based on front matter properties, which shows how to iterate over an entire collection and do some per-item processing based on a front matter variable's value.
You could iterate over your collection, inspecting the sublog values of each item and concat-ing them to a list of all known sublog values (perhaps removing duplicates using uniq afterwards, and optionally sort-ing them before further processing).
This would enable you to create a list of all sub blogs, and for each sub blog, create a list of posts within it (which is presumably your end goal).
You can store Sitewide information + configuration settings in _config.yml.
Your example shows Page specific information in the YAML front matter!
Read the Jekyll Documentation, please.
I'm using an existing role, and I wish to modify it to extend its capabilities. Currently, one of its tasks is to create directories. These directories get passed as a variable containing a list of strings to the role, and then iterated over in a with_items statement. However, I would prefer to pass a list of dictionaries of the form e.g. {name: foo, mode: 751}.
So far so good; I can simply edit the role to make it take this sort of input. However, I also want to make it backwards compatible with the old format, i.e. where the items are strings.
Is there a way to test the type of a variable and then return different values (or perform different tasks) based on this? Perhaps using a Jinja2 filter? I was briefly looking at the conditionals listed in the manual, but nothing caught my eye that could be used in this situation.
You could use default() for backwards compatibility.
- file:
path: "{{ item.name | default(item) }}"
mode: "{{ item.mode | default(omit) }}"
state: directory
with_items: your_list
If the item has a name property, use it, else simply use the item itself.
Same goes for all other properties you might have in your dict. The special variable omit would omit the whole option from the task, as if no mode was passed to the file module. Of course you could set any other default.
Documentation references:
default
omit
The quickest solution would be to have two tasks, and have they trigger with opposed conditions. Unfortunately, all items in the list will have to use the same form (you can't mix and match strings and dicts).
- name: create dirs (strings)
file:
...
with_items: items
when: string(items[0])
- name: create dirs (dicts)
file:
...
with_items: items
when: not string(items[0])