sylvain durand

Improving typography on Jekyll

Observing typographical rules on the Internet is not always easy: although Unicode reserves many areas of characters for typographic symbols, many punctuation marks and spaces are most of the time unused.

With Jekyll, the articles are written very simply with Markdown before being generated in HTML by the engine: we can add automatic rules to improve typography on our site without carrying about it when writing articles.

Apply filters to the content

Modify paragraphs, leave the code

Care must be taken to apply the changes only in paragraphs, not in code blocks that could become unusable for users that will copy them.

To do so, we will replace {{ content }}, in the _layout/default.html file (or equivalent), with:

{% assign content = content | split: '<pre' %}

{% for parts in content %}

  {% assign part = parts | split: '</pre>' %}
  {% assign c = part.first %}
  {% assign t = part.last %}

  {% if part.size == 2 %}

    {% capture output %}{{ output }}<pre{{ c }}</pre>{% endcapture %}

  {% endif %}

  {% capture output %}{{ output }}{{ t }}{% endcapture %}

{% endfor %}
{{ output }}

We just have to act on the variable t, which corresponds to the texts, by applying different filters, just after {% assign t = part.last %}.

For example, if you want to replace all a’s in b’s in the texts, but not in the code blocks, juste use:

{% assign t = t | replace: 'a' , 'b' %}

French typography

We will show here how to make Jekyll automatically generates quotes French and non-breaking spaces to the right length before the various punctuation marks.

Using French guillemets

For quotes French « and », we simply replace English quotation marks, as seen in the previous section, with: (we add a normal non-breaking space before the closing quotation mark, and after entering quote with &#160;)

{% assign t = t | replace: '“', '«&#160;'
                | replace: '”', '&#160;»' %}

Using the right spaces before punctuation

In French, the colons (:) and percent (%) must be preceded by a normal non-breaking space, which is obtained with &#160;. We use:

{% assign t = t | replace: ' :', '&#160;:'
                | replace: ' %', '&#160;%' %}

However, the semicolon (;), the exclamation point (!) and the question mark (?) are preceded by a thin non-breaking space. Thereof is obtained using &thinsp;. However, it is preferable to use <span style="white-space:nowrap">&thinsp;</span>; because some browsers that do not treat the space as indivisible.

We then use the following code to get the desired result:

{% assign t = t | replace: ' ;', '<span style="white-space:nowrap">&thinsp;</span>;'
                | replace: ' !', '<span style="white-space:nowrap">&thinsp;</span>!'
                | replace: ' ?', '<span style="white-space:nowrap">&thinsp;</span>?' %}

Final result

Finally, the following code provides all the typographical improvements presented above:

{% assign content = content | split: '<pre' %}

{% for parts in content %}

  {% assign part = parts | split: '</pre>' %}
  {% assign c = part.first %}
  {% assign t = part.last %}

  {% assign t = t | replace: '“', '«&#160;'
                  | replace: '”', '&#160;»'
                  | replace: ' :', '&#160;:'
                  | replace: ' %', '&#160;%'
                  | replace: ' ;', '<span style="white-space:nowrap">&thinsp;</span>;'
                  | replace: ' !', '<span style="white-space:nowrap">&thinsp;</span>!'
                  | replace: ' ?', '<span style="white-space:nowrap">&thinsp;</span>?' %}

  {% if part.size == 2 %}

    {% capture output %}{{ output }}<pre{{ c }}</pre>{% endcapture %}

  {% endif %}

  {% capture output %}{{ output }}{{ t }}{% endcapture %}

{% endfor %}
{{ output }}

If your website is multilingual, you can restrict the previous modifications to the French articles, by adding:

{% if page.lang == 'fr' %}
...
{% endif %}

Finally, to lighten the code, it is possible to include these codes in a specific page, for example _includes/typography.html. Then, we simply use:

{% if page.lang != 'en' %}
    {% include typography.html %}
{% else %}
    {{ content }}
{% endif %}