Include another page with Jekyll without displaying Front Matter - jekyll

I'm trying to clone the output of index.html in another page, thanks.html. It's working, but no matter what I try I end up with --- layout: default title: example --- rendered (from index.html's Front Matter) where the file starts.
I've tried:
---
layout: default
thanks: true
---
{% capture main %}{% include_relative /index.html %}{% endcapture %}
{{ main }}
And:
---
layout: default
thanks: true
---
{% include_relative /index.html %} <!-- Same problem with just 'include' -->
But I get the same result.
If I drop the line layout: default it works, but as expected I don't have a header or footer anymore. I can also get it to work using includes but this makes for a lot of duplication for a page with a single line that's different.
In case it's relevant, I'm running Jekyll version 4.2.2 via docker, and there are no plugins set in my _config.yml.

A fragile hack:
{% capture source %}{% include_relative included.html %}{% endcapture %}
{{ source | split: "---" | last }}
Just don’t use --- anywhere in the included document. :)

Related

Getting current url from a collection in Jekyll

If I want to get a page's url it's not exactly complicated:
page.url
However, what if I make a collection who's job it is to be used like an include instead of like a page?
If I make such a collection and ask for page.url it gives me the path to the collection instead of the path to the current url.
Is there a way to get the real current URL in Jekyll?
Edit: example
test.md:
---
title: Test page
permalink: /test/
---
Test page
{% for block in site.blocks %}
{% if block.whatever %}
{{ block.content }}
{% endif %}
{% endfor %}
_blocks/block.md:
---
whatever: true
---
{% page.relative_path %}
Got:
Test page
/_blocks/block.md
Expected:
Test page
test.md
I've been using jekyll for a short time and I'm relying on collections to build my first static portfolio site. So far all my attempts when trying to get the path to the current url simply fails.
In order to achieve the desired result, I've used Jekyll Liquid filters.
Here is how you'd get the expected result you as per your question:
test.md:
---
title: Test page
permalink: /test/
---
Test page
{% for block in site.blocks %}
{% if block.whatever %}
{{ block.content }}
{% endif %}
{% endfor %}
_blocks/block.md:
---
whatever: true
---
{{ page.relative_path | replace:'index.html', '' | remove: '_blocks/' | prepend: site.baseurl }}
Output on Test page
Test page
test.md
Update:
Perhaps the following is not the most straightforward method to get the path to the current url, but by defining relative_path: in the front-matter definitions of a document you'd also get the result you expect, of course this is something required on a per page basis.
---
whatever: true
relative_path: test.md
---
{% page.relative_path %}
So in this very specific case
{% page.relative_path %}
should output
test.md
A Jekyll's doc reminder:
As per Jekyll's doc, when you create a collection it becomes available via the site Liquid variable, pretty much like site.posts and site.pages, so you're able to use the available filters in most cases.
I hope it helps!

Include files and also copy them to output

In a Jekyll powered page, I have a set of files located in:
_includes/stuff/
I put those files there so that I can include them in other Markdown pages using:
{% include stuff/example.txt %}
This works as expected.
However, I also want to copy those files to the generated page so that I can link to them and that people can follow those links to download them. But by definition, stuff stored in directories starting with an underscore are not copied by Jekyll.
Another approach also didn't work. I put the files in an own top folder called stuff. This copies the folder to the final site. However, I'm not able to include a file from this folder. It seems include_relative only allows including files below the current one. For example, the following don't work:
{% include_relative stuff/example.txt %}
{% include_relative /stuff/example.txt %}
{% include_relative ../stuff/example.txt %}
Any ideas how I can achieve including and copying at the same time?
This works from index.html
{% include_relative example.txt %} for example.txt
{% include_relative stuff/example.txt %} for stuff/example.txt
{% include_relative /stuff/example.txt %} for stuff/example.txt
stuff/example.txt
class Toto
def dototo
myvar = "toto"
end
end
index.html
{% assign codeurl = "stuff/example.txt" %}
{% highlight ruby %}
{% include_relative {{codeurl}} %}
{% endhighlight %}
link to code
if codeurl == "/stuff/example.txt" this generates a link relative to site root
this may need {{site.baseurl}} prepended if your site is not at the root
of a domain (eg: user.github.io/repository)
link to code
For security reasons, this will not work :
{% include_relative ../stuff/example.txt %}
Just to avoid directory traversal
{% include_relative ../../../../../../../../../../../../etc/pwd %}
If you want to put you files in _includes/stuff you will need to do an include: [ /_includes ] in _config.yml, that will include all files in _includes as static files. Not very clean as you cannot filter subdiretories like include: [ /_includes/stuff ] to import only your stuff files.
Note : a dirty trick allows you to import only _includes/stuff/*.txt but I think it's really dirty.
# _config.yml
include:
- "_includes"
- "stuff"
- "*.txt"
exclude:
- "_includes/*.*"

Jekyll Docs folder

Im my Jekyll website I need to create an documentation section similar to Original website. However I am not sure how the Docs sections renders. For example, the docs folder, which is located in site root, is filled with documentation .md files. This folder doesn't inculde any index.html file responsible for Layouting of website. The link to that folder is
Doc<span class="show-on-mobiles">s</span><span class="hide-on-mobiles">Documentation</span>
Could someone shed a light on how this section is rendering?
The docs folder includes an index.md, which is rendered as index.html in the final site.
If you look at the YAML front matter of index.md, you'll see this:
---
layout: docs
title: Welcome
next_section: quickstart
permalink: /docs/home/
---
The permalink: /docs/home/ line sets the final URL to {{ site.url }}/docs/home/, even though the actual file is in the /docs folder and the /docs/home folder doesn't even exist.
(for more info about the permalink setting, see Predefined Global Variables in the docs)
So that's where the URL comes from.
Concerning the list of documentation topics (the sidebar on the right):
The YAML front matter of index.md (see above), also contains the line layout: docs.
This refers to /_layouts/docs.html, a layout file.
Inside the layout file, there's the line {% include docs_contents.html %}, which refers to _includes/docs_contents.html, an include file, which contains the following code:
{% for section in site.data.docs %}
<h4>{{ section.title }}</h4>
{% include docs_ul.html items=section.docs %}
{% endfor %}
site.data.docs (in the first line) refers to /_data/docs.yml, a YAML data file.
It looks like this (shortened):
- title: Getting Started
docs:
- home
- quickstart
- installation
- usage
- structure
- configuration
- title: Your Content
docs:
- frontmatter
- posts
- drafts
- pages
- variables
- datafiles
- assets
- migrations
The code inside docs_contents.html loops through the items in the data file, displays the title values ("Getting Started", "Your Content"...) and then includes another include file /_includes/docs_ul.html, passing the list of docs from the data file.
This second include file loops through the list of docs, and does the following for each one:
Step 1:
{% assign item_url = item | prepend:'/docs/' | append:'/' %}
This builds the URL of the page based on the list item. For example, quickstart becomes /docs/quickstart/.
Step 2:
{% if item_url == page.url %}
{% assign c = 'current' %}
{% else %}
{% assign c = '' %}
{% endif %}
This marks the current page (used in the next step) by checking if the URL created in the previous step is equal to the URL of the current page.
Step 3:
{% for p in site.pages %}
{% if p.url == item_url %}
<li class="{{ c }}">{{ p.title }}</li>
{% endif %}
{% endfor %}
This loops all pages in the whole site, until it finds the page with the URL created in the first step.
(to make sure that the URL is equal, all Markdown files in the docs folder have set a permalink in the front-matter, for example permalink: /docs/quickstart/ in quickstart.md)
Then, it outputs a <li> with a link to the page, using the title from the respective Markdown file as the link text.
Plus, the class of the <li> is set to current if it's the current page (see step 2), so the current pae is highlighted in the list:

Overriding YAML frontmatter variables from Liquid

I would like my outermost Liquid template file to reference a JavaScript file only when the page requires it. I created a page variable, page.slideshow, which controls this:
default.html:
{% if page.slideshow %}
<script type="text/javascript" src="/js/slideshow.js"></script>
{% endif %}
Now I have a template that "inherits" from default.html, which allows the page to specify in its YAML frontmatter a list of images (page.images). Only when this list has more than one element do I want slideshow.js to be included in the page.
My attempt at this looks something like:
other.html
---
layout: default
---
{% assign imagecount = page.images | size %}
{% if imagecount > 1 %}
{% assign page.slideshow = true %}
{% endif %}
However, this does not seem to affect the rendering of default.html, because the script tag is not included in the final page.
As a workaround, I can modify the frontmatter of each page that lists multiple images to explicitly set slideshow: Yes, or change default.html to check page.slideshow or (page.images | size) > 0 but I'd prefer to structure it closer to what I attempted above.
I've had a play about and you can't really do it the way you've suggested. It seems page variables just cant be modified once they're set. You might be able to set it with Jekyll plugins, but that's a whole other thing.
The cleanest way I have found to do it is to put all the logic in your main, outermost template.
{% assign imageCount = page.images | size %}
{% if page.slideshow or imageCount > 1 %}
{{ page.images | size }}
<script src="/js/slideshow.js"></script>
{% endif %}

Strip url to 1 word in Jekyll

I am building a Jekyll blog, and I have come across an issue with permalinks.
My permalinks to blog posts are set like this in
_config.yml:
permalink: /:page/:categories/:title
It outputs like this when navigating to a blog post:
http://localhost:4000/blog/travel/netherlands-trip-prequesites/
I have some static pages in the site: Blog, Travel
The variable page.url outputs this url: /blog/travel/netherlands-trip-prequesites
The code my navigation bar uses to highlight the current page (giving it an "active" class):
{% assign url = page.url|remove:'index.html' %}
{% for nav in site.navigation %}
{% if nav.href == url %}
<li class="active">{{nav.name}}</li>
{% else %}
<li>{{nav.name}}</li>
{% endif %}
{%endfor%}
It works great when navigating to static pages, however when I click a blog post it doesn't highlight the correct static page. (ex.: If i navigate to a blog post with the url /blog/smth/title it should automatically highlight "Blog" in my navigation. When I navigate to /travel/smth/title it should highlight "Travel")
What I'd like to do is to strip down the output of page.url to its first part. For example I'd like to stip the following output
/blog/travel/netherlands-trip-prequesites
down to
/blog/
Why? So I can use it to check which static page it belongs to and highlight it accordigly.
The easiest way is to use split:
{{ page.url | split:'/' | first }}
That will give you the URL content up to the first / character.
I managed to solve it with three filters:
{{ page.url | replace:'/',' ' | truncatewords: 1 | remove:'...' }}
page.url outputs: /page/cat/title, then replace removes the forward slashes producing: page cat title. truncatewords truncates the string down to one word, producing: page... (for some reason three dots gets inserted after the remaining word). After all this I only needed to remove those dots with remove and voilá, my final string: page.
Hope this helps someone.
The answer provided by PeterInvincible was almost perfect, however, there's no need to get piping to remove involved...
The following also will produce desired output
{{ page.url | replace:'/',' ' | truncatewords: 1,"" }}
And to save it to a variable use capture redirection
{{ capture url_base }}{{ page.url | replace:'/',' ' | truncatewords: 1,"" }}{{ endcapture }}
Which can be called via {{url_base}} or mixed with other processing calls.
Also for file paths instead of URLs page.dir works well if you're not using permalink settings for layout, check the gh-pages branch (specifically _includes/nav_gen.html for functional, though rough'round the edges, example) for hosted examples of similar code examples related to liquid syntax and other magic.
Edits & Updates
The above linked script is now live/mostly-working/modular and auto-serving parsed sub-directories viewed currently at the related https://s0ands0.github.io/Perinoid_Pipes/ project site providing examples of recursive parsing of directories. Including and modding for nearly any theme should be possible just check the commented section at the top for currently recognized commands that maybe passed at inclusion call... on that note of inclusion and modularization here's how to turn the above example code for directory parsing into a function
{% comment %}
# Save this to _include/dir_path_by_numbers.html
# import with the following assigning arguments if needed
# {% include dir_path_by_numbers.html directory_argument_path="blog" directory_argument_depth=1 %}
{% endcomment %}
{% assign default_arg_directory_path = page.url %}
{% assign default_arg_directory_depth = 1 %}
{% if directory_argument_path %}
{% assign directory_to_inspect = directory_argument_path %}
{% else %}
{% assign directory_to_inspect = default_arg_directory_path %}
{% endif %}
{% if directory_argument_depth %}
{% assign directory_to_inspect_depth = directory_argument_path %}
{% else %}
{% assign directory_to_inspect_depth = default_arg_directory_depth %}
{% endif %}
{% comment %}
# Defaults read and assigned now to output results
{% endcomment %}
{{ directory_to_inspect_depth | replace:'/',' ' | truncatewords: directory_to_inspect_depth,"" | remove_first: '/' | replace:' ','/' }}
The above should output directory path lengths of whatever size desired and maybe included as shown previously or if feeling adventurous try what's shown below; though for looping and recursive features look to the linked script for how I've worked around stack size restrictions.
{% capture dir_sub_path %}{{include dir_path_by_numbers.html directory_argument_path="blog" directory_argument_depth=1}}{% endcapture %}
Note above is just speculation, untested, and maybe more buggy than scripts tested and hosted publicly... in other words inspiration.
Simplest way would be using
if page.url contains
example:
<li class="{% if page.url contains '/docs/' %}current{% endif %}">
Docs