nanoc / features

Collection of feature requests
2 stars 1 forks source link

Multiple filters support for layouts. #62

Open 0x1eef opened 2 years ago

0x1eef commented 2 years ago

Hello !

I would like to first say, thank you for all your work on nanoc. I love it ! This issue is a feature request (maybe it's already possible, but I couldn't figure out how).

I would like to apply multiple filters to a layout - at the moment I could only figure out how to apply one filter (eg erb). The reason is that I would like to run the erb filter, followed by a custom filter that minifies the result of the erb filter.

The solution I came up with is this - but it is less than ideal because it implies using erb all the time, and I didn't see an easy way to avoid that.

Gist:

# lib/filters/minify_filter.rb
class MinifyFilter < Nanoc::Filters::ERB
  identifier :minify_erb
  type :text

  def run(content, params={})
    content = super(content, params)
    file = tmp_write(content)
    run_minify(file.path)
    File.read(file.path).tap { file.tap(&:unlink).close }
  end

  private

  def run_minify(path)
    system "minify", path, "--type", "html", "-o", path
  end

  def content_dir
    source = config[:data_sources].find { _1[:type] == "filesystem" }
    source[:content_dir] || File.join(Dir.getwd, "content")
  end

  def tmp_write(content)
    file = Tempfile.new('minify')
    file.write(content)
    file.tap(&:flush)
  end
end

# Rules
layout '**/*', :minify_erb
denisdefreyne commented 2 years ago

Hey there,

At the moment, the easiest (though a little repetitive) way to do this is to call :minify after the layout:

compile '/**/*.md' do
  filter :kramdown
  layout '/default.*'
  filter :minify
end

layout '/**/*.erb', :erb

The filter :minify is called separately after the layout call. (A compilation rule evaluates its steps in order, one after another.)

If two filters always need to happen in succession, then it might be worth having a way to explicitly combine filters. Something like this:

Nanoc::Filter.combine([:erb, :minify] => :my_erb)

(You’d still need to define your own :minify filter in this example.)

0x1eef commented 2 years ago

If two filters always need to happen in succession, then it might be worth having a way to explicitly combine filters. Something like this:

Nanoc::Filter.combine([:erb, :minify] => :my_erb)

That seems nice !

This is what I had imagined:

layout '**/*', [:erb, :minify]

I could see this working too:

layout '**/*', Nanoc::Filter.combine([:erb, :minify])

My only suggestion would be to not make a name of the combined filters required. I think it can be redundant (like in the examples above), and introduce a new filter name that is kind of strange (like :my_erb).

Thanks!

0x1eef commented 2 months ago

Hey :wave: I'm cleaning up my issue list. Not clear if this one is actionable or not. Please feel free to close if it is taking up space among legitimate issues.