Home > front end >  Dynamically change link target in Jekyll when target does not exist
Dynamically change link target in Jekyll when target does not exist

Time:11-09

I need to insert links but check whether a file exists in this language. I want to adjust the link target dynamically during or after build.

Currently, due to the nested structure of the navigation file, a generator plugin creates an index of articles with their properties, e.g. title, path, etc. The information is accessible in includes in site.docs_by_site.

The idea is to correct any missing links to other articles in the page content by passing a partial link to an include file. The link will be passed into a parameter.

I would insert links like this:

{% include link.html path='getting-started/test.md' %}

I though using an include file could work out:

{% if page.lang == 'en' %}
  {% assign full_path = "_" | append: 'en' | append: "/" | append: include.path %}
  {% assign post = site.docs_by_path[full_path] %} 
{% endif %}

{% if page.lang != 'en' %}    
  {% assign full_path = "_" | append: page.lang | append: "/" | append: include.path %}
  {% assign localized_file = site.docs_by_path[full_path] %}

  {% if localized_file %}
    {% assign post = localized_file %}
  {% else %}
    {% assign full_path = "_" | append: 'en' | append: "/" | append: include.path %}
    {% assign post = site.docs_by_path[full_path] %} 
  {% endif %}
{% endif %}

<div>
{% if post[0] == nil %}
  <a href="wrong-link-target">wrong-link-target {{ full_path }} in {{ page.url }}</a>
{% else %}
  <a href="{{ post[0] }}">{{ post[1] }} <sup>in English</sup></a><!-- localize sup using i18n - it: in inglese, es: en inglés, nl: in Engels -->
{% endif %}
</div>

Is it smart and does it make sense at all or do you see any downsides, e.g. performance? I need to check and adjust several thousand links. Can it be implemented better, e.g. using another Jekyll plugin?

I have created a sample repo with code using conditionals, see include file and a sample file.

Bonus question: The include returns the element inside a p tag - any idea how to workaround this?

CodePudding user response:

This is a good idea, but I think it can be improved.

First, you don't need to use the docs_by_path variable. You can use the docs variable, which contains all the documents in your site.

Second, you can use the where filter to find the document you're looking for.

Third, you can use the url_for helper to generate the URL for the document.

Here's how I would do it:

{% if page.lang != 'en' %}
  {% assign path = '_' | append: page.lang | append: '/' | 
append: include.path %}
  {% assign post = docs | where: 'path', path | first %}
  {% if post %}
    <a href="{{ post.url }}">{{ post.title }}</a>
  {% else %}
{% assign path = '_' | append: 'en' | append: '/' | append: 
include.path %}
    {% assign post = docs | where: 'path', path | first %}
    {% if post %}
      <a href="{{ post.url }}">{{ post.title }}</a>
    {% endif %}
  {% endif %}
{% endif %}

The where filter takes a property and a value and returns all the documents where the property is equal to the value.

The first filter returns the first document in the array, or nil if the array is empty.

The url_for helper generates the URL for a document.

If you need to generate a URL for a document in a different language, you can pass the lang parameter to the helper. For example, to generate the URL for a document in the French language, you would use this:

{{ post.url | prepend: '/lang/fr' }}
  • Related