How can I use Jekyll to test for the existence of a file?
To clarify, I want to run an {% if %} statement to check if an image file exists with the same name as the page I am on.
On my page in the YAML front matter:
----
reference-design: true
----
In my layout:
{% if page.reference-design %}
{% assign filename = page.path | remove_first: '.html' %}
<!-- How can I check if file actually exists? -->
<img src="images/reference_designs/{{ filename }}.png">
{% endif %}
As of Jekyll 2, all site files are available via site.static_files. You can use this to check if a file exists. For example:
{% for static_file in site.static_files %}
{% if static_file.path == '/favicon.ico' %}
{% assign favicon = true %}
{% endif %}
{% endfor %}
I had a similar problem to solve, but specifically looking for videos that matched the a specific directory / filename based on the markdown file.
Using file.size allowed me to test if the file (actually) exists.
{% for video in site.video-demos %}
{% assign path = page.id | replace: page.slug , "" | prepend: '/assets/media/video' | append: video.directory | append: page.slug | append: ".mp4" %}
{% assign file_exists = site.static_files | where: "path", path %}
{% if file_exists.size != 0 %}
{% include video-player.html filename = path title = video.title %}
{% endif %}
{% endfor %}
It loops through an array from my config to get part of the directory structure:
video-demos:
- title: iOS Voiceover Safari
directory: ios/
- title: Android Talkback Chrome
directory: android/
- title: Windows Jaws Chrome
directory: jaws/
- title: Windows NVDA Chrome
directory: nvda/
- title: MacOS Voiceover Safari
directory: macos/
This plugin worked for me: https://github.com/Wolfr/jekyll_file_exists
After you install it, you can use it like:
{% if page.reference-design %}
{% assign filename = page.path | remove_first: '.html' %}
{% capture img_exists %}{% file_exists {{ filename }}.png %}{% endcapture %}
{% if img_exists == "true" %}
<img src="images/reference_designs/{{ filename }}.png">
{% endif %}
{% endif %}
Read http://ecommerce.shopify.com/c/ecommerce-design/t/testing-if-a-file-exists-29624. Also you might be able to play with capture.
Related
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.
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.
Context
I have a jekyll collection called product-categories in which each file has the following metadata in front matter:
_product-categories/filename1.md
---
- title
- uuid
---
I have a page whose front matter contains filenames from this collection (collection array selections are saved by their filenames with front matter)...
page.html
---
product-categories:
- filename1
- filename2
---
[list of product-categories to be displayed here]
Goal
I want to display the title (from the collection metadata) of these product-categories on the page. Since the items are saved in the front matter by their filename, shouldn't this be possible?
You can do like this :
{% comment %} --- Get product-categories collection's datas --- {% endcomment %}
{% assign collection = site.collections | where: "label", "product-categories" | first %}
{% comment %} --- collection's docs root path --- {% endcomment %}
{% assign collection_path = collection.relative_directory | append: "/" %}
<ul>
{% for cat in page.product-categories %}
{% comment %} --- expected file path --- {% endcomment %}
{% assign filepath = collection_path | append: cat | append:".md" %}
{% comment %} Look for files that have path == filepath.
As "where" filter return an array,
we pick the first and only item in array {% endcomment %}
{% assign file = site.product-categories | where:"path", filepath | first %}
{% if file %}
<li>{{ file.title }}</li>
{% else %}
{% comment %} --- error in front matter list ---{% endcomment %}
<li>No file match for <strong>{{ cat }}</strong> : file at <strong>{{ filepath }}</strong> not found</li>
{% endif %}
{% endfor %}
</ul>
I have been trying to create a site with Github and I'm new to the whole thing. I have been struggling with a piece of code that has been giving me some headache:
{% for item in site.static_files %}
{% if item.path contains '/archive' %}
{% if item.path contains 'index.html' == false %}
{% assign split_path = item.path | split: '/' %}
<p>{{item.path}}</p>
{% assign filename = split_path.last %}
<p>{{ filename }}</p>
{% endif %}
{% endif %}
{% endfor %}
This generates the following error:
Error:
Liquid Warning: Liquid Syntax Error (line 5): Expected end_of_string but found comparison in "item.path contains 'index.html' == false" in archive/index.html
Can anyone help?
Replace:
if item.path contains 'index.html' == false
With:
unless item.path contains 'index.html'
Liquid's getting confused.
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 %}