Daniel Pietzsch

Responsive images

I have now added the ability to display responsive images on this site.

And just as with my photo journal, I’m using the fantastic jekyll-responsive-image plugin1 to do so.

What I did differently this time, though, is that I can use the standard markdown syntax for images, instead of using the custom liquid tag. There are a few reasons for why I wanted it this way:

Replacing Liquid syntax with Markdown

In order for this to work, I can run some code in a pre-render hook that replaces the standard markdown syntax with said custom liquid tag before Jekyll actually converts the file to HTML.

This pre-render hook needs to basically translate the Markdown image syntax to the liquid tag that the jekyll-responsive-image plugin expects. E.g., I want to replace syntax like this (in standard markdown notation):

![alt text](image.jpeg "The title for this image")

…with something like this (which will be the source Jekyll uses to convert to HTML):

{% responsive_image path: image.jpeg alt: "alt text" title: "The title for this image" %}

The Regular Expression

And in order to do so, I need to parse all those different parts of the markdown syntax – image path, alt text, and title text – so I can reuse them when it comes to constructing the liquid syntax. Here’s the regular expression I found to be working – with alt- and title-attributes both being optional:

^\!\[(?<alt>.+)?\]\((?<path>\S+) ?"?(?<title>.*?)"?\)

The Prerender Hook

Here’s the complete code from the pre-render hook2, that does its thing each time right before a markdown file is converted to HTML3:

Jekyll::Hooks.register [:pages, :posts], :pre_render do |post, payload|
  document_extension = post.extname.tr('.', '')
  # Only process if we deal with a markdown file
  if payload['site']['markdown_ext'].include? document_extension
    new_content = post.content.gsub(/^\!\[(?<alt>.+)?\]\((?<path>\S+) ?"?(?<title>.*?)"?\)/, '{% responsive_image path: \k<path> alt: "\k<alt>" title: "\k<title>" %}')
    post.content = new_content
  end
end

An example

In addition to serving the original file, I decided to generate five smaller versions: 320, 640, 960, 1280, and 1920 pixels wide respectively.

And here’s the first responsive image in a blog post:

Zoe and some rubble
  1. My own fork, though, to be precise. 

  2. Thanks to David Jacquel for the original version

  3. And of course, I ran into problems while writing this very article: Since the hook simply processes the whole document – without paying any attention to markdown-specifics, it would have also replaced the standard-markdown-image-syntax code example above. To circumvent the problem, I added the ^ to the regular expression, so that the hook only replaces those occurrences that start at the beginning of a new line. Because then I could use Markdown’s indent-four-spaces-for-code-markup syntax (i.e. not at the start of a new line), which was not replaced – and instead renders the example above, as intended .