Using binary items effectively

Along with textual items, Nanoc also supports binary items. Binary items are not loaded into memory, enabling Nanoc to handle large files. Examples of binary items include images, fonts, audio files, and videos.

This page gives an example of how binary items can be used.

If you want to include a gallery on your website, containing thumbnails that link to full-size images, you can let Nanoc handle the thumbnail generation instead of generating the thumbnails up front.

If you have a lot of images to convert, and if the conversion process itself is taking a long time, consider performing the conversion up-front once, and then let a Rake task copy the generated thumbnails into the output directory. Nanoc’s dependency resolution is not yet perfect; Nanoc may decide to recompile items even though they do not need to.

This example assumes that several images are stored in the content/gallery folder. A file at content/gallery.html corresponds to the gallery page itself; this item is filtered through ERB and, for the time being, contains a list of links to full-size images:

<ul>
<% @items.find_all('/gallery/*').each do |img| %>
  <li><a href="<%= img.path %>"><%= img.path %></a></li>
<% end %>
</ul>

Ensure that the gallery page is filtered using ERB. For example:

compile '/gallery.*'
  filter :erb
end

The images themselves will be copied as-is. To do so, add the following to the Rules file, at the top:

passthrough '/gallery/*'

At this point, the image gallery is functioning, but does not yet include thumbnails.

Generating thumbnails

This gallery page will be enhanced so that it displays a list of thumbnails of these images, rather than the paths to the images.

To generate the image thumbnails, a custom filter will be necessary. Depending on what OS you are on, and what software you have installed, you may need to use different filters. On macOS, you can use sips, so place this in lib/filters/thumbnailize.rb:

class Thumbnailize < Nanoc::Filter
  identifier :thumbnailize
  type       :binary

  def run(filename, params = {})
    system(
      'sips',
      '--resampleWidth',
      params[:width].to_s,
      '--out',
      output_filename,
      filename
    )
  end
end

On platforms that have convert, which is part of ImageMagick and GraphicsMagick, you can use the following filter instead:

class Thumbnailize < Nanoc::Filter
  identifier :thumbnailize
  type       :binary

  def run(filename, params = {})
    system(
      'convert',
      '-resize',
      params[:width].to_s,
      filename,
      output_filename
    )
  end
end

To generate the actual thumbnails, the images will need a :thumbnail representation, and accompanying compilation/routing rules:

compile '/gallery/*', rep: :thumbnail do
  filter :thumbnailize, width: 200
end

route '/gallery/*', rep: :thumbnail do
  item.identifier.without_ext + '-thumbnail.' + item.identifier.ext
end

When the site is compiled now, you’ll find both output/gallery/some_image.jpg as well as output/gallery/some_image-thumbnail.jpg, corresponding to the full-size image and its thumbnail. The gallery page can now be updated so that it displays the thumbnails:

<ul>
<% @items.find_all('/gallery/*').each do |img| %>
  <li>
    <a href="<%= img.path %>">
      <img src="<%= img.path(rep: :thumbnail) %>">
    </a>
  </li>
<% end %>
</ul>

If you want to give each thumbnail a bit of ALT text, you can do so by treating the ALT text as metadata that you want to assign to that item. To do so, create a metadata file for the item you want to give the ALT text; this file will have the same name as the image file itself, but a different extension (.yaml). For example, an image at content/gallery/rick.jpg would have a metadata file named content/gallery/rick.yaml. Inside the newly created YAML file, add the ALT text, like this:

alt: "A picture of a kitten that looks cute but is actually quite evil"

Writing the ALT text on the gallery page can now be done using the img[:alt] text, like this:

<ul>
<% @items.find_all('/gallery/*').each do |img| %>
  <li>
    <a href="<%= img.path %>">
      <img src="<%= img.path(rep: thumbnail) %>" alt="<%= img[:alt] %>">
    </a>
  </li>
<% end %>
</ul>

And done! All that’s left at this point is styling the page.