erector 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.txt +17 -3
- data/VERSION.yml +2 -2
- data/bin/erector +1 -1
- data/lib/erector.rb +22 -2
- data/lib/erector/after_initialize.rb +34 -0
- data/lib/erector/caching.rb +93 -0
- data/lib/erector/convenience.rb +58 -0
- data/lib/erector/dependencies.rb +24 -0
- data/lib/erector/dependency.rb +21 -0
- data/lib/erector/{erect.rb → erect/erect.rb} +14 -4
- data/lib/erector/{erected.rb → erect/erected.rb} +6 -4
- data/lib/erector/{indenting.rb → erect/indenting.rb} +0 -0
- data/lib/erector/{rhtml.treetop → erect/rhtml.treetop} +51 -11
- data/lib/erector/errors.rb +12 -0
- data/lib/erector/extensions/hash.rb +21 -0
- data/lib/erector/externals.rb +88 -24
- data/lib/erector/html.rb +352 -0
- data/lib/erector/inline.rb +5 -5
- data/lib/erector/jquery.rb +36 -0
- data/lib/erector/mixin.rb +3 -5
- data/lib/erector/needs.rb +94 -0
- data/lib/erector/output.rb +117 -0
- data/lib/erector/rails.rb +2 -2
- data/lib/erector/rails/extensions/action_controller.rb +5 -3
- data/lib/erector/rails/extensions/rails_helpers.rb +159 -0
- data/lib/erector/rails/extensions/rails_widget.rb +98 -56
- data/lib/erector/rails/rails_form_builder.rb +8 -4
- data/lib/erector/rails/rails_version.rb +2 -2
- data/lib/erector/rails/template_handlers/ert_handler.rb +1 -1
- data/lib/erector/rails/template_handlers/rb_handler.rb +42 -1
- data/lib/erector/raw_string.rb +2 -2
- data/lib/erector/sass.rb +22 -0
- data/lib/erector/widget.rb +100 -653
- data/lib/erector/widgets.rb +1 -0
- data/lib/erector/widgets/external_renderer.rb +51 -0
- data/lib/erector/widgets/page.rb +45 -63
- data/lib/erector/widgets/table.rb +9 -1
- data/spec/erect/erect_rails_spec.rb +19 -17
- data/spec/erect/erect_spec.rb +11 -1
- data/spec/erect/erected_spec.rb +76 -5
- data/spec/erect/rhtml_parser_spec.rb +11 -1
- data/spec/erector/caching_spec.rb +267 -0
- data/spec/erector/convenience_spec.rb +258 -0
- data/spec/erector/dependency_spec.rb +46 -0
- data/spec/erector/externals_spec.rb +233 -0
- data/spec/erector/html_spec.rb +508 -0
- data/spec/erector/indentation_spec.rb +84 -24
- data/spec/erector/inline_spec.rb +19 -8
- data/spec/erector/jquery_spec.rb +35 -0
- data/spec/erector/mixin_spec.rb +1 -1
- data/spec/erector/needs_spec.rb +120 -0
- data/spec/erector/output_spec.rb +199 -0
- data/spec/erector/sample-file.txt +1 -0
- data/spec/erector/sass_spec.rb +33 -0
- data/spec/erector/widget_spec.rb +113 -932
- data/spec/erector/widgets/field_table_spec.rb +6 -6
- data/spec/erector/widgets/form_spec.rb +3 -3
- data/spec/erector/widgets/page_spec.rb +52 -6
- data/spec/erector/widgets/table_spec.rb +4 -4
- data/spec/spec_helper.rb +70 -29
- metadata +56 -19
- data/lib/erector/rails/extensions/rails_widget/rails_helpers.rb +0 -137
- data/spec/core_spec_suite.rb +0 -3
- data/spec/erector/external_spec.rb +0 -110
- data/spec/rails_spec_suite.rb +0 -3
- data/spec/spec.opts +0 -1
- data/spec/spec_suite.rb +0 -40
data/lib/erector/widgets.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
class ExternalRenderer < Erector::Widget
|
2
|
+
needs :classes
|
3
|
+
needs :included_stylesheets => true, :inline_styles => true, :included_scripts => true, :inline_scripts => true
|
4
|
+
|
5
|
+
def content
|
6
|
+
included_stylesheets if @included_stylesheets
|
7
|
+
inline_styles if @inline_styles
|
8
|
+
included_scripts if @included_scripts
|
9
|
+
inline_scripts if @inline_scripts
|
10
|
+
end
|
11
|
+
|
12
|
+
def rendered_externals(type)
|
13
|
+
@classes.map do |klass|
|
14
|
+
klass.dependencies(type)
|
15
|
+
end.flatten.uniq
|
16
|
+
end
|
17
|
+
|
18
|
+
def included_scripts
|
19
|
+
rendered_externals(:js).each do |external|
|
20
|
+
script({:type => "text/javascript", :src => external.text}.merge(external.options))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def included_stylesheets
|
25
|
+
rendered_externals(:css).each do |external|
|
26
|
+
link({:rel => "stylesheet", :href => external.text, :type => "text/css", :media => "all"}.merge(external.options))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def inline_styles
|
31
|
+
rendered_externals(:style).each do |external|
|
32
|
+
style({:type => "text/css", 'xml:space' => 'preserve'}.merge(external.options)) do
|
33
|
+
rawtext external.text
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def inline_scripts
|
39
|
+
rendered_externals(:script).each do |external|
|
40
|
+
javascript external.options do
|
41
|
+
rawtext external.text
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# todo: allow :load or :ready per external script
|
45
|
+
rendered_externals(:jquery).each do |external|
|
46
|
+
jquery :load, external.text, external.options
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
data/lib/erector/widgets/page.rb
CHANGED
@@ -1,18 +1,24 @@
|
|
1
1
|
# Erector Page base class.
|
2
2
|
#
|
3
|
-
# Allows for accumulation of script and style tags (see example below) with
|
4
|
-
# external or inline content. External references are 'uniq'd, so it's
|
5
|
-
# a js script in all widgets that use it, so you don't
|
6
|
-
# the one widget that happened to
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# which
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
3
|
+
# Allows for accumulation of script and style tags (see example below) with
|
4
|
+
# either external or inline content. External references are 'uniq'd, so it's
|
5
|
+
# a good idea to declare a js script in all widgets that use it, so you don't
|
6
|
+
# accidentally lose the script if you remove the one widget that happened to
|
7
|
+
# declare it.
|
8
|
+
#
|
9
|
+
# The script and style declarations are accumulated at class load time, as
|
10
|
+
# 'dependencies'. This technique allows all widgets to add their own requirements
|
11
|
+
# to the page header without extra logic for declaring which pages include
|
12
|
+
# which nested widgets. Fortunately, Page is now smart enough to figure out
|
13
|
+
# which widgets were actually rendered during the body_content run, so it only
|
14
|
+
# emits into its HEAD the dependencies that are relevant. If it misses some, or
|
15
|
+
# if you want to add some extra dependencies -- for instance, styles that apply
|
16
|
+
# to widgets that are rendered later via AJAX -- then return an array of those
|
17
|
+
# widget classes in your subclass by overriding the #extra_widgets method.
|
18
|
+
#
|
19
|
+
# If you want something to show up in the headers for just one page type
|
20
|
+
# (subclass), then override #head_content, call super, and then emit it
|
21
|
+
# yourself.
|
16
22
|
#
|
17
23
|
# Body content can be supplied in several ways:
|
18
24
|
#
|
@@ -40,19 +46,20 @@
|
|
40
46
|
# text "body content"
|
41
47
|
# end
|
42
48
|
#
|
43
|
-
# This last trick (passing a block to Page.new) works because Page is an
|
44
|
-
# so its block is evaluated in the context of the newly
|
45
|
-
# and not in the context of its caller. But this
|
46
|
-
# of the caller, e.g.
|
47
|
-
#
|
49
|
+
# This last trick (passing a block to Page.new) works because Page is an
|
50
|
+
# InlineWidget so its block is evaluated in the context of the newly
|
51
|
+
# instantiated widget object, and not in the context of its caller. But this
|
52
|
+
# means you can't access instance variables of the caller, e.g.
|
53
|
+
#
|
48
54
|
# @name = "fred"
|
49
55
|
# Erector::Widgets::Page.new do
|
50
56
|
# text "my name is #{@name}"
|
51
57
|
# end
|
52
58
|
#
|
53
|
-
# will emit "my name is " because @name is nil inside the new Page. However,
|
54
|
-
# call methods in the parent class, thanks to some method_missing
|
55
|
-
# should be. See Erector::Inline#content for more
|
59
|
+
# will emit "my name is " because @name is nil inside the new Page. However,
|
60
|
+
# you *can* call methods in the parent class, thanks to some method_missing
|
61
|
+
# magic. Confused? You should be. See Erector::Inline#content for more
|
62
|
+
# documentation.
|
56
63
|
#
|
57
64
|
# Author:: Alex Chaffee, alex@stinky.com
|
58
65
|
#
|
@@ -63,21 +70,21 @@
|
|
63
70
|
# external :script, "$(document).ready(function(){...});"
|
64
71
|
# external :css, "stuff.css"
|
65
72
|
# external :style, "li.foo { color: red; }"
|
66
|
-
#
|
73
|
+
#
|
67
74
|
# def page_title
|
68
75
|
# "my app"
|
69
76
|
# end
|
70
|
-
#
|
77
|
+
#
|
71
78
|
# def body_content
|
72
79
|
# h1 "My App"
|
73
80
|
# p "welcome to my app"
|
74
81
|
# widget WidgetWithExternalStyle
|
75
82
|
# end
|
76
83
|
# end
|
77
|
-
#
|
84
|
+
#
|
78
85
|
# class WidgetWithExternalStyle < Erector::Widget
|
79
86
|
# external :style, "div.custom { border: 2px solid green; }"
|
80
|
-
#
|
87
|
+
#
|
81
88
|
# def content
|
82
89
|
# div :class => "custom" do
|
83
90
|
# text "green is good"
|
@@ -99,21 +106,24 @@ class Erector::Widgets::Page < Erector::InlineWidget
|
|
99
106
|
end
|
100
107
|
|
101
108
|
def content
|
109
|
+
extra_head_slot = nil
|
102
110
|
rawtext doctype
|
103
111
|
html(html_attributes) do
|
104
112
|
head do
|
105
113
|
head_content
|
114
|
+
extra_head_slot = output.placeholder
|
106
115
|
end
|
107
116
|
body(body_attributes) do
|
108
117
|
if block_given?
|
109
118
|
yield
|
110
|
-
elsif @block
|
111
|
-
super
|
112
119
|
else
|
113
120
|
body_content
|
114
121
|
end
|
115
122
|
end
|
116
123
|
end
|
124
|
+
# after everything's been rendered, use the placeholder to
|
125
|
+
# insert all the head's dependencies
|
126
|
+
extra_head_slot << included_head_content
|
117
127
|
end
|
118
128
|
|
119
129
|
# override me to provide a page title (default = name of the Page subclass)
|
@@ -133,51 +143,23 @@ class Erector::Widgets::Page < Erector::InlineWidget
|
|
133
143
|
|
134
144
|
# override me (or instantiate Page with a block)
|
135
145
|
def body_content
|
146
|
+
call_block
|
136
147
|
end
|
137
148
|
|
138
149
|
# emit the contents of the head element. Override and call super if you want to put more stuff in there.
|
139
150
|
def head_content
|
140
151
|
meta 'http-equiv' => 'content-type', :content => 'text/html;charset=UTF-8'
|
141
152
|
title page_title
|
142
|
-
|
143
|
-
included_stylesheets
|
144
|
-
inline_styles
|
145
|
-
|
146
|
-
included_scripts
|
147
|
-
inline_scripts
|
148
|
-
end
|
149
|
-
|
150
|
-
def included_scripts
|
151
|
-
self.class.externals(:js).each do |external|
|
152
|
-
script({:type => "text/javascript", :src => external.text}.merge(external.options))
|
153
|
-
end
|
154
153
|
end
|
155
154
|
|
156
|
-
def
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
def inline_styles
|
163
|
-
self.class.externals(:style).each do |external|
|
164
|
-
style({:type => "text/css", 'xml:space' => 'preserve'}.merge(external.options)) do
|
165
|
-
rawtext external.text
|
166
|
-
end
|
167
|
-
end
|
155
|
+
def included_head_content
|
156
|
+
# now that we've rendered the whole page, it's the right time
|
157
|
+
# to ask what all widgets were rendered to the output stream
|
158
|
+
included_widgets = [self.class] + output.widgets.to_a + extra_widgets
|
159
|
+
ExternalRenderer.new(:classes => included_widgets).to_html
|
168
160
|
end
|
169
161
|
|
170
|
-
def
|
171
|
-
|
172
|
-
javascript external.options do
|
173
|
-
rawtext external.text
|
174
|
-
end
|
175
|
-
end
|
176
|
-
self.class.externals(:jquery).each do |external|
|
177
|
-
javascript external.options do
|
178
|
-
jquery_ready external.text
|
179
|
-
end
|
180
|
-
end
|
162
|
+
def extra_widgets
|
163
|
+
[]
|
181
164
|
end
|
182
|
-
|
183
165
|
end
|
@@ -1,5 +1,10 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require "active_support/inflector"
|
3
|
+
|
4
|
+
module Erector
|
2
5
|
module Widgets #:nodoc:
|
6
|
+
|
7
|
+
|
3
8
|
# The Table widget provides the ability to render a table from a
|
4
9
|
# list of objects (one for each row).
|
5
10
|
#
|
@@ -93,4 +98,7 @@ module Erector
|
|
93
98
|
end
|
94
99
|
end
|
95
100
|
end
|
101
|
+
end
|
102
|
+
rescue LoadError => e
|
103
|
+
$stderr.puts "Erector::Widgets::Table requires active_support"
|
96
104
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
2
|
require "erector/rails"
|
3
|
+
require "rails/version"
|
3
4
|
|
4
5
|
# backport mktmpdir so this test will work on Ruby 1.8.6
|
5
6
|
unless Dir.respond_to?(:mktmpdir)
|
@@ -49,7 +50,6 @@ end
|
|
49
50
|
# user guide).
|
50
51
|
#
|
51
52
|
module Erector
|
52
|
-
|
53
53
|
describe "the Rails version" do
|
54
54
|
it "should be #{Erector::Rails::RAILS_VERSION}" do
|
55
55
|
::Rails::VERSION::STRING.should == Erector::Rails::RAILS_VERSION
|
@@ -57,9 +57,7 @@ module Erector
|
|
57
57
|
end
|
58
58
|
|
59
59
|
describe "Erect in a Rails app" do
|
60
|
-
|
61
60
|
def run(cmd)
|
62
|
-
# puts "Running #{cmd}"
|
63
61
|
stderr_file = Dir.tmpdir + "/stderr.txt"
|
64
62
|
stdout = IO.popen(cmd + " 2>#{stderr_file}") do |pipe|
|
65
63
|
pipe.read
|
@@ -76,37 +74,41 @@ module Erector
|
|
76
74
|
def indent(s)
|
77
75
|
s.gsub(/^/, ' ')
|
78
76
|
end
|
79
|
-
|
80
|
-
def run_rails(app_dir)
|
81
|
-
# To ensure we're working with the right version of Rails we use "gem 'rails', 1.2.3"
|
82
|
-
# in a "ruby -e" command line invocation of the rails executable to generate an
|
83
|
-
# app called explode.
|
84
|
-
#
|
85
|
-
# puts "Generating fresh rails #{Erector::Rails::RAILS_VERSION} app in #{app_dir}"
|
86
|
-
run "ruby -e \"require 'rubygems'; gem 'rails', '#{Erector::Rails::RAILS_VERSION}'; load 'rails'\" #{app_dir}"
|
87
|
-
end
|
88
|
-
|
77
|
+
|
89
78
|
it "works like we say it does in the user guide" do
|
90
79
|
erector_dir = File.expand_path("#{File.dirname(__FILE__)}/../..")
|
91
80
|
|
81
|
+
# We add the paths to our vendored copy of rails to the load paths, so
|
82
|
+
# that this spec can be run without having a version of Rails (which may
|
83
|
+
# not match the version we wish to test against) installed.
|
84
|
+
rails_libs_argument = "-I'#{RAILS_LOAD_PATHS.join("':'")}'"
|
85
|
+
|
92
86
|
Dir.mktmpdir do |app_dir|
|
93
|
-
|
87
|
+
run "ruby #{rails_libs_argument} '#{VENDOR_RAILS}/railties/bin/rails' '#{app_dir}'"
|
88
|
+
|
89
|
+
FileUtils.cp_r(VENDOR_RAILS, "#{app_dir}/vendor/rails")
|
94
90
|
|
95
91
|
FileUtils.mkdir_p(app_dir + "/vendor/gems")
|
96
92
|
FileUtils.cp_r(erector_dir, "#{app_dir}/vendor/gems/erector")
|
97
93
|
|
98
94
|
FileUtils.cd(app_dir) do
|
99
95
|
run "script/generate scaffold post title:string body:text published:boolean"
|
100
|
-
|
96
|
+
|
97
|
+
# The 'erector' binary would normally have been installed through rubygems,
|
98
|
+
# providing it with a wrapper script which requires rubygems. But here we
|
99
|
+
# run it directly, so we need to require rubygems explicitly before running
|
100
|
+
# the main script.
|
101
|
+
run "ruby #{rails_libs_argument} -I'#{erector_dir}/lib' " +
|
102
|
+
"-e \"require 'rubygems'; load '#{erector_dir}/bin/erector'\" app/views/posts"
|
103
|
+
|
101
104
|
FileUtils.rm_f("app/views/posts/*.erb")
|
102
105
|
run "rake --trace db:migrate"
|
106
|
+
|
103
107
|
# run "script/server" # todo: launch in background; use mechanize or something to crawl it; then kill it
|
104
108
|
# perhaps use open4?
|
105
109
|
# open http://localhost:3000/posts
|
106
110
|
end
|
107
111
|
end
|
108
112
|
end
|
109
|
-
|
110
113
|
end
|
111
|
-
|
112
114
|
end
|
data/spec/erect/erect_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
2
|
|
3
|
-
require "erector/erect"
|
3
|
+
require "erector/erect/erect"
|
4
4
|
|
5
5
|
module Erector
|
6
6
|
describe Erect do
|
@@ -23,6 +23,16 @@ module Erector
|
|
23
23
|
Erect.new([]).verbose.should be_true
|
24
24
|
Erect.new(["-q"]).verbose.should be_false
|
25
25
|
end
|
26
|
+
|
27
|
+
it "sets the superclass to what you tell it" do
|
28
|
+
Erect.new([]).superklass.should == 'Erector::Widget'
|
29
|
+
Erect.new(['--superclass', 'Foo::Bar']).superklass.should == 'Foo::Bar'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "sets the method name to what you tell it" do
|
33
|
+
Erect.new([]).method_name.should == 'content'
|
34
|
+
Erect.new(['--method', 'my_content']).method_name.should == 'my_content'
|
35
|
+
end
|
26
36
|
|
27
37
|
it "parses a command line with several filenames and an option on it" do
|
28
38
|
erect = Erect.new(["-q", "foo.html", "bar/baz.html"])
|
data/spec/erect/erected_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
2
|
|
3
|
-
require "erector/erect"
|
3
|
+
require "erector/erect/erect"
|
4
4
|
|
5
5
|
module Erector
|
6
6
|
describe Erected do
|
@@ -37,7 +37,7 @@ module Erector
|
|
37
37
|
Erected.new("views/stuff/foo_bar.html.erb").parent_class.should == "Erector::Widget"
|
38
38
|
end
|
39
39
|
|
40
|
-
def convert(dir, input, output)
|
40
|
+
def convert(dir, input, output, superklass = nil, method_name = nil)
|
41
41
|
dir = Dir.tmpdir + "/#{Time.now.to_i}" + "/#{dir}"
|
42
42
|
|
43
43
|
FileUtils.mkdir_p(dir)
|
@@ -47,8 +47,9 @@ module Erector
|
|
47
47
|
File.open(html, "w") do |f|
|
48
48
|
f.puts(input)
|
49
49
|
end
|
50
|
-
|
51
|
-
|
50
|
+
|
51
|
+
args = [ html, superklass || 'Erector::Widget', method_name || 'content' ]
|
52
|
+
@e = Erected.new(*args)
|
52
53
|
@e.convert
|
53
54
|
|
54
55
|
File.read(rb).should == output
|
@@ -79,13 +80,83 @@ module Erector
|
|
79
80
|
"end\n"
|
80
81
|
)
|
81
82
|
end
|
83
|
+
|
84
|
+
it "converts a normal file with a different superclass" do
|
85
|
+
convert(".",
|
86
|
+
"<div>hello</div>",
|
87
|
+
"class Dummy < Foo::Bar\n" +
|
88
|
+
" def content\n" +
|
89
|
+
" div do\n" +
|
90
|
+
" text 'hello'\n" +
|
91
|
+
" end\n" +
|
92
|
+
" end\n" +
|
93
|
+
"end\n",
|
94
|
+
"Foo::Bar"
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "converts a normal file with a different superclass and method name" do
|
99
|
+
convert(".",
|
100
|
+
"<div>hello</div>",
|
101
|
+
"class Dummy < Foo::Bar\n" +
|
102
|
+
" def my_content\n" +
|
103
|
+
" div do\n" +
|
104
|
+
" text 'hello'\n" +
|
105
|
+
" end\n" +
|
106
|
+
" end\n" +
|
107
|
+
"end\n",
|
108
|
+
"Foo::Bar",
|
109
|
+
'my_content'
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "ignores ERb trim markers" do
|
114
|
+
convert(".",
|
115
|
+
%{<div>
|
116
|
+
<%= 1 + 3 -%>
|
117
|
+
</div>},
|
118
|
+
%{class Dummy < Erector::Widget
|
119
|
+
def content
|
120
|
+
div do
|
121
|
+
rawtext 1 + 3
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
})
|
126
|
+
end
|
127
|
+
|
128
|
+
it "converts ERb escapes in attributes" do
|
129
|
+
convert(".",
|
130
|
+
"<div id=\"foo_<%= bar %>_baz_<%= quux %>_marph\">hello</div>",
|
131
|
+
%{class Dummy < Erector::Widget
|
132
|
+
def content
|
133
|
+
div(:id => ('foo_' + bar + '_baz_' + quux + '_marph')) do
|
134
|
+
text 'hello'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
})
|
139
|
+
end
|
140
|
+
|
141
|
+
it "only parenthesizes ERb escapes in attributes if necessary" do
|
142
|
+
convert(".",
|
143
|
+
"<div id=\'<%= bar %>\'>hello</div>",
|
144
|
+
%{class Dummy < Erector::Widget
|
145
|
+
def content
|
146
|
+
div :id => bar do
|
147
|
+
text 'hello'
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
})
|
152
|
+
end
|
82
153
|
|
83
154
|
# todo: figure out if there is any such thing as unparsable HTML anymore
|
84
155
|
# it "raises an exception if given unparsable HTML" do
|
85
156
|
# begin
|
86
157
|
# convert(".", "<", "")
|
87
158
|
# rescue => e
|
88
|
-
# e.
|
159
|
+
# e.to_html.should include("Could not parse")
|
89
160
|
# end
|
90
161
|
# end
|
91
162
|
|