Browse files

Fixed compatibility issues with Nokogiri >= 1.4.2;

Separated Effigy::View#render into methods for full documents and fragments;
Render Rails layouts as full documents and everything else as fragments.
  • Loading branch information...
1 parent b120331 commit 1709452345e86ffdb89ced87f062111d92a851fb @jferris committed Aug 20, 2010
View
4 README.textile
@@ -4,7 +4,7 @@ Create usable views in Ruby with HTML and CSS selectors.
h2. Synopsis
-In Effigy, your view is a Ruby class that performs transformation on an HTML template. The template is passed to #render, which calls a private #transform method to apply the transformations. The transformed template is then returned as a string of HTML.
+In Effigy, your view is a Ruby class that performs transformation on an HTML template. The template is passed to a render method, which calls a private #transform method to apply the transformations. The transformed template is then returned as a string of HTML.
<pre>
template = %{
@@ -46,7 +46,7 @@ class PostView < Effigy::View
end
view = PostView.new(post)
-document = view.render(template)
+document = view.render_html_document(template)
# Result document:
# <html>
View
13 lib/effigy/rails/template_handler.rb
@@ -34,7 +34,7 @@ def compile(view)
end
end
view = #{view_class_name}.new(self, assigns) { |*names| yield(*names) }
- view.render(#{template_source.inspect})
+ view.#{render_method}(#{template_source.inspect})
RUBY
end
@@ -90,6 +90,17 @@ def layout?
base_path =~ /^layouts/
end
+ # @return [String] the method that should be used to render the document.
+ # The template will be parsed as a full html document for a layout, and a
+ # fragment for anything else.
+ def render_method
+ if layout?
+ 'render_html_document'
+ else
+ 'render_html_fragment'
+ end
+ end
+
# @return [Boolean] true-ish if this view is a partial, false-ish otherwise
def partial?
@view.name =~ /^_/
View
52 lib/effigy/view.rb
@@ -10,13 +10,15 @@ module Effigy
# Accepts a template to be transformed.
#
# For most common cases, creating a subclass makes the most sense, but this
- # class can be used directly by passing a block to {#render}.
+ # class can be used directly by passing a block to {#render_html_document} or
+ # {#render_html_fragment}.
#
# @see #transform
- # @see #render
+ # @see #render_html_document
+ # @see #render_html_fragment
# @example
# view = Effigy::View.new
- # view.render(template) do
+ # view.render_html_document(template) do
# view.find('h1').text('the title')
# end
#
@@ -77,18 +79,26 @@ def replace_each(selector, collection, &block)
ExampleElementTransformer.new(self, selected_elements).replace_each(collection, &block)
end
- # Perform transformations on the given template.
+ # Perform transformations on a string containing an html fragment.
#
# @yield inside the given block, transformation methods such as #text and
# #html can be used on the template. Using a subclass, you can instead
# override the #transform method, which is the preferred approach.
#
- # @return [String] the resulting document
- def render(template)
- @current_context = Nokogiri::HTML.fragment(template)
- yield if block_given?
- transform
- output
+ # @return [String] the transformed fragment
+ def render_html_fragment(template, &block)
+ yield_transform_and_output(Nokogiri::HTML.fragment(template), &block)
+ end
+
+ # Perform transformations on a string containing an html document.
+ #
+ # @yield inside the given block, transformation methods such as #text and
+ # #html can be used on the template. Using a subclass, you can instead
+ # override the #transform method, which is the preferred approach.
+ #
+ # @return [String] the transformed document
+ def render_html_document(template, &block)
+ yield_transform_and_output(Nokogiri::HTML.parse(template), &block)
end
# Removes the selected elements from the template.
@@ -201,10 +211,9 @@ def find(selector)
end
alias_method :f, :find
- # Called by {#render} to perform transformations on the source template.
- #
- # Override this method in subclasses to perform the transformations
- # specific to your view.
+ # Called by render methods to perform transformations on the source
+ # template. Override this method in subclasses to perform the
+ # transformations specific to your view.
#
# @example
# class PostView < Effigy::View
@@ -261,8 +270,8 @@ def clone_element_with_item(original_element, item, &block)
# Converts the transformed document to a string.
#
- # Called by {#render} after transforming the document using a passed block
- # and {#transform}.
+ # Called by render methods after transforming the document using a passed
+ # block and {#transform}.
#
# Override this in subclasses if you wish to return something besides an
# XHTML string representation of the transformed document.
@@ -272,5 +281,16 @@ def output
current_context.to_html
end
+ # Uses the given document or fragment as a basis for transformation.
+ #
+ # @yield self, with the document or fragment set as the context.
+ #
+ # @return [String] the transformed document or fragment as a string
+ def yield_transform_and_output(document_or_fragment)
+ @current_context = document_or_fragment
+ yield if block_given?
+ transform
+ output
+ end
end
end
View
2 spec/effigy/example_element_transformer_spec.rb
@@ -19,7 +19,7 @@ def transform
<element><value>original</value></element>
<element><value>dup</value></element>
</test>}
- xml = view.render(template)
+ xml = view.render_html_fragment(template)
xml.should have_selector('element value', :contents => 'one')
xml.should have_selector('element value', :contents => 'two')
View
6 spec/effigy/rails/template_handler_spec.rb
@@ -120,10 +120,10 @@ def transform
RUBY
create_rails_file 'app/templates/wand/index.html', <<-HTML
- <html><body>
+ <div>
<h1 class="success">spell</h1>
<p>placeholder</p>
- </body></html>
+ </div>
HTML
create_rails_file 'app/views/wand/_spell.html.effigy', <<-RUBY
@@ -141,6 +141,6 @@ def transform
response = render(WandController.new)
response.should be_success
- response.body.should have_selector('html body p', :contents => 'hocus pocus')
+ response.body.should have_selector('div p', :contents => 'hocus pocus')
end
end
View
45 spec/effigy/view_spec.rb
@@ -10,7 +10,7 @@ module Effigy
</test>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.text 'element', 'expected'
end
@@ -25,7 +25,7 @@ module Effigy
</test>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.attr 'element', :one => '123', :two => '234'
end
@@ -37,7 +37,7 @@ module Effigy
template = %{<test><element one="abc">something</element></test>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.attr 'element', :one, '123'
end
@@ -51,7 +51,7 @@ module Effigy
</test>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.replace_each('element', %w(one two)) do |value|
view.text('value', value)
end
@@ -68,7 +68,7 @@ module Effigy
template = %{<test><element><value>original</value></element></test>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.find('element') do
view.text('value', 'expected')
end
@@ -81,7 +81,7 @@ module Effigy
template = %{<test><first class="yes"/><other class="yes"/><last class="no"/></test>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.remove('.yes')
end
@@ -93,7 +93,7 @@ module Effigy
template = %{<test class="original"/>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.add_class('test', 'one', 'two')
end
@@ -106,7 +106,7 @@ module Effigy
template = %{<test class="one two three"/>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.remove_class('test', 'one', 'two')
end
@@ -119,31 +119,31 @@ module Effigy
template = %{<test><original>contents</original></test>}
view = Effigy::View.new
- html = view.render(template) do
- view.html 'test', '<new>replaced</new>'
+ html = view.render_html_fragment(template) do
+ view.html 'test', '<b>replaced</b>'
end
- html.should have_selector('test new', :contents => 'replaced')
+ html.should have_selector('test b', :contents => 'replaced')
html.should_not have_selector('original')
end
it "should replace an element's outer markup" do
template = %{<test><original>contents</original></test>}
view = Effigy::View.new
- html = view.render(template) do
- view.replace_with 'test', '<new>replaced</new>'
+ html = view.render_html_fragment(template) do
+ view.replace_with 'test', '<b>replaced</b>'
end
- html.should have_selector('new', :contents => 'replaced')
+ html.should have_selector('b', :contents => 'replaced')
html.should_not have_selector('test')
end
it "should append text to elements" do
template = %{<outer><test class="abc">start</test><other class="abc">start</other></outer>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.append '.abc', '<p>middle</p><p>end</p>'
end
@@ -155,23 +155,24 @@ module Effigy
html.should have_selector('other p', :contents => 'end')
end
- it "should render html by default" do
+ it "should render an html document" do
template = %{<html/>}
- html = Effigy::View.new.render(template)
+ html = Effigy::View.new.render_html_document(template)
html.should_not include('<?xml')
html.should_not include('xmlns')
+ html.should have_selector('html')
end
it "should keep multiple top-level elements" do
template = %{<p>fragment one</p><p>fragment two</p>}
- html = Effigy::View.new.render(template)
+ html = Effigy::View.new.render_html_fragment(template)
html.should include('one')
html.should include('two')
end
it "should handle html fragments" do
template = %{<h1>hello</h1>}
- html = Effigy::View.new.render(template)
+ html = Effigy::View.new.render_html_fragment(template)
html.should == template
end
@@ -180,7 +181,7 @@ module Effigy
template = %{<test><element one="abc">something</element></test>}
view = Effigy::View.new
- html = view.render(template) do
+ html = view.render_html_fragment(template) do
view.send(chain_method, 'element').text('expected')
end
@@ -192,7 +193,7 @@ module Effigy
def render(&block)
lambda do
view = Effigy::View.new
- view.render('<test/>') { block.call(view) }
+ view.render_html_fragment('<test/>') { block.call(view) }
end
end
@@ -235,7 +236,7 @@ def transform
it "should run #transform when rendering" do
template = %{<test><element>original</element></test>}
view = @subclass.new('expected')
- view.render(template).should have_selector('element', :contents => 'expected')
+ view.render_html_fragment(template).should have_selector('element', :contents => 'expected')
end
end
end
View
1 spec/spec_helper.rb
@@ -1,3 +1,4 @@
+gem 'nokogiri', '1.4.2'
require 'spec'
require 'spec/autorun'

0 comments on commit 1709452

Please sign in to comment.