module Haml::Filters::Base

def self.included(base) # :nodoc:

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

def compile(precompiler, text)

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

that will be executed in the context of the active Haml template.
compile uses the Haml::Precompiler instance to compile the string to Ruby code
Rather than applying a filter to a string at compile-time,
to the Haml evaluation context.
compile should be overridden when a filter needs to have access
def compile(precompiler, text)
  resolve_lazy_requires
  filter = self
  precompiler.instance_eval do
    if contains_interpolation?(text)
      return if options[:suppress_eval]
      push_script(<<RUBY, false)
nd_preserve(#{filter.inspect}.render(#{unescape_interpolation(text)}))
      return
    end
    rendered = Haml::Helpers::find_and_preserve(filter.render(text), precompiler.options[:preserve])
    if !options[:ugly]
      push_text(rendered.rstrip.gsub("\n", "\n#{'  ' * @output_tabs}"))
    else
      push_text(rendered.rstrip)
    end
  end
end

def internal_compile(*args) # :nodoc:

:nodoc:
def internal_compile(*args) # :nodoc:
  resolve_lazy_requires
  compile(*args)
end

def lazy_require(*reqs)


end
...

lazy_require 'bluecloth', 'redcloth'
module Haml::Filters::Markdown

For example:

If none are found, the compilation throws an exception.
then the second, etc.
The first file specified is tried first,

that Haml should try to require when compiling the filter.
It allows the module to specify one or more Ruby files
This becomes a class method of modules that include Base.
def lazy_require(*reqs)
  @lazy_requires = reqs
end

def render(text)

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

and returns the string resulting from running the filter on text.
Takes a string, the source text that should be passed to the filter,
def render(text)
  raise Error.new("#{self.inspect}#render not defined!")
end

def resolve_lazy_requires

def resolve_lazy_requires
  return unless @lazy_requires
  @lazy_requires[0...-1].each do |req|
    begin
      @required = req
      require @required
      return
    rescue LoadError; end # RCov doesn't see this, but it is run
  end
  begin
    @required = @lazy_requires[-1]
    require @required
  rescue LoadError => e
    classname = self.class.to_s.gsub(/\w+::/, '')
    if @lazy_requires.size == 1
      raise Error.new("Can't run #{classname} filter; required file '#{@lazy_requires.first}' not found")
    else
      raise Error.new("Can't run #{classname} filter; required #{@lazy_requires.map { |r| "'#{r}'" }.join(' or ')}, but none were found")
    end
  end
end