2007-01-19 17:03:47 +00:00
|
|
|
# This file contains redefinitions of and wrappers around various text
|
|
|
|
# filters so they can be used as Haml filters.
|
|
|
|
|
|
|
|
module Haml
|
2008-02-22 23:27:35 -08:00
|
|
|
# The module containing the default filters,
|
|
|
|
# as well as the base module,
|
|
|
|
# Haml::Filters::Base.
|
2007-01-19 17:03:47 +00:00
|
|
|
module Filters
|
2008-02-22 23:27:35 -08:00
|
|
|
# The base module for Haml filters.
|
|
|
|
# User-defined filters should be modules including this module.
|
|
|
|
#
|
|
|
|
# A user-defined filter should override either Base#render or Base #compile.
|
|
|
|
# Base#render is the most common.
|
|
|
|
# It takes a string, the filter source,
|
|
|
|
# and returns another string,
|
|
|
|
# the result of the filter.
|
|
|
|
# For example:
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
2008-02-22 23:03:25 -08:00
|
|
|
module Base
|
2008-02-22 23:27:35 -08:00
|
|
|
def self.included(base) # :nodoc:
|
2008-02-22 23:03:25 -08:00
|
|
|
base.extend(base)
|
2007-01-19 17:03:47 +00:00
|
|
|
end
|
|
|
|
|
2008-02-22 23:27:35 -08:00
|
|
|
# Takes a string, the source text that should be passed to the filter,
|
|
|
|
# and returns the string resulting from running the filter on <tt>text</tt>.
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
def render(text)
|
2008-04-19 10:07:40 -07:00
|
|
|
raise Error.new("#{self.inspect}#render not defined!")
|
2008-02-22 23:27:35 -08:00
|
|
|
end
|
|
|
|
|
2008-02-23 01:13:36 -08:00
|
|
|
def internal_compile(*args) # :nodoc:
|
|
|
|
resolve_lazy_requires
|
|
|
|
compile(*args)
|
|
|
|
end
|
|
|
|
|
2008-02-22 23:27:35 -08:00
|
|
|
# compile 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 Haml::Precompiler instance to compile the string to Ruby code
|
|
|
|
# that will be executed in the context of the active Haml template.
|
|
|
|
#
|
|
|
|
# Warning: the Haml::Precompiler 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.
|
2008-02-22 23:03:25 -08:00
|
|
|
def compile(precompiler, text)
|
|
|
|
resolve_lazy_requires
|
|
|
|
filter = self
|
|
|
|
precompiler.instance_eval do
|
|
|
|
if contains_interpolation?(text)
|
|
|
|
return if options[:suppress_eval]
|
2007-01-19 17:03:47 +00:00
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
push_script("#{filter.inspect}.render(#{unescape_interpolation(text)})", false)
|
|
|
|
return
|
|
|
|
end
|
2007-01-19 17:03:47 +00:00
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
rendered = filter.render(text)
|
2007-01-19 17:03:47 +00:00
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
if !options[:ugly]
|
|
|
|
push_text(rendered.rstrip.gsub("\n", "\n#{' ' * @output_tabs}"))
|
|
|
|
else
|
|
|
|
push_text(rendered.rstrip)
|
|
|
|
end
|
|
|
|
end
|
2007-02-06 08:08:32 +00:00
|
|
|
end
|
|
|
|
|
2008-02-22 23:27:35 -08:00
|
|
|
# This becomes a class method of modules that include Base.
|
|
|
|
# It allows the module to specify one or more Ruby files
|
|
|
|
# that Haml should try to require when compiling the filter.
|
|
|
|
#
|
|
|
|
# The first file specified is tried first,
|
|
|
|
# then the second, etc.
|
|
|
|
# If none are found, the compilation throws an exception.
|
|
|
|
#
|
|
|
|
# For example:
|
|
|
|
#
|
|
|
|
# module Haml::Filters::Markdown
|
|
|
|
# lazy_require 'bluecloth', 'redcloth'
|
|
|
|
#
|
|
|
|
# ...
|
|
|
|
# end
|
2008-04-07 23:09:17 -07:00
|
|
|
#
|
2008-02-22 23:03:25 -08:00
|
|
|
def lazy_require(*reqs)
|
|
|
|
@lazy_requires = reqs
|
2007-02-06 08:08:32 +00:00
|
|
|
end
|
|
|
|
|
2008-02-22 23:27:35 -08:00
|
|
|
private
|
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
def resolve_lazy_requires
|
|
|
|
return unless @lazy_requires
|
|
|
|
|
|
|
|
@lazy_requires[0...-1].each do |req|
|
2007-08-11 21:04:51 +00:00
|
|
|
begin
|
|
|
|
@required = req
|
|
|
|
require @required
|
|
|
|
return
|
|
|
|
rescue LoadError; end # RCov doesn't see this, but it is run
|
|
|
|
end
|
2008-04-07 23:09:17 -07:00
|
|
|
|
2007-08-11 21:04:51 +00:00
|
|
|
begin
|
2008-02-22 23:03:25 -08:00
|
|
|
@required = @lazy_requires[-1]
|
2007-08-11 21:04:51 +00:00
|
|
|
require @required
|
|
|
|
rescue LoadError => e
|
|
|
|
classname = self.class.to_s.gsub(/\w+::/, '')
|
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
if @lazy_requires.size == 1
|
2008-04-19 10:07:40 -07:00
|
|
|
raise Error.new("Can't run #{classname} filter; required file '#{@lazy_requires.first}' not found")
|
2007-08-11 21:04:51 +00:00
|
|
|
else
|
2008-04-19 10:07:40 -07:00
|
|
|
raise Error.new("Can't run #{classname} filter; required #{@lazy_requires.map { |r| "'#{r}'" }.join(' or ')}, but none were found")
|
2007-08-11 21:04:51 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2007-01-31 06:38:23 +00:00
|
|
|
end
|
2008-02-22 23:27:35 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# :stopdoc:
|
2008-02-22 23:03:25 -08:00
|
|
|
|
2008-02-22 23:27:35 -08:00
|
|
|
begin
|
|
|
|
require 'rubygems'
|
|
|
|
rescue LoadError; end
|
|
|
|
|
|
|
|
module Haml
|
|
|
|
module Filters
|
2008-02-22 23:03:25 -08:00
|
|
|
module Plain
|
|
|
|
include Base
|
|
|
|
|
|
|
|
def render(text); text; end
|
|
|
|
end
|
|
|
|
|
2008-02-23 01:56:16 -08:00
|
|
|
module Javascript
|
|
|
|
include Base
|
|
|
|
|
|
|
|
def render(text)
|
|
|
|
<<END
|
|
|
|
<script type='text/javascript'>
|
|
|
|
//<![CDATA[
|
|
|
|
#{text.rstrip.gsub("\n", "\n ")}
|
|
|
|
//]]>
|
|
|
|
</script>
|
|
|
|
END
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
module Ruby
|
|
|
|
include Base
|
|
|
|
lazy_require 'stringio'
|
|
|
|
|
2008-02-23 01:24:33 -08:00
|
|
|
def compile(precompiler, text)
|
|
|
|
precompiler.instance_eval do
|
|
|
|
push_silent <<-END.gsub("\n", ';')
|
|
|
|
_haml_old_stdout = $stdout
|
|
|
|
$stdout = StringIO.new(_hamlout.buffer, 'a')
|
|
|
|
#{text}
|
|
|
|
_haml_old_stdout, $stdout = $stdout, _haml_old_stdout
|
|
|
|
_haml_old_stdout.close
|
|
|
|
END
|
|
|
|
end
|
2008-02-22 23:03:25 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module Preserve
|
|
|
|
include Base
|
|
|
|
|
|
|
|
def compile(precompiler, text)
|
|
|
|
text = Haml::Helpers.preserve(text) + "\n"
|
|
|
|
|
|
|
|
precompiler.instance_eval do
|
|
|
|
if contains_interpolation?(text)
|
|
|
|
return if options[:suppress_eval]
|
|
|
|
|
|
|
|
push_silent("_hamlout.buffer << #{unescape_interpolation(text)};")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
concat_merged_text(text)
|
|
|
|
end
|
2007-08-11 21:04:51 +00:00
|
|
|
end
|
2008-02-22 23:03:25 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
module Sass
|
|
|
|
include Base
|
|
|
|
lazy_require 'sass/engine'
|
2007-01-31 06:38:23 +00:00
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
def render(text)
|
|
|
|
::Sass::Engine.new(text).render
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
module ERB
|
|
|
|
include Base
|
|
|
|
lazy_require 'erb'
|
|
|
|
|
2008-02-23 01:37:35 -08:00
|
|
|
def compile(precompiler, text)
|
|
|
|
src = ::ERB.new(text).src.sub(/^_erbout = '';/, "").gsub("\n", ';')
|
|
|
|
precompiler.send(:push_silent, src)
|
2008-02-22 23:03:25 -08:00
|
|
|
end
|
|
|
|
end
|
2008-04-07 23:09:17 -07:00
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
module RedCloth
|
|
|
|
include Base
|
|
|
|
lazy_require 'redcloth'
|
|
|
|
|
|
|
|
def render(text)
|
|
|
|
::RedCloth.new(text).to_html
|
2007-08-11 21:04:51 +00:00
|
|
|
end
|
|
|
|
end
|
2008-04-07 23:09:17 -07:00
|
|
|
|
2007-08-11 21:04:51 +00:00
|
|
|
# Uses RedCloth to provide only Textile (not Markdown) parsing
|
2008-02-22 23:03:25 -08:00
|
|
|
module Textile
|
|
|
|
include Base
|
|
|
|
lazy_require 'redcloth'
|
|
|
|
|
|
|
|
def render(text)
|
|
|
|
::RedCloth.new(text).to_html(:textile)
|
2007-08-11 21:04:51 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Uses BlueCloth or RedCloth to provide only Markdown (not Textile) parsing
|
2008-02-22 23:03:25 -08:00
|
|
|
module Markdown
|
|
|
|
include Base
|
|
|
|
lazy_require 'bluecloth', 'redcloth'
|
2007-08-11 21:04:51 +00:00
|
|
|
|
2008-02-22 23:03:25 -08:00
|
|
|
def render(text)
|
2007-08-11 21:04:51 +00:00
|
|
|
if @required == 'bluecloth'
|
2008-02-22 23:03:25 -08:00
|
|
|
::BlueCloth.new(text).to_html
|
2007-08-11 21:04:51 +00:00
|
|
|
else
|
2008-02-22 23:03:25 -08:00
|
|
|
::RedCloth.new(text).to_html(:markdown)
|
2007-01-19 17:03:47 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# :startdoc:
|