# Module: Haml::Filters::Base

Included in:
  Cdata, Css, Escaped, Javascript, Plain, Preserve, Ruby

Defined in:
  lib/haml/filters.rb

## Overview

The base module for Haml filters. User-defined filters should be modules including this module. The name of the filter is taken by downcasing the module name. For instance, if the module is named `FooBar`, the filter will be `:foobar`.

A user-defined filter should override either #render or #compile. #render is the most common. It takes a string, the filter source, and returns another string, the result of the filter. For example, the following will define a filter named `:sass`:

    module Haml::Filters::Sass
      include Haml::Filters::Base

      def render(text)
        ::Sass::Engine.new(text).render
      end
    end

For details on overriding #compile, see its documentation.

Note that filters overriding #render automatically support `#{}` for interpolating Ruby code. Those overriding #compile will need to add such support manually if it’s desired.

## Class Method Summary collapse

- .included(base)

  This method is automatically called when Base is included in a module.

## Instance Method Summary collapse

- #compile(compiler, text)

  This should be overridden when a filter needs to have access to the Haml evaluation context.

- #internal_compile(*args)

  Same as #compile, but requires the necessary files first.

- #render(_text) ⇒ String

  Takes the source text that should be passed to the filter and returns the result of running the filter on that string.

- #render_with_options(text, _options) ⇒ String

  Same as #render, but takes a Engine options hash as well.

## Class Method Details

### .included(base)

This method is automatically called when Haml::Filters::Base is included in a module. It automatically defines a filter with the downcased name of that module. For example, if the module is named `FooBar`, the filter will be `:foobar`.

Parameters:

- base (`Module`, `Class`) —

  The module that this is included in

    108
    109
    110
    111

    # File 'lib/haml/filters.rb', line 108

    def self.included(base)
      Filters.defined[base.name.split("::").last.downcase] = base
      base.extend(base)
    end

## Instance Method Details

### #compile(compiler, text)

This should be overridden when a filter needs to have access to the Haml evaluation context. Rather than applying a filter to a string at compile-time, #compile uses the Compiler instance to compile the string to Ruby code that will be executed in the context of the active Haml template.

Warning: the Compiler interface is neither well-documented nor guaranteed to be stable. If you want to make use of it, you’ll probably need to look at the source code and should test your filter when upgrading to new Haml versions.

Parameters:

- compiler (`Haml::Compiler`) —

  The compiler instance

- text (`String`) —

  The text of the filter

Raises:

- (`Haml::Error`) —

  if none of #compile, #render, and #render_with_options are overridden

    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193

    # File 'lib/haml/filters.rb', line 162

    def compile(compiler, text)
      filter = self
      compiler.instance_eval do
        if contains_interpolation?(text)
          return if options[:suppress_eval]

          escape = options[:escape_filter_interpolations]
          # `escape_filter_interpolations` defaults to `escape_html` if unset.
          escape = options[:escape_html] if escape.nil?

          text = unescape_interpolation(text, escape).gsub(/(\\+)n/) do |s|
            escapes = $1.size
            next s if escapes % 2 == 0
            "#{'\\' * (escapes - 1)}\n"
          end
          # We need to add a newline at the beginning to get the
          # filter lines to line up (since the Haml filter contains
          # a line that doesn't show up in the source, namely the
          # filter name). Then we need to escape the trailing
          # newline so that the whole filter block doesn't take up
          # too many.
          text = %[\n#{text.sub(/\n"\Z/, "\\n\"")}]
          push_script <<RUBY.rstrip, :escape_html => false
    find_and_preserve(#{filter.inspect}.render_with_options(#{text}, _hamlout.options))
    RUBY
          return
        end

        rendered = Haml::Helpers::find_and_preserve(filter.render_with_options(text.to_s, compiler.options), compiler.options[:preserve])
        push_text("#{rendered.rstrip}\n")
      end
    end

### #internal_compile(*args)

Same as #compile, but requires the necessary files first. This is used by Engine and is not intended to be overridden or used elsewhere.

See Also:

- #compile

    142
    143
    144

    # File 'lib/haml/filters.rb', line 142

    def internal_compile(*args)
      compile(*args)
    end

### #render(_text) ⇒ `String`

Takes the source text that should be passed to the filter and returns the result of running the filter on that string.

This should be overridden in most individual filter modules to render text with the given filter. If #compile is overridden, however, #render doesn’t need to be.

Parameters:

- text (`String`) —

  The source text for the filter to process

Returns:

- (`String`) —

  The filtered result

Raises:

- (`Haml::Error`) —

  if it’s not overridden

    123
    124
    125

    # File 'lib/haml/filters.rb', line 123

    def render(_text)
      raise Error.new("#{self.inspect}#render not defined!")
    end

### #render_with_options(text, _options) ⇒ `String`

Same as #render, but takes a Engine options hash as well. It’s only safe to rely on options made available in Engine#options_for_buffer.

Parameters:

- text (`String`) —

  The source text for the filter to process

Returns:

- (`String`) —

  The filtered result

Raises:

- (`Haml::Error`) —

  if it or #render isn’t overridden

See Also:

- #render

    134
    135
    136

    # File 'lib/haml/filters.rb', line 134

    def render_with_options(text, _options)
      render(text)
    end