effigy 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/gempackagetask'
4
+
5
+ require 'spec/rake/spectask'
6
+
7
+ desc 'Default: run the specs.'
8
+ task :default => [:spec]
9
+
10
+ Spec::Rake::SpecTask.new do |t|
11
+ t.spec_opts = ['--color', '--format', 'progress']
12
+ t.libs = %w(spec)
13
+ t.ruby_opts = ['-rrubygems']
14
+ end
15
+
16
+ spec = Gem::Specification.new do |s|
17
+ s.name = %q{effigy}
18
+ s.version = "0.1"
19
+ s.summary = %q{Effigy provides a view and template framework without a templating language.}
20
+ s.description = %q{Define views in Ruby and templates in HTML. Avoid code interpolation or ugly templating languages. Use ids, class names, and semantic structures already present in your documents to produce content.}
21
+
22
+ s.files = FileList['[A-Z]*', 'lib/**/*.rb', 'spec/**/*.rb']
23
+ s.require_path = 'lib'
24
+ s.test_files = Dir[*['spec/**/*_spec.rb']]
25
+
26
+ s.authors = ["Joe Ferris"]
27
+ s.email = %q{jferris@thoughtbot.com}
28
+
29
+ s.platform = Gem::Platform::RUBY
30
+ end
31
+
32
+ Rake::GemPackageTask.new spec do |pkg|
33
+ pkg.need_tar = true
34
+ pkg.need_zip = true
35
+ end
data/lib/effigy.rb ADDED
@@ -0,0 +1 @@
1
+ require 'effigy/view'
@@ -0,0 +1,63 @@
1
+ require 'nokogiri'
2
+
3
+ module Effigy
4
+ class View
5
+ def initialize
6
+ @css_assignments = {}
7
+ @xpath_assignments = {}
8
+ end
9
+
10
+ def text(selector, content)
11
+ select(selector).content = content
12
+ end
13
+
14
+ def attributes(selector, attributes)
15
+ element = select(selector)
16
+ attributes.each do |attribute, value|
17
+ element[attribute.to_s] = value
18
+ end
19
+ end
20
+
21
+ def examples_for(selector, collection, &block)
22
+ original_element = current_context.at(selector)
23
+ sibling = original_element
24
+ collection.each do |item|
25
+ item_element = original_element.dup
26
+ context(item_element) { yield(item) }
27
+ sibling.add_next_sibling(item_element)
28
+ sibling = item_element
29
+ end
30
+ original_element.unlink
31
+ end
32
+
33
+ def render(template)
34
+ @current_context = Nokogiri::XML.parse(template)
35
+ yield if block_given?
36
+ apply
37
+ current_context.to_s
38
+ end
39
+
40
+ def context(new_context)
41
+ old_context = @current_context
42
+ @current_context = select(new_context)
43
+ yield
44
+ @current_context = old_context
45
+ end
46
+
47
+ private
48
+
49
+ attr_reader :current_context
50
+
51
+ def select(nodes)
52
+ if nodes.respond_to?(:search)
53
+ nodes
54
+ else
55
+ current_context.at(nodes)
56
+ end
57
+ end
58
+
59
+ def apply
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+ require 'effigy/view'
3
+
4
+ module Effigy
5
+ describe View do
6
+ it "should replace element contents" do
7
+ template = %{<test><element one="abc">something</element></test>}
8
+
9
+ view = Effigy::View.new
10
+ xml = view.render(template) do
11
+ view.text 'element', 'expected'
12
+ end
13
+
14
+ xml.should have_selector(:element, :contents => 'expected', :one => 'abc')
15
+ end
16
+
17
+ it "should replace element attributes" do
18
+ template = %{<test><element one="abc">something</element></test>}
19
+
20
+ view = Effigy::View.new
21
+ xml = view.render(template) do
22
+ view.attributes 'element', :one => '123', :two => '234'
23
+ end
24
+
25
+ xml.should have_selector(:element, :contents => 'something', :one => '123', :two => '234')
26
+ end
27
+
28
+ it "should replace examples" do
29
+ template = %{<test><element><value>original</value></element></test>}
30
+
31
+ view = Effigy::View.new
32
+ xml = view.render(template) do
33
+ view.examples_for('element', %w(one two)) do |value|
34
+ view.text('value', value)
35
+ end
36
+ end
37
+
38
+ xml.should have_selector('element value', :contents => 'one')
39
+ xml.should have_selector('element value', :contents => 'two')
40
+ xml.should_not have_selector('element value', :contents => 'original')
41
+ xml.should =~ /one.*two/m
42
+ end
43
+
44
+ it "should replace within a context" do
45
+ template = %{<test><element><value>original</value></element></test>}
46
+
47
+ view = Effigy::View.new
48
+ xml = view.render(template) do
49
+ view.context('element') do
50
+ view.text('value', 'expected')
51
+ end
52
+ end
53
+
54
+ xml.should have_selector('element value', :contents => 'expected')
55
+ end
56
+ end
57
+
58
+ describe View, "subclass" do
59
+ before do
60
+ @subclass = Class.new(View)
61
+ @subclass.class_eval do
62
+ def initialize(value)
63
+ @value = value
64
+ end
65
+
66
+ def apply
67
+ text('element', @value)
68
+ end
69
+ end
70
+ end
71
+
72
+ it "should run #apply when rendering" do
73
+ template = %{<test><element>original</element></test>}
74
+ view = @subclass.new('expected')
75
+ view.render(template).should have_selector('element', :contents => 'expected')
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec'
2
+ require 'spec/autorun'
3
+
4
+ PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
5
+
6
+ $: << File.join(PROJECT_ROOT, 'lib')
7
+
8
+ Dir[File.join(PROJECT_ROOT, 'spec', 'support', '**', '*.rb')].each { |file| require(file) }
9
+
10
+ Spec::Runner.configure do |config|
11
+ config.include Matchers
12
+ end
@@ -0,0 +1,68 @@
1
+ module Matchers
2
+ class HaveSelector
3
+ def initialize(selector, attrs)
4
+ @selector = selector
5
+ @attrs = attrs
6
+ @contents = attrs.delete(:contents)
7
+ end
8
+
9
+ def matches?(xml)
10
+ @xml = xml
11
+
12
+ verify_element_present! &&
13
+ verify_contents! &&
14
+ verify_attrs!
15
+ end
16
+
17
+ def failure_message
18
+ "Expected #{@missing},\nGot: #{elements.to_a.join("\n")}"
19
+ end
20
+
21
+ def negative_failure_message
22
+ "Did not expect #{selector}"
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :xml, :selector, :attrs, :contents, :missing
28
+
29
+ def verify_element_present!
30
+ if elements.empty?
31
+ @missing = "an element matching the following CSS selector: #{selector}"
32
+ false
33
+ else
34
+ true
35
+ end
36
+ end
37
+
38
+ def verify_contents!
39
+ if contents.nil? || elements.any? { |element| element.text == @contents}
40
+ true
41
+ else
42
+ @missing = "element with contents: #{@contents}"
43
+ false
44
+ end
45
+ end
46
+
47
+ def verify_attrs!
48
+ if elements.any? { |element| attrs.all? { |attribute, value| element[attribute.to_s] == value } }
49
+ true
50
+ else
51
+ @missing = "element with attrs: #{attrs.inspect}"
52
+ false
53
+ end
54
+ end
55
+
56
+ def elements
57
+ @elements ||= document.css(selector.to_s)
58
+ end
59
+
60
+ def document
61
+ @document ||= Nokogiri::XML.parse(xml)
62
+ end
63
+ end
64
+
65
+ def have_selector(selector, attrs = {})
66
+ HaveSelector.new(selector, attrs)
67
+ end
68
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: effigy
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Joe Ferris
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-06 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Define views in Ruby and templates in HTML. Avoid code interpolation or ugly templating languages. Use ids, class names, and semantic structures already present in your documents to produce content.
17
+ email: jferris@thoughtbot.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - Rakefile
26
+ - lib/effigy/view.rb
27
+ - lib/effigy.rb
28
+ - spec/effigy/view_spec.rb
29
+ - spec/spec_helper.rb
30
+ - spec/support/have_selector.rb
31
+ has_rdoc: true
32
+ homepage:
33
+ licenses: []
34
+
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ requirements: []
53
+
54
+ rubyforge_project:
55
+ rubygems_version: 1.3.4
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: Effigy provides a view and template framework without a templating language.
59
+ test_files:
60
+ - spec/effigy/view_spec.rb