Notes to self

Inserting content in the middle of a Jekyll post

Do you wish to insert content (such as advertisement or a link) right in the middle of the Jekyll page? We can do that by using the content as an array and a forloop. Here is how.

If we want to insert something in the middle of a blog post, we need to separate the main content with split Liquid template filter:

{% assign content_array = page.content | split: site.excerpt_separator %}
{% assign excerpt_only = content_array | first %}
{% assign content_remainder = content_array | last %}

Above, we got an example of splitting with your excerpt separator, which should work for the regular posts and creating a content_array. Then we can show the first part, the excerpt, and the remainder by using first and last filters.

Dependending on the separator we can also append or remove leading and trailing tags:

<div class="post-excerpt">
  {{ excerpt_only | append: '</p>'}}
</div>

<div class="post-content">
  {{ content_remainder | remove_first: '</p>'}}
</div>

However, if we want a bit more flexibility, we need to use a forloop to insert a specific bloc to a specific place:

{% for block in content_array %}
  {{ block }}

  {% if forloop.index0 == 1 %}
    Inserting content in the middle!
  {% endif %}
{% endfor %}

In the snipped above, I am putting content after the second block. We can leverage forloop’s various properties to fiddle with the results:

  • forloop.length: length of the entire forloop
  • forloop.index: index of the current iteration
  • forloop.index0: zero-based index of the current iteration
  • forloop.rindex: index of how many items are still left
  • forloop.rindex0: zero-based index of how many items are still left
  • forloop.first: first iteration
  • forloop.last: last iteration

Finally, if you have code blocks in your posts, using the default excerpt separator would break them. In such case, we have to check for language-XXX highlighter-rouge class and split accordingly by code mentions (the split is a little different, but things might work as you intented). Don’t forget to replace XXX to the language you use. Here is an example:

{% if page.content contains 'language-elixir highlighter-rouge' %}
  {% assign content_array = page.content | split: '<div class="language-elixir highlighter-rouge">' %}
{% elsif page.content contains 'highlighter-rouge' %}
  <!-- no split -->
  {% assign content_array = page.content %}
{% else %}
  {% assign content_array = page.content | split: site.excerpt_separator %}
{% endif %}

Work with me

I have some availability for contract work. I can be your fractional CTO, a Ruby on Rails engineer, or consultant. Write me at strzibny@strzibny.name.

RSS