Jekyll: Get number of files in front matter specified sub-directories? - jekyll

Imagine a directory specified in pages' front matter:
---
...
assets: "/assets/<project-name>"
...
---
How can one determine the number of files in the assets' sub-directories? For example:
{% assign img_dir = page.assets | append: "img/" %}
{% if <files-in-img_dir>.length > 1 %}
// Render multiple images
{% else %}
// Render single images
{% end if %}
As of right now I'm using something like below, but I would like to be able to optimize (imports, build, etc.) based on the number of assets to render.
{% for asset in site.static_files %}
{% if asset.path contains img_dir %}
// Render
{% endif %}
{% endfor %}
Thanks.

Related

Jekyll blog - How to show a list of posts if list file exists

What I'm trying to do is for each category page, if a file exists with the category name then use that file for the list of popular posts. If not then I want to use the default popular posts.
The category featured post file would exist in this folder, if there is one "_includes/blog/feat-posts."
I want to display in the sidebar of my blog. Here's the code I tried using some documentation I found online. This does not work.
<h3>POPULAR POSTS</h3>
{% comment %}(Not sure if this is the correct code, but looking for static file){% endcomment %}
{% for static_file in site.static_files %}
{% comment %}(if a file exists with the same name as the category name, then..){% endcomment %}
{% if static_file.path == '_includes/blog/feat-posts/{{page.autopages.display_name}}.html' %}
{% comment %}(include that file){% endcomment %}
{% include {{ blog/feat-posts/{{page.autopages.display_name}}.html }} %}
{% else %}
{% comment %}(otherwise use the default files){% endcomment %}
<p>Filename1 Text</p>
<p>Filename2 Text</p>
{% endif %}
{% endfor %}
Please help.
I still don't know what "it does not work" means but I assume the error happens in the line with include or your file is not in your static_sites.
You can check the site.static_files content by adding {{ site.static_files | inspect }} to your code. Static files are kind of special, see https://jekyllrb.com/docs/static-files/.
To construct paths dynamically, you may want to use assign to assign the value to a variable first (see simplified example below).
I could check the path by adding a file to the root folder (path /test.html) and then link to the same file name in the _includes folder:
<h3>POPULAR POSTS</h3>
{% comment %}{{ site.static_files | inspect }}{% endcomment %}
{% for static_file in site.static_files %}
{% if static_file.path == '/test.html' %}
{% assign filename = 'test.html' %}
{% include {{ filename }} %}
{% endif %}
{% endfor %}
I hope this helps.

Idiomatic way in Jekyll to inherit default data if project specific data unavailable

I am completely new to Jekyll. I did something like this:
{% assign top_nav = site.data.menus %}
{% if site.data.orgs[site.orgData].menus %}
{% assign top_nav = site.data.orgs[site.orgData].menus %}
{% endif %}
<ul>
{% for menu in top_nav %}
<li>
{{ menu.title }}
</li>
{% endfor %}
</ul>
Basically, I will grab an array of navigation items from a default folder. But if I notice the existence of a menu for a specific organization, then I will override the menu provided by the default folder.
What I don't like about this approach is I now have hundreds of places in my jekyll templates that does this if statement check. If this were any other scripting programming language, I would define a function like function($org_name,$prop) {return $site.data.orgs[$org_name][$prop] ? $site.data.orgs[$org_name][$prop] : $site.data[$prop]; } . What would be the idiomatic way to achieve the same objective in jekyll?
I tried a variation of David Jacquel's suggestion by doing this
./org_var.html
{% assign prop = include.prop %}
{% assign orgVar = site.data[prop] %}
{% if site.data.orgs[site.orgData][prop] %}
{% assign orgVar = site.data.orgs[site.orgData][prop] %}
{% endif %}
./_include/nav.html
{% include_relative ../org_var.html prop=menus %}
{% for menu in orgVar %}
... print menu items
./_layout/header.html
{% include_relative ../org_var prop='electronics.televisions' %}
{% for tv in orgVar%}
{{ tv.modelName }}
... print tv values
{% endfor %}
But I get a syntax error in ../org_var.html saying {% include_relative file.ext param='value' param2='value' %} . The documentation says I can't use relative path with include or include_relative. How do I make my org_var.html a reusable and global function? And will electronics.televisions even evaluate properly to the proper path of my site.data.org.[site.orgData][...path] variable?
Just realized there is a default: modifier for a variable like smarty templates.
{% assign top_nav = site.data.orgs[site.orgData].menus | default: site.data.menus %}
You can use Jekyll includes.
From anywhere you want to use your include :
{% include nav.html org_name=org_name prop=prop %}
Will call _include/nav.html that can be something like this :
{% assign org_name = include.org_name %}
{% assign prop = include.prop %}
{% if site.data.orgs[org_name][prop] %}
{% assign top_nav = site.data.orgs[site.orgData].menus %}
{% else %}
{% assign top_nav = site.data.orgs[site.orgData].menus %}
{% endif %}
<ul>
{% for menu in top_nav %}
...

How to include all files in a folder in Jekyll?

In Jekyll you can include a file by doing:
{% include some-folder/some-file.html %}
If you add more files to the folder you have to manually add them:
{% include some-folder/some-file-2.html %}
{% include some-folder/some-file-3.html %}
{% include some-folder/some-file-4.html %}
Is there a way in Jekyll to include all files in a folder automatically?
It seems possible to have a variable name in an include (source).
If this is allowed:
{% include {{ page.my_variable }} %}
Then also this is allowed:
{% include include_all_files.html folder="some-folder" %}
With an include_all_files.html that looks like this:
{% for file in site.static_files %}
{% if file.path contains include.folder %}
{% include {{ file.path }} %}
{% endif %}
{% endif %}
I have found a way to include the content of all files in the current folder not including the current file.
{% assign parent_path = page.path | split:'/' | last %}
{% assign parent_path = page.path | remove: parent_path %}
{% for file in site.static_files %}
{% if file.path contains parent_path %}
{% assign file_name = file.path | remove: parent_path | remove: "/" %}
{% include_relative {{ file_name }} %}
{% endif %}
{% endfor %}
Reason for my setup: I have a large markdown file (main.md) that contains a lot of information, so I needed a way to move the content into separate files and included them with main.md.

Jekyll/liquid list parameter?

I wanted to create a simply include which simplifies creating a carousel. So I was looking for the syntax to give a list of image urls as a parameter. However I couldn't find anything about this.
{% include carousel.html images=WHAT HERE? %}
You can create a list as a string then convert it into an array inside your snippet. This is the way I would do it.
{% assign urls = 'url1.jpg,url2.jpg,url3.jpg' %}
{% include carousel.html images=urls %}
Of course this is the same as:
{% include carousel.html images='url1.jpg,url2.jpg,url3.jpg' %}
carousel.html
{% assign images = include.images | split: ',' %}
{% for image in images %}
{{ image }}
{% endfor %}

Include a file, but only if it exists?

I'm creating a style guide in Jekyll and using Collections to define different elements of the guide. For example, headings, lists, etc.
I'm trying to separate the Sass into files that match up with the partials, one to one, and I'd like to render the Sass files as part of each collection.
So, something like:
{% if _includes/_sass/{{ entry.title | append: ".scss"}} %}
{% highlight sass %}
{% include _includes/_sass/{{ entry.title | append: ".scss" }} %}
{% endhighlight %}
{% endif %}
Basically, what I want is "Include a file in this directory that has the same name as this entry in my collection. If it doesn't exist, don't break."
How do I do this? I've explored storing the file path in a variable but can't seem to get that to work.
Thanks in advance.
It can be done.
This works on Jekyll 3 but it can certainly be ported to Jekyll 2.
Starting from a base install (jekyll new)
_config.yml
collections:
guide:
sasssamples:
Style guide files
Our samples will be grouped in the _guide collection.
Example file : _guide/header/header1.hmtl
---
title: Header level 1
---
<h1>Header level 1</h1>
SCSS samples
We want our SCSS samples to be included in our css/main.scss and use variables defined in our other SCSS files. Our samples will be integrated at the end of our css/main.scss
We don't want our SCSS samples to render as css so no .scss extension. Switch to .txt extension
We want to access SCSS samples from a list. Let's put them in a sasssamples collection.
Example file : _sasssamples/header/header1.txt
---
---
h1{
color: $brand-color;
border: 1px solid $brand-color;
}
SCSS samples integration
Add this code at the very end of you bootstraping scss file (css/main.scss on a base Jekyll install)
css/main.scss
[ original code ... ]
{% comment %} Selecting a collection the Jekyll 3 way. See https://github.com/jekyll/jekyll/issues/4392 {% endcomment %}
{% assign scssCollection = site.collections | where: 'label', 'sasssamples' | first %}
{% comment %}
Printing documents in sasssamples collection.
All SCSS from style guide are sandboxed in .guide class
This allows us to apply styles only to style guide html samples
{% endcomment %}
.guide{
{% for doc in scssCollection.docs %}
{{ doc.content }}
{% endfor %}
}
The style guide
<h2>Style guide</h2>
{% comment %}Selecting a collection the Jekyll 3 way. See https://github.com/jekyll/jekyll/issues/4392 {% endcomment %}
{% assign guideCollection = site.collections | where: 'label', 'guide' | first %}
{% assign scssCollection = site.collections | where: 'label', 'sasssamples' | first %}
{% comment %} Looping hover style guide samples {% endcomment %}
{% assign samples = guideCollection.docs %}
{% for sample in samples %}
<article>
<h3>Element : {{ sample.title }}</h3>
<h4>Render</h4>
<div class="guide">
{{ sample.content }}
</div>
<h4>html code</h4>
{% highlight html %}{{ sample.content }}{% endhighlight %}
{% comment %}
Changing a path like : _guide/headers/header1.html
to : _sasssamples/headers/header1.txt
{% endcomment %}
{% assign scssPath = sample.path | replace: '_guide', '_sasssamples' %}
{% assign scssPath = scssPath | replace: '.html', '.txt' %}
{% comment %} Try to find a SCSS sample with equivalent path {% endcomment %}
{% assign scssSample = scssCollection.docs | where: 'path', scssPath | first %}
{% comment %}We print SCSS sample only if we found an equivalent path{% endcomment %}
{% if scssSample != nil %}
<h4>SCSS code</h4>
{% highlight css %}{{ scssSample.content }}{% endhighlight %}
{% endif %}
</article>
{% endfor %}
Done!
Seems it only miss on assigning the correct path
{% if _includes/_sass/{{ entry.title | append: ".scss"}}
Need to be replaced to relative path to the scss file:
{% assign scssPath = 'relative/path/to/your/scss/' %}
{% if {{ entry.title | append: ".scss" | prepend: scssPath }} != nil %}