Blogging with Middleman: Partials Are Magic

Now that you've got your Middleman blog set up, let's use Partials to customize your posts.

Partials are small templates that can be inserted into larger layouts. They're great for bits of content that you want rendered on multiple pages, like header or footer links.

Moreover, partials can also be brought directly into your blog posts, layering on top of your Markdown to create even richer, more flexible content.

Use Case

While working on this blog, I realized that I wanted to display images in four contexts: large or small; and as a freestanding image, or paired with a caption. If an image came with caption text, I wanted to wrap the image in a <figure> element with an accompanying <figcaption>.

Markdown, unfortunately, doesn't provide a way to mark up <figure> elements. It allows raw HTML, such as this red text, but that wouldn't have been a sustainable workaround. If the <figure> spec changed, I would have to go around and update every post that used it.

Creating a partial

The solution was to create a partial template that could render media in different contexts. The file itself looks like this:

<% if locals[:caption] %>
  <figure role="img" class="image-wrap image-<%= locals[:size] %>">
<% else %>
  <div class="image-wrap image-<%= locals[:size] %>">
<% end %>
    <%= image_tag locals[:src], { alt: locals[:alt], title: locals[:title], width: locals[:width] , height: locals[:height] } %>
<% if locals[:caption] %>
  <figcaption>
    <p><%= locals[:caption] %></p>
  </figcaption>
</figure>
<% else %>
  </div>
<% end %>

The partial checks the locals I pass in for a caption and renders a different element accordingly. locals values also provide the path and other attributes of the image, and determine what styling the element will receive.

I include this partial by writing the following straight in my Markdown:

The main characters of "My Little Pony: Friendship is Magic" crowd the camera.

<%= partial(:media, :locals => {
  :src => 'ponies.png',
  :title => 'The main characters from "My Little Pony: Friendship is Magic"',
  :alt => 'The main characters of "My Little Pony: Friendship is Magic" crowd the camera.',
  :size => 'secondary',
  :width => '900px',
  :height => '809px',
})%>

This ERB tells Middleman to find the "media" partial and pass in the locals specified. Partials are located relative to /source, so this particular partial is found at /source/media.erb.

Using a partial

Finally, we need to tell Middleman that it will be seeing ERB in our posts. By default, Middleman only expects Markdown in blog posts; hence the .markdown extension of all the files in /source/articles. It can't yet parse ERB.

Thanks to Middleman's super cool extension chaining, add an .erb to the end of your post's extension, and you're done! .markdown.erb works, as does .md.erb, or any set of extensions where the ERB-related extension comes after the Markdown-related one.

These extensions tell Middleman to make one pass of the file and render any ERB that it finds. It then makes a second pass and renders any Markdown found; the file is now entirely converted to HTML.

Give all new blog posts these extensions by changing this line in your config.rb:

# blog.default_extension = ".markdown"

to something like

blog.default_extension = ".markdown.erb"

This means that all new blog posts created via middleman article <articleName> will have that extension and be ready to accept partials.


I hope you are ~fully~ convinced of the power of partials. I may revisit them again when I change my media partials from using <img> to <picture>, which will be a journey in its own right.

Coming next: custom Markdown rendering and syntax highlighting in code blocks. Read my first Middleman post here.