Much nicer Redcloth and Bluecloth filter structure, both code and tests. Many implementation ideas thanks to Mislav Marohnic, ugly test output pointed out by Jan Szumiec.

git-svn-id: svn://hamptoncatlin.com/haml/trunk@581 7063305b-7217-0410-af8c-cdc13e5119b9
This commit is contained in:
nex3 2007-08-11 21:04:51 +00:00
parent e55be25534
commit 1c96889cef
4 changed files with 112 additions and 86 deletions

View File

@ -120,19 +120,11 @@ module Haml
:filters => {
'sass' => Sass::Engine,
'plain' => Haml::Filters::Plain,
'preserve' => Haml::Filters::Preserve }
}
if !NOT_LOADED.include? 'redcloth'
@options[:filters].merge!({
'redcloth' => RedCloth,
'preserve' => Haml::Filters::Preserve,
'redcloth' => Haml::Filters::RedCloth,
'textile' => Haml::Filters::Textile,
'markdown' => Haml::Filters::Markdown
})
end
if !NOT_LOADED.include? 'bluecloth'
@options[:filters]['markdown'] = Haml::Filters::Markdown
end
'markdown' => Haml::Filters::Markdown }
}
@options.rec_merge! l_options

View File

@ -7,22 +7,12 @@ require 'erb'
require 'sass/engine'
require 'stringio'
volatile_requires = ['rubygems', 'redcloth', 'bluecloth']
NOT_LOADED = [] unless defined?(NOT_LOADED)
volatile_requires.each do |file|
begin
require file
rescue LoadError
NOT_LOADED.push file
end
end
begin
require 'rubygems'
rescue LoadError; end
class ERB; alias_method :render, :result; end
unless NOT_LOADED.include? 'bluecloth'
class BlueCloth; alias_method :render, :to_html; end
end
module Haml
module Filters
class Plain
@ -60,26 +50,66 @@ module Haml
end
end
unless NOT_LOADED.include? 'bluecloth'
Markdown = BlueCloth unless defined?(Markdown)
class LazyLoaded
def initialize(*reqs)
reqs[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 = reqs[-1]
require @required
rescue LoadError => e
classname = self.class.to_s.gsub(/\w+::/, '')
if reqs.size == 1
raise HamlError.new("Can't run #{classname} filter; required file '#{reqs.first}' not found")
else
raise HamlError.new("Can't run #{classname} filter; required #{reqs.map { |r| "'#{r}'" }.join(' or ')}, but none were found")
end
end
end
end
unless NOT_LOADED.include? 'redcloth'
class ::RedCloth; alias_method :render, :to_html; end
class RedCloth < LazyLoaded
def initialize(text)
super('redcloth')
@engine = ::RedCloth.new(text)
end
# Uses RedCloth to provide only Textile (not Markdown) parsing
class Textile < RedCloth
def render
self.to_html(:textile)
def render
@engine.to_html
end
end
# Uses RedCloth to provide only Textile (not Markdown) parsing
class Textile < RedCloth
def render
@engine.to_html(:textile)
end
end
# Uses BlueCloth or RedCloth to provide only Markdown (not Textile) parsing
class Markdown < LazyLoaded
def initialize(text)
super('bluecloth', 'redcloth')
if @required == 'bluecloth'
@engine = ::BlueCloth.new(text)
else
@engine = ::RedCloth.new(text)
end
end
unless defined?(Markdown)
# Uses RedCloth to provide only Markdown (not Textile) parsing
class Markdown < RedCloth
def render
self.to_html(:markdown)
end
def render
if @engine.is_a?(::BlueCloth)
@engine.to_html
else
@engine.to_html(:markdown)
end
end
end

View File

@ -194,60 +194,41 @@ class EngineTest < Test::Unit::TestCase
end
def test_no_bluecloth
old_markdown = false
if defined?(Haml::Filters::Markdown)
old_markdown = Haml::Filters::Markdown
end
Kernel.module_eval do
alias_method :haml_old_require, :gem_original_require
def gem_original_require(file)
def gem_original_require_with_bluecloth(file)
raise LoadError if file == 'bluecloth'
haml_old_require(file)
gem_original_require_without_bluecloth(file)
end
alias_method :gem_original_require_without_bluecloth, :gem_original_require
alias_method :gem_original_require, :gem_original_require_with_bluecloth
end
begin
assert_equal("<h1>Foo</h1>\t<p>- a\n- b</p>\n",
Haml::Engine.new(":markdown\n Foo\n ===\n - a\n - b").to_html)
rescue Haml::HamlError => e
if e.message == "Can't run Markdown filter; required 'bluecloth' or 'redcloth', but none were found"
puts "\nCouldn't require 'bluecloth' or 'redcloth'; skipping a test."
else
raise e
end
end
if old_markdown
Haml::Filters.instance_eval do
remove_const 'Markdown'
end
end
# This is purposefully redundant, so it doesn't stop
# haml/filters from being required later on.
require 'haml/../haml/filters'
assert_equal("<h1>Foo</h1>\t<p>- a\n- b</p>\n",
Haml::Engine.new(":markdown\n Foo\n ===\n - a\n - b").to_html)
Haml::Filters.instance_eval do
remove_const 'Markdown'
end
Haml::Filters.const_set('Markdown', old_markdown) if old_markdown
Kernel.module_eval do
alias_method :gem_original_require, :haml_old_require
alias_method :gem_original_require, :gem_original_require_without_bluecloth
end
NOT_LOADED.delete 'bluecloth'
end
def test_no_redcloth
Kernel.module_eval do
alias_method :haml_old_require2, :gem_original_require
def gem_original_require(file)
def gem_original_require_with_redcloth(file)
raise LoadError if file == 'redcloth'
haml_old_require2(file)
gem_original_require_without_redcloth(file)
end
alias_method :gem_original_require_without_redcloth, :gem_original_require
alias_method :gem_original_require, :gem_original_require_with_redcloth
end
# This is purposefully redundant, so it doesn't stop
# haml/filters from being required later on.
require 'haml/../haml/../haml/filters'
begin
Haml::Engine.new(":redcloth\n _foo_").to_html
rescue Haml::HamlError
@ -256,10 +237,30 @@ class EngineTest < Test::Unit::TestCase
end
Kernel.module_eval do
alias_method :gem_original_require2, :haml_old_require
alias_method :gem_original_require, :gem_original_require_without_redcloth
end
end
def test_no_redcloth_or_bluecloth
Kernel.module_eval do
def gem_original_require_with_redcloth_and_bluecloth(file)
raise LoadError if file == 'redcloth' || file == 'bluecloth'
gem_original_require_without_redcloth_and_bluecloth(file)
end
alias_method :gem_original_require_without_redcloth_and_bluecloth, :gem_original_require
alias_method :gem_original_require, :gem_original_require_with_redcloth_and_bluecloth
end
NOT_LOADED.delete 'redcloth'
begin
Haml::Engine.new(":markdown\n _foo_").to_html
rescue Haml::HamlError
else
assert(false, "No exception raised!")
end
Kernel.module_eval do
alias_method :gem_original_require, :gem_original_require_without_redcloth_and_bluecloth
end
end
def test_local_assigns_dont_modify_class

View File

@ -49,11 +49,14 @@ class TemplateTest < Test::Unit::TestCase
assert_equal(pair.first, pair.last, message)
end
end
test.call(@base.render(name))
# If eval's suppressed, the partial won't render anyway :p.
unless Haml::Template.options[:suppress_eval]
test.call(@base.render(:file => "partialize", :locals => { :name => name }))
begin
test.call(@base.render(name))
rescue ActionView::TemplateError => e
if e.message =~ /Can't run [\w:]+ filter; required (one of|file) ((?:'\w+'(?: or )?)+)(, but none were found| not found)/
puts "\nCouldn't require #{$2}; skipping a test."
else
raise e
end
end
end