Filters
Filters are used for transforming an item’s content.
One commonly used filter is :erb
, which interprets the item’s content as text with embedded Ruby. Another commonly used filter is :kramdown
, which takes Markdown as its input and produces an HTML fragment.
Filters can be applied to both textual and binary items. An example of a binary filter is an image thumbnail filter. Filters can also convert textual content into binary files and vice versa; text-to-speech filters and OCR filters are therefore possible (but perhaps not very useful).
Filters are called within compilation rules. Here is an example rule that applies the :kramdown
filter with the :auto_ids
option set to false:
compile '/**/*.md' do
filter :kramdown, auto_ids: false
layout '/default.*'
end
For details on compilation rules, see the Rules page.
Nanoc comes with a handful of filters. See the Filters page for a list of filters bundled with Nanoc.
Writing filters
Filters are classes that inherit from Nanoc::Filter
. Writing custom filters is done by subclassing this class and overriding the run()
method, which is responsible for transforming the content.
Here is an example (textual) filter that replaces any occurrences of “Nanoc sucks” by “Nanoc rocks”:
class CensorFilter < Nanoc::Filter
identifier :censor
def run(content, params = {})
content.gsub('Nanoc sucks', 'Nanoc rocks')
end
end
Alternatively, there is a shorthand using Nanoc::Filter.define
:
Nanoc::Filter.define(:censor) do |content, params|
content.gsub('Nanoc sucks', 'Nanoc rocks')
end
Each filter needs an identifier, so that it can be used in a call to filter()
in a compilation rule. A filter identifier is set using identifier()
. In the example above, the identifier is set to :censor
.
The content
argument to the run()
method is a string that contains the content to be transformed. The params
argument is taken from the filter()
call in the compilation rule.
Filters that output textual content should return the filtered content at the end of the method.
Filters have access to @item
, @item_rep
, @items
, @layouts
, and @config
. For details, see the Variables page.
Binary filters
A filter is marked as a binary filter using the type()
method. For example:
class SampleBinaryFilter < Nanoc::Filter
identifier :sample_binary
type :binary
# (other code here)
end
The run()
method for binary filters takes a filename
argument, rather than a content
argument. This filename
argument contains the path to the file to be filtered. For example:
class SampleBinaryFilter < Nanoc::Filter
identifier :sample_binary
type :binary
def run(filename, params = {})
# (filter code here)
end
end
Filters that output binary content should not return content, but rather write it to the location returned by the output_filename()
method.
When writing filters that apply to binary data, make sure that you check the exit code and any errors generated by the sub-process that you are invoking (if any). If the sub-process exits with an error, you should raise an error in the filter.
Here is an example of a filter that resizes images to a given width:
class ResizeFilter < Nanoc::Filter
identifier :resize
type :binary
def run(filename, params = {})
system(
'sips',
'--resampleWidth', params[:width],
'--out', output_filename,
filename
)
end
end
Text-to-binary and binary-to-text filters
Filters that convert textual content to binary content or vice versa have the type declaration type :text => :binary
or type :binary => :text
, respectively. For example:
class SampleTextualToBinaryFilter < Nanoc::Filter
identifier :sample_textual_to_binary
type :text => :binary
# (other code here)
end
A text-to-binary filter will receive a content
string as its first argument, and should write the generated binary content to output_filename()
. A binary-to-text filter will receive a filename
string argument, and should return the filtered content.
Here is an example of an audio synthesis filter:
class SynthesiseAudio < Nanoc::Filter
identifier :synthesize_audio
type :text => :binary
def run(content, params = {})
system('say', content, '-o', output_filename)
end
end