bubble 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Eric Budd
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,68 @@
1
+ = Bubble
2
+
3
+ Bubble is a library for creating HTML from basic Ruby data structures.
4
+
5
+ == Installation
6
+
7
+ Bubble is a gem.
8
+
9
+ gem install bubble
10
+
11
+ == Examples
12
+
13
+ Bubble can convert arrays and symbols into tags and hashes into attributes.
14
+
15
+ If you want to create simple tags:
16
+
17
+ b = Bubble.new([:h1, "Entitling!"])
18
+ b.to_html
19
+ # => "<h1>Entitling!</h1>"
20
+
21
+ Or if you want a tag with attributes:
22
+
23
+ link = Bubble.new([:a, {:href => "/images/free_cat.jpg"}, "Free Cat!"])
24
+ link.to_html
25
+ # => "<a href="/images/free_cat.jpg">Free Cat!</a>"
26
+
27
+ Empty tags:
28
+
29
+ sad_and_alone = Bubble.new([:p])
30
+ sad_and_alone.to_html
31
+ # => "<p />"
32
+
33
+ Or even nested tags:
34
+
35
+ blurb = Bubble.new([:marquee, {:style => 'font-weight: bold'}, [:font, "Arial",[:size, "smaller", [:b, "Made with DreamWeaver!"]]]])
36
+ blurb.to_html
37
+ # => "<marquee style="font-weight: bold"><font><Arial><size><smaller><b>Made with DreamWeaver!</b></smaller></size></Arial></font></marquee>"
38
+
39
+ Since Bubble objects are just repurposed Arrays and Hashes, you can perform all the same operations on them.
40
+
41
+ b = Bubble.new
42
+ b[0] = :p
43
+ b << "Parachute Pants!"
44
+ b += [{:class => "hammer#{Time.new.class.name.downcase}"}]
45
+ b.last.merge!(:action => 'Stop!')
46
+ b.to_html
47
+ # => "<p class="hammertime" action="Stop!">Parachute Pants!</p>"
48
+
49
+ == Purpose
50
+
51
+ While it's certainly conceivable that you could build an entire templating system around Bubble, it's intended to create and programatically maniuplate small snippets of HTML.
52
+
53
+ Ruby has an excellent library for working with arrays and hashes, and Bubble lets you work within the standard library instead of trying to wrangle raw HTML into a manipulable format.
54
+
55
+ == Contributing to Bubble
56
+
57
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
58
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
59
+ * Fork the project
60
+ * Start a feature/bugfix branch
61
+ * Commit and push until you are happy with your contribution
62
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
63
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
64
+
65
+ == Copyright
66
+
67
+ Copyright (c) 2011 Eric Budd. See LICENSE.txt for further details.
68
+
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "bubble"
16
+ gem.homepage = "http://github.com/Calamitous/bubble"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Bubble is a library for creating HTML from basic Ruby data structures.}
19
+ gem.description = %Q{Bubble is a library for creating HTML from basic Ruby data structures.}
20
+ gem.email = "eric.b.budd@gmail.com"
21
+ gem.authors = ["Eric Budd"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "bubble #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,64 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{bubble}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Eric Budd"]
12
+ s.date = %q{2011-06-08}
13
+ s.description = %q{Bubble is a library for creating HTML from basic Ruby data structures.}
14
+ s.email = %q{eric.b.budd@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bubble.gemspec",
28
+ "lib/bubble.rb",
29
+ "spec/bubble_spec.rb",
30
+ "spec/spec_helper.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/Calamitous/bubble}
33
+ s.licenses = ["MIT"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.6}
36
+ s.summary = %q{Bubble is a library for creating HTML from basic Ruby data structures.}
37
+ s.test_files = [
38
+ "spec/bubble_spec.rb",
39
+ "spec/spec_helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
48
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
49
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
50
+ s.add_development_dependency(%q<rcov>, [">= 0"])
51
+ else
52
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
53
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
54
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
55
+ s.add_dependency(%q<rcov>, [">= 0"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
59
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
61
+ s.add_dependency(%q<rcov>, [">= 0"])
62
+ end
63
+ end
64
+
@@ -0,0 +1,82 @@
1
+ class Bubble < Array
2
+ def to_fragment
3
+ self
4
+ end
5
+
6
+ def to_html
7
+ if first.is_a?(Array)
8
+ self.each do |x|
9
+ unless x.is_a?(Array)
10
+ raise ArgumentError.new(":#{x.to_s} is not a valid tag array. Did you mean [:#{x.to_s}]?")
11
+ end
12
+ end
13
+ map{|x| x.to_html }.join # traverse
14
+ else
15
+ self.to_tag #descend
16
+ end
17
+ end
18
+
19
+ def to_tag
20
+ return '' if empty?
21
+ if self.size == 1
22
+ return self[0].is_a?(Symbol) ? "<#{self[0].to_s} />" : self[0]
23
+ end
24
+
25
+ list = reject{ |x| x.is_a?(Hash) }
26
+ head, tail = list.bite_off_head
27
+
28
+ fore_tag = [head.to_s, properties.to_property_string].compact.reject{ |x| x.empty? }.join(' ')
29
+
30
+ return "<#{fore_tag} />" if tail.nil? || tail.empty?
31
+ "<#{fore_tag}>#{tail.to_html}</#{head}>"
32
+ end
33
+
34
+ def properties
35
+ self.inject({}) { |acc, elem| acc.merge!(elem) if elem.is_a?(Hash); acc }
36
+ end
37
+
38
+ def bite_off_head
39
+ return self[0], self[1..-1]
40
+ end
41
+ end
42
+
43
+ class BubbleProperty < Hash
44
+ def initialize(data = {})
45
+ if data.respond_to?(:keys)
46
+ data.keys.each{|k| self[k] = data[k]}
47
+ else
48
+ raise ArgumentError, "Couldn't instantiate BubbleProperty; I expected a Hash-y object."
49
+ end
50
+ end
51
+
52
+ def to_property_string
53
+ self.map{ |k, v| "#{k.to_s}=\"#{v.to_s}\""}.join(' ')
54
+ end
55
+ end
56
+
57
+ class Array
58
+ def to_fragment
59
+ Bubble.new(self)
60
+ end
61
+
62
+ def to_html
63
+ self.to_fragment.to_html
64
+ end
65
+ end
66
+
67
+ class Hash
68
+ def to_fragment_property
69
+ BubbleProperty.new(self)
70
+ end
71
+
72
+ def to_property_string
73
+ self.to_fragment_property.to_property_string
74
+ end
75
+ end
76
+
77
+ class String
78
+ def to_html
79
+ self
80
+ end
81
+ end
82
+
@@ -0,0 +1,133 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe 'Bubble' do
4
+ context 'while entagging data' do
5
+ it 'entags a tag array' do
6
+ data = [[:a]]
7
+ data.to_html.should == '<a />'
8
+ end
9
+
10
+ it 'entags multiple arrays' do
11
+ data = [[[:a], [:b]]]
12
+ data.to_html.should == '<a /><b />'
13
+ end
14
+
15
+ it 'entags nested tag arrays' do
16
+ data = [[:a, [:b]]]
17
+ data.to_html.should == '<a><b /></a>'
18
+ end
19
+
20
+ it 'entags nested multiple tag arrays' do
21
+ data = [[[:a, [:b]], [:c, [:d]]]]
22
+ data.to_html.should == '<a><b /></a><c><d /></c>'
23
+ end
24
+
25
+ it 'entags nested arrays to an arbitrary depth' do
26
+ data = [[:a, [:b, [:c, [:d]]]]]
27
+ data.to_html.should == '<a><b><c><d /></c></b></a>'
28
+ end
29
+
30
+ it 'entags nested arrays including static text' do
31
+ pending
32
+ # hmmm, what should be the preferred usage...
33
+ # [:p, 'Test', [:a, {:href => '/wut'}, 'this'], 'baby']
34
+ # or
35
+ # [:p, 'Test #{[:a, {:href => '/wut'}, 'this'].to_html} baby']
36
+ data = [[:a, [:b, 'NO WAI', [:c, [:d, 'LOLWUT']]]]]
37
+ # data.to_html.should == '<a><b>NO WAI<c><d>LOLWUT</d></c></b></a>'
38
+ end
39
+
40
+ it 'ignores empty nesting' do
41
+ data = [[:a, [[[:b]]], [:c]]]
42
+ data.to_html.should == '<a><b /><c /></a>'
43
+ end
44
+
45
+ it 'raises an error if a tag is not correctly wrapped' do
46
+ data = [[:a], :c]
47
+ lambda { data.to_html }.should raise_error(':c is not a valid tag array. Did you mean [:c]?')
48
+ end
49
+
50
+ it 'renders static text' do
51
+ data = [:p, 'this thing']
52
+ data.to_html.should == '<p>this thing</p>'
53
+ end
54
+
55
+ context 'with properties' do
56
+ it 'entags a tag array' do
57
+ data = [[:a, {:foo => :bar}]]
58
+ data.to_html.should == '<a foo="bar" />'
59
+ end
60
+
61
+ it 'renders static text' do
62
+ data = [:p, {:class => 'test'}, 'this thing']
63
+ data.to_html.should == '<p class="test">this thing</p>'
64
+ end
65
+
66
+ it 'entags properties around interleaved tag arrays' do
67
+ data = [[:a, [:b], {:foo => :bar}]]
68
+ data.to_html.should == '<a foo="bar"><b /></a>'
69
+ end
70
+
71
+ it 'collects multiple hashes in to a single list of properties' do
72
+ data = [[:a, {:foo => :bar}, {:baz => 'quux!'}]]
73
+ data.to_html.should match(/baz="quux!"/)
74
+ data.to_html.should match(/foo="bar"/)
75
+ end
76
+
77
+ it 'overrides properties which have already been defined to the left' do
78
+ data = [[:a, {:foo => :bar}, {:foo => 'quux!'}]]
79
+ data.to_html.should == '<a foo="quux!" />'
80
+ end
81
+
82
+ it 'entags nested arrays' do
83
+ data = [[:a, [:b, {:lol => 'wut'}]]]
84
+ data.to_html.should == '<a><b lol="wut" /></a>'
85
+ end
86
+
87
+ it 'entags nested multiple tag arrays' do
88
+ data = [[[:a, [:b, {:lol => 'wut'}]], [:c, [:d, {:no => 'wai'}]]]]
89
+ data.to_html.should == '<a><b lol="wut" /></a><c><d no="wai" /></c>'
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ describe BubbleProperty do
96
+ context 'instantiation' do
97
+ it 'doesn\'t have any values' do
98
+ BubbleProperty.new.keys.should be_empty
99
+ end
100
+
101
+ it 'copies values from a provided hash' do
102
+ props = BubbleProperty.new(:a => :b)
103
+ props[:a].should == :b
104
+ end
105
+
106
+ it 'raises an error when an unhashable value is provided' do
107
+ lambda { BubbleProperty.new('I\'m a string!') }.should raise_error(ArgumentError)
108
+ end
109
+
110
+ it 'occurs when Hash#to_fragment_property is called' do
111
+ hash = {:c => 45, 'other' => Class}
112
+ prop = hash.to_fragment_property
113
+ prop.keys.each{ |k| hash[k].should == prop[k] }
114
+ end
115
+ end
116
+
117
+ context 'rendering' do
118
+ it 'returns an HTML property string' do
119
+ props = BubbleProperty.new(:a => 45)
120
+ props.to_property_string.should == 'a="45"'
121
+ end
122
+
123
+ it 'renders multiple properties' do
124
+ new_properties = {:a => 45, 'foo' => 'bar'}
125
+ props = BubbleProperty.new(new_properties)
126
+ props.to_property_string.should == 'foo="bar" a="45"'
127
+ end
128
+
129
+ it 'occurs when Hash#to_property_string is called' do
130
+ {:a => 45, 'foo' => 'bar'}.to_property_string.should == 'foo="bar" a="45"'
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'bubble'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bubble
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Eric Budd
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-06-08 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ version_requirements: &id001 !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ~>
24
+ - !ruby/object:Gem::Version
25
+ segments:
26
+ - 2
27
+ - 3
28
+ - 0
29
+ version: 2.3.0
30
+ prerelease: false
31
+ name: rspec
32
+ requirement: *id001
33
+ type: :development
34
+ - !ruby/object:Gem::Dependency
35
+ version_requirements: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 1
41
+ - 0
42
+ - 0
43
+ version: 1.0.0
44
+ prerelease: false
45
+ name: bundler
46
+ requirement: *id002
47
+ type: :development
48
+ - !ruby/object:Gem::Dependency
49
+ version_requirements: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 1
55
+ - 5
56
+ - 2
57
+ version: 1.5.2
58
+ prerelease: false
59
+ name: jeweler
60
+ requirement: *id003
61
+ type: :development
62
+ - !ruby/object:Gem::Dependency
63
+ version_requirements: &id004 !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ prerelease: false
71
+ name: rcov
72
+ requirement: *id004
73
+ type: :development
74
+ description: Bubble is a library for creating HTML from basic Ruby data structures.
75
+ email: eric.b.budd@gmail.com
76
+ executables: []
77
+
78
+ extensions: []
79
+
80
+ extra_rdoc_files:
81
+ - LICENSE.txt
82
+ - README.rdoc
83
+ files:
84
+ - .document
85
+ - .rspec
86
+ - Gemfile
87
+ - LICENSE.txt
88
+ - README.rdoc
89
+ - Rakefile
90
+ - VERSION
91
+ - bubble.gemspec
92
+ - lib/bubble.rb
93
+ - spec/bubble_spec.rb
94
+ - spec/spec_helper.rb
95
+ has_rdoc: true
96
+ homepage: http://github.com/Calamitous/bubble
97
+ licenses:
98
+ - MIT
99
+ post_install_message:
100
+ rdoc_options: []
101
+
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ requirements: []
119
+
120
+ rubyforge_project:
121
+ rubygems_version: 1.3.6
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: Bubble is a library for creating HTML from basic Ruby data structures.
125
+ test_files:
126
+ - spec/bubble_spec.rb
127
+ - spec/spec_helper.rb