Is there a way in Jekyll to set a base path for images?

Viewed 603

I am creating blog with Jekyll and for the sake of organization I have decided to put the images under the folder: "assets/img/[post name]/". The folders look like this:

.
├── assets
│   ├── css
│   │   ├── BMFW.css
│   │   └── vs.css
│   └── img
│       └── 2021-05-23-Blog-presentation
│           └── test.jpg <--
├── _config.yml
├── Gemfile
├── Gemfile.lock
├── index.html
├── _layouts
│   ├── layout.html
│   └── post.html
├── _posts
│   └── 2021-05-23-Blog-presentation.md
├── README.md
└── script
    └── cibuild

Seems that the page.name variable for some reason does not exist (I have checked it with {{page | inspect}}) so I use this line to get the name of the post:

{{ page.path | replace: ".md","" | split: "/" | slice: -1 | }}

That means that if I want to display an image called test.jpg I would write:

![]({{ site.baseurl }}/assets/img/{{ page.path | replace: ".md","" | split: "/" | slice: -1 | }}/test.jpg)

The only thing that changes from one image to another is the name of the image. So my question is: is there a way to set a base path, in my case {{ site.baseurl }}/assets/img/{{ page.path | replace: ".md","" | split: "/" | slice: -1 | }}/, so I don't have to write the full path over and over again?

The ideal solution would be to just have to write ![]({{media}}/test.jpg) or similar.

EDIT 1:

Just in case it is useful for anybody, what I am doing now is to put this line at the beginning of each blog entry:

{% assign media = site.baseurl | append: "assets/media/" | append:  page.path | replace: ".md","" | replace: "_posts/",""  %}

So then I can insert images just writing:

![]({{ media }}/test.jpg)

It is not a solution because I still have to put that line at the beginning of every post but is better than before.

EDIT 2:

I have looked to make some custom pluggin in Jekyll but I haven't found a way to get access to the page properties.

Another option was to create a custom tag that inserted the liquid code: {{site.baseurl | append: "assets/media/" | append: page.path | replace: ".md","" | replace: "_posts/","" }}. The problem with this one is that once the custom tag has ben executed jekyll continues and does not execute the newly inserted liquid code.

2 Answers

To avoid repetition in Jekyll, you use includes. You could make a _includes/image.html file like this:

{% assign media = site.baseurl | append: "assets/media/" | append:  include.post | replace: ".md","" | replace: "_posts/",""  %}
<img src="{{ media }}/{{ include.file }}">

and use it like this:

{% include image.html post=page.path file="test_1.jpg" %}
{% include image.html post=page.path file="test_2.jpg" %}

The only problem is that the included file can't see anything from the file that's not passed as a parameter, so we can't get rid of the post=page.page part. However, that's less repetition than with your current solution.

Related: Macro in Liquid template language.

Would using static files in Jekyll be sufficient for setting the base path for all your image assets?

Add to _config.yml:

defaults:
  - scope:
      path: "assets/img"

All the static files will have base path assets/img added to their file.path metadata.

Edit: Here is Liquid snippet on getting the path in the defaults

{% assign defaults = site.defaults %}
{{ defaults[0].scope.path | inspect }}
Related