In Jekyll, do all variables have to be defined in _config.yml? - jekyll

In my Jekyll _config.yml file, I have:
...
test1: hello
...
And in my index.html file, I have
...
<h1>{{ site.test1 }}</h1>
...
When my site is built, in _site/index.html, I now have
...
<h1>hello</h1>
...
Here is what I want to do: in my _config.yml file:
...
test1: hello
#include _config2.yml ### this is not possible, but I'd like to do this!
...
Then, in _config2.yml:
...
test2: world
...
In index.html,
...
<h1>{{ site.test1 }}, {{ site.test2 }}</h1>
...
Which would generate, in _site/index.html:
When my site is built, in _site/index.html, I now have
...
<h1>hello, world</h1>
...
I'm trying to figure out how/if this can be done, the idea is that I have a one-page website with dozens of variables, and for the sake of my editors, I would like them to reside in separate .yml files.
Cheers,
Albert

Jekyll provides the option to use data files usable in your pages and posts. This is a perfect case for them.
More information here: http://jekyllrb.com/docs/datafiles/

Related

Jekyll posts aren't using layout accordingly

As described in "specifying layout for html posts in jekyll", Jekyll _posts should behave as any other page when it comes from its _layouts, however it isn't doing this way to me right now.
I'm developing this static site to be hosted in a Github Pages and everything else is working fine, but my posts are not.
I also checked the errors in "Jekyll post not generated" about Jekyll _posts, but the problem wasn't solved.
# _posts/2020-06-27-how-I-long-for-summer.md
---
layout: post
title: How I long for Summer
cover: /assets/img/jhonny.jpg
date: 2020-06-27 20:56:28 -0300
categories: text
---
# _layouts/post.html
---
layout: default
---
# layouts/default.html
<!DOCTYPE html>
<html lang="en">
{% include head.html %}
<body>
{% include navbar.html %}
{{ content }}
{%- include footer.html -%}
</body>
</html>
So, even all regular pages are using default layout accordingly, my post pages have been rendered raw, as if I haven't declared any layout to them.
I'm using minima theme, but actually I was expecting it hasn't any effect since I overwrited post layout.
# _config.yml
markdown: kramdown
theme: minima
permalink: :year/:month/:day/:title
I tried what I could. Does anyone have a clue about what I'm doing wrong?
All of your CSS is using relative paths rather than absolute paths and therefore isn't being fetched correctly.
In your various source code files (head.html, footer.html etc.).
assets/js/main.min.js
assets/js/theme.js
assets/css/main.min.css
assets/css/theme.css
assets/main.css // not available
Should be:
/assets/js/main.min.js
/assets/js/theme.js
/assets/css/main.min.css
/assets/css/theme.css
/assets/main.css // not available
Another solution is to use Liquid's relative_url filter:
https://github.com/jekyll/minima/blob/master/_includes/head.html#L6
https://jekyllrb.com/docs/liquid/filters/

Jekyll Collection Not Rendering

I want to create an archive for old blog posts on my jekyll site. Previously, my structure was serving the contents of _posts on my website homepage, index.html. After reading the collections documentation and a few tutorials online, I have added a collection folder _archive to my structure and a test file inside called test-file.markdown.
However, the url mysite.com/archive/test-file fully regenerates my main index.html, not the collection contents.
Structure:
_archive
index.html
test-file.markdown
_includes
about.html
head.html
... other stuff ...
_layouts
default.html
_posts
post1.markdown
post2.markdown
... other stuff ...
css
img
js
_config.yaml
... other stuff ...
test-file.markdown
---
layout: default
title: test
---
_config.yml
# Site settings
title: test
email: test#test.com
url: http://www.test.com
# Color settings (hex-codes without the leading hash-tag)
color:
primary: ffffff #80B3FF
primary-rgb: "24,288,156" #"128,179,255"
secondary: 2c3e50 #FD6E8A
secondary-dark: 233140 #A2122F
third: 979797
collections:
archive:
output: true
permalink: /archive/:path/
# Build settings
markdown: kramdown
permalink: pretty
mysite.com/archive/index.html
---
---
{% for p in site.archive %}
{{ p}}
{{ p.title }}
{% endfor %}
This re-renders the main index.html, not the contents of test-file.markdown.
How can I properly render the contents of _archive at mysite.com/archive/?
EDIT: added --- to index.html
Did you add the:
---
---
{% for p in site.archive %}
{{ p}}
{{ p.title }}
{% endfor %}
on the top of the index.html file? If it's missing it won't run any content within in that file through jekyll's templating engine.
It's hard to tell what your problem really is without seeing the whole site. Provide a repo URL if possible.
If the contents of /index.html are appearing in the /_archive/test-file.markdown output, the post loop is probably in the default layout file, since both of the files share that layout. The solution here would be to move the relevant content into /index.html.
I believe that your /_archive/index.html is not being output. Move /_archive/index.html to /archive.html. Jekyll doesn't process pages inside of the _archive folder because it starts with an underscore.
You'd then have these files output with your current config:
/archive/index.html
/archive/test-file/index.html
In my opinion, you should keep posts as posts, whether they are archived or not. You would then keep the URLs when posts are archived rather than having to set 301s or losing them to the great void.
To do this, add front matter to your archived posts:
---
archived: true
---
And your current posts (you could use defaults to save repetition):
---
archived: false
---
Exclude the archived posts in your main post loop:
{% assign posts = site.posts | where: "archived", false %}
Exclude the current posts on your archive page:
{% assign archived_posts = site.posts | where: "archived", true %}

Sub templates inside of Jekyll

Is there an equivalent to laravel's #section('') blocks in jekyll? What I am trying to do is create a template that can condense the html shared between multiple jekyll pages. For example:
default_layout
<html>
<div class="page-content">
<div class="wrapper">
{{ content }}
</div>
</div>
</html>
page_1
---
layout: default
permalink: xxx
---
<head>
<title>My title</title>
{% include header.html %}
...
<div> <!-- A shared block between pages with different content --> </div>
....
<div> <!-- Another shared block between pages with different content --> </div>
{% include footer.html %}
</html>
It looks like the current offering of jekyll allows you to use sub-templates, but limits the {{content}} block to be a separate file that also inherits the child template. I would need to create a bunch of files that inherent one another to create the final html page (or so I think).
What worked for me in Laravel was using multiple #yield and #section statements to easily insert dynamic data into a shared template. I don't think Jekyll can do this without creating a bunch of nested sub templates, but I hope I am wrong.
Solution 1:
You could use Jekyll's include files for that.
You probably already know about includes, because you're using them in the layout file in your question.
If your shared blocks are just HTML, using an include is all you need.
But maybe (I'm not sure) the shared blocks are text, meaning you'd like to use Markdown for formatting?
By default, Jekyll doesn't render Markdown in include files, but with a little trick it's still possible to include Markdown files.
I have a site where I needed the same block of text (with formatting and links) on multiple pages, so I did this:
Put the text in a Markdown file into the _includes folder, e.g. _includes/info.md
Include that file and render the Markdown by capturing it and then using the markdownify Liquid filter:
{% capture tmp %}{% include info.md %}{% endcapture %}
{{ tmp | markdownify }}
Solution 2:
If the shared blocks are the same for certain groups of pages, maybe you want to use multiple layout files.
The best example of this would be a blog built with Jekyll:
You have a "basic" layout (navigation, sidebar, footer...) that all pages share, and which is directly used by "regular" pages.
Then, you have a second layout "inheriting" from the main one, which adds stuff like post date, tags and so on - this is used by all blog posts.
Here's a simple Jekyll example for this.

How do I use JSON/YAML in Hexo Templates?

I've looked through the documentation for Hexo in it's entirety, but I'm still not exactly sure how to integrate structured data (YAML, JSON) into a page/post using Hexo templating. The closest I could find is the File Data section of the plugins documentation. I'm not really sure if this is what I'm looking for, and there aren't any examples of implementation.
For those familiar with Jekyllrb, the popular Ruby static site generator, you can use a _data directory to store JSON and YAML files. In templates you can reference this data using something like {% for event in site.data.events %}...{% endfor %}.
Is there an equivalent in Hexo?
If you want to access YAML or JSON data in your markdown files, then do the following.
Create your static data file: /source/_data/mydata.yml
var1: "value 1"
var2: "value 2"
var3: "value 3"
Then access it in your post /source/_posts/mypost.md:
---
title: "My Post"
data: 2021-01-01 14:41:29
---
{{ site.data.mydata.var1 }}
You may use expressions like <%= page.title %>, <%= page.date %> or even <%= page.foo %> (in EJS templates) where title, date and foo is a YAML attribute from the header of your post or page, e.g. source/_posts/2015-06-14-my-awesome-post.markdown":
---
layout: post
title: "My Awesome Post"
date: 2015-06-14T17:23:00+04:00
foo: bar
---
Hello World
Hexo 3 now does data files, Jekyll-style.
From documentation:
This feature loads YAML or JSON files in source/_data folder so you can use them in your site.
For example, add menu.yml in source/_data folder.
Home: /
Gallery: /gallery/
Archives: /archives/
And you can use them in templates:
{% for link in site.data.menu %}
{{ loop.key }}
{% endfor %}

Jekyll automatic table of contents

I have built a website based on the Jekyll code for the website for Apache Buildr. The Buildr website automatically generates a table of contents for each page based on the headers in the textile format files.
For example, you write a page using textile marking out the headings like so . .
h2(#why). Why are we doing this?
BLah blah balh etc ..
h2(#something). Some other header
BLah blah balh etc ..
Then in the default HTML you have some code that pipes the content into something called toc and then you put the contents afterward. For example ...
<div id='content'>
<h1 id='{{ page.title | downcase | replace(' ', '_') }}'>{{ page.title }}</h1>
{{ content | toc }}
{{ content }}
</div>
On the Apache site they get the desired results (the toc is shown followed by the contents). However, on my site, the contents are rendered twice. No table of contents is generated.
Furthermore, if I clone the Apache Buildr project directly from github and run jekyll --server in the doc folder of that project, then no table of contents is generated either.
What am I missing?
I emailed the Buildr developer mailing list and someone told me to look here for inspiration. Turns out that the relevant code snippet is ...
module TocFilter
def toc(input)
output = "<ol class=\"toc\">"
input.scan(/<(h2)(?:>|\s+(.*?)>)([^<]*)<\/\1\s*>/mi).each do |entry|
id = (entry[1][/^id=(['"])(.*)\1$/, 2] rescue nil)
title = entry[2].gsub(/<(\w*).*?>(.*?)<\/\1\s*>/m, '\2').strip
if id
output << %{<li>#{title}</li>}
else
output << %{<li>#{title}</li>}
end
end
output << '</ol>'
output
end
end
Liquid::Template.register_filter(TocFilter)
Make a folder in the source folder of your site called _plugins and then paste this code into a file called TocFilter.rb within that folder.
It works!!
Where is toc defined? It isn't listed as one of the standard liquid filters or jekyll extensions, so likely you are missing a plugin.
I've used ghiculescu's JS TOC on my Jekyll powered Github blog. It works very well.
Example.
jekyll-toc plugin does this for you out of the box.
Add the following to your GemFile
gem 'jekyll-toc'
Add the following to your _config.yml
plugins:
- jekyll-toc
Add the following liquid tag where you want the TOC to be generated.
{{ content | toc_only }}
And finally set toc: true in your post's front-matter.
I added this value as a default in my _config.yml so that TOC is applied to all my posts by default.