Class: Nanoc::Core::Filter Abstract

Inherits:
Context
  • Object
show all
Extended by:
DDPlugin::Plugin
Includes:
ContractsSupport
Defined in:
lib/nanoc/core/filter.rb

Overview

This class is abstract.

Subclass and override #run to implement a custom filter.

Nanoc::Core::Filter is responsible for filtering items. It is the superclass for all textual filters.

A filter instance should only be used once. Filters should not be reused since they store state.

When creating a filter with a hash containing assigned variables, those variables will be made available in the ‘@assigns` instance variable and the #assigns method. The assigns itself will also be available as instance variables and instance methods.

Examples:

Accessing assigns in different ways


filter = SomeFilter.new({ :foo => 'bar' })
filter.instance_eval { @assigns[:foo] }
  # => 'bar'
filter.instance_eval { assigns[:foo] }
  # => 'bar'
filter.instance_eval { @foo }
  # => 'bar'
filter.instance_eval { foo }
  # => 'bar'

Defined Under Namespace

Classes: FilterReturnedNilError, OutputNotWrittenError, UnknownFilterError

Constant Summary collapse

TMP_BINARY_ITEMS_DIR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'binary_items'

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ContractsSupport

enabled?, included, setup_once, warn_about_performance

Methods inherited from Context

#get_binding, #include, #method_missing, #respond_to_missing?

Constructor Details

#initialize(hash = {}) ⇒ Filter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates a new filter that has access to the given assigns.

Parameters:

  • hash (Hash) (defaults to: {})

    A hash containing variables that should be made available during filtering.



175
176
177
178
# File 'lib/nanoc/core/filter.rb', line 175

def initialize(hash = {})
  @assigns = hash
  super
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Nanoc::Core::Context

Class Method Details

.always_outdatedvoid

This method returns an undefined value.

Marks this filter as always causing the item rep to be outdated. This is useful for filters that cannot do dependency tracking properly.



137
138
139
# File 'lib/nanoc/core/filter.rb', line 137

def always_outdated
  @always_outdated = true
end

.always_outdated?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


129
130
131
# File 'lib/nanoc/core/filter.rb', line 129

def always_outdated?
  @always_outdated || false
end

.define(ident, &block) ⇒ Object



65
66
67
68
69
70
# File 'lib/nanoc/core/filter.rb', line 65

def define(ident, &block)
  filter_class = Class.new(::Nanoc::Core::Filter) { identifier(ident) }
  filter_class.send(:define_method, :run) do |content, params = {}|
    instance_exec(content, params, &block)
  end
end

.from_binary?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns True if this filter can be applied to binary item representations, false otherwise.

Returns:

  • (Boolean)

    True if this filter can be applied to binary item representations, false otherwise



109
110
111
# File 'lib/nanoc/core/filter.rb', line 109

def from_binary?
  (@from || :text) == :binary
end

.named!(name) ⇒ Object

Raises:



72
73
74
75
76
77
# File 'lib/nanoc/core/filter.rb', line 72

def named!(name)
  klass = named(name)
  raise UnknownFilterError.new(name) if klass.nil?

  klass
end

.requires(*requires) ⇒ void .requiresEnumerable<String>

Overloads:

  • .requires(*requires) ⇒ void

    This method returns an undefined value.

    Sets the required libraries for this filter.

    Parameters:

    • requires (Array<String>)

      A list of library names that are required

  • .requiresEnumerable<String>

    Returns the required libraries for this filter.

    Returns:

    • (Enumerable<String>)

      This filter’s list of library names that are required



148
149
150
151
152
153
154
# File 'lib/nanoc/core/filter.rb', line 148

def requires(*requires)
  if requires.any?
    @requires = requires
  else
    @requires || []
  end
end

.setupvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Requires the filter’s required library if necessary.



161
162
163
164
165
166
# File 'lib/nanoc/core/filter.rb', line 161

def setup
  @setup ||= begin
    requires.each { |r| require r }
    true
  end
end

.to_binary?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns True if this filter results in a binary item representation, false otherwise.

Returns:

  • (Boolean)

    True if this filter results in a binary item representation, false otherwise



117
118
119
# File 'lib/nanoc/core/filter.rb', line 117

def to_binary?
  (@to || :text) == :binary
end

.to_text?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


122
123
124
# File 'lib/nanoc/core/filter.rb', line 122

def to_text?
  (@to || :text) == :text
end

.type(arg) ⇒ void

This method returns an undefined value.

Sets the new type for the filter. The type can be ‘:binary` (default) or `:text`. The given argument can either be a symbol indicating both “from” and “to” types, or a hash where the only key is the “from” type and the only value is the “to” type.

Examples:

Specifying a text-to-text filter


type :text

Specifying a text-to-binary filter


type :text => :binary

Parameters:

  • arg (Symbol, Hash)

    The new type of this filter



95
96
97
98
99
100
101
102
103
# File 'lib/nanoc/core/filter.rb', line 95

def type(arg)
  if arg.is_a?(Hash)
    @from = arg.keys[0]
    @to = arg.values[0]
  else
    @from = arg
    @to = arg
  end
end

Instance Method Details

#depend_on(items) ⇒ void

This method returns an undefined value.

Creates a dependency from the item that is currently being filtered onto the given collection of items. In other words, require the given items to be compiled first before this items is processed.



263
264
265
266
# File 'lib/nanoc/core/filter.rb', line 263

def depend_on(items)
  items.flat_map(&:reps).flat_map(&:raw_path)
  items.each(&:raw_filename)
end

#filenameString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the filename associated with the item that is being filtered.

It is in the format `item <identifier> (rep <name>)`.

Returns:



242
243
244
245
246
247
248
249
250
# File 'lib/nanoc/core/filter.rb', line 242

def filename
  if @layout
    "layout #{@layout.identifier}"
  elsif @item
    "item #{@item.identifier} (rep #{@item_rep.name})"
  else
    '?'
  end
end

#on_main_fiber(&block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



253
254
255
# File 'lib/nanoc/core/filter.rb', line 253

def on_main_fiber(&block)
  Fiber.yield(block)
end

#output_filenameString

Returns a filename that is used to write data to. This method is only

used on binary items. When running a binary filter on a file, the
resulting file must end up in the location returned by this method.

The returned filename will be absolute, so it is safe to change to

another directory inside the filter.

Returns:

  • (String)

    The output filename



230
231
232
233
# File 'lib/nanoc/core/filter.rb', line 230

def output_filename
  @output_filename ||=
    Nanoc::Core::TempFilenameFactory.instance.create(TMP_BINARY_ITEMS_DIR)
end

#run(content_or_filename, params = {}) ⇒ String, void

This method is abstract.

Runs the filter on the given content or filename.

Parameters:

  • content_or_filename (String)

    The unprocessed content that should be filtered (if the item is a textual item) or the path to the file that should be filtered (if the item is a binary item)

  • params (Hash) (defaults to: {})

    A hash containing parameters. Filter subclasses can use these parameters to allow modifying the filter’s behaviour.

Returns:

  • (String, void)

    If the filter output binary content, the return value is undefined; if the filter outputs textual content, the return value will be the filtered content.

Raises:

  • (NotImplementedError)


205
206
207
# File 'lib/nanoc/core/filter.rb', line 205

def run(content_or_filename, params = {}) # rubocop:disable Lint/UnusedMethodArgument
  raise NotImplementedError.new('Nanoc::Core::Filter subclasses must implement #run')
end

#setup_and_run(*args) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Sets up the filter and runs the filter. This method passes its arguments to #run unchanged and returns the return value from #run.

See Also:



186
187
188
189
# File 'lib/nanoc/core/filter.rb', line 186

def setup_and_run(*args)
  self.class.setup
  run(*args).tap { |res| verify(res) }
end

#verify(res) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
# File 'lib/nanoc/core/filter.rb', line 209

def verify(res)
  if self.class.to_binary?
    unless File.file?(output_filename)
      raise Nanoc::Core::Filter::OutputNotWrittenError.new(self.class.identifier, output_filename)
    end
  elsif self.class.to_text?
    unless res
      raise Nanoc::Core::Filter::FilterReturnedNilError.new(self.class.identifier)
    end
  end
end