erector 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|