microformats 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,6 @@
1
+ = Microformats CHANGELOG
2
+
3
+ == Version 0.1
4
+ * Initial Implementation of Vcard
5
+ * Implements hCard microformat
6
+ * Implements Google's Person microdata http://www.data-vocabulary.org/Person/
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Chris Powers
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.
data/README.rdoc ADDED
@@ -0,0 +1,95 @@
1
+ = MICROFORMATS
2
+
3
+ <em>Created by Chris Powers, September 11, 2010</em>
4
+
5
+ == Two Great Tastes, One Great Library
6
+
7
+ The goal of this Microformats library is to give the developer
8
+ a series of simple view helper methods to richly markup their
9
+ HTML documents using both the older Microformats standard and
10
+ the new HTML5 Microdata standard.
11
+
12
+ By using microformats, you are opening your data up to Google
13
+ and other consumers for easy and intelligent consumption. In
14
+ the future, Google plans on consuming microdata and making it
15
+ directly searchable, which yields all sorts of new potential
16
+ for relevant results.
17
+
18
+ == Installation
19
+
20
+ Install the Microformats gem as usual:
21
+
22
+ gem install microformats
23
+
24
+ == Usage: Vcards
25
+
26
+ You can easily markup a person and/or organization using the
27
+ 'vcard' helper method. This will use both the hCard Microformat
28
+ and the http://www.data-vocabulary.org/Person/ microdata.
29
+
30
+ <strong>PLEASE NOTE:</strong> These two microdata standards do
31
+ not support the same fields. For example, hCard gives a person
32
+ telephone numbers and email addresses. The Person microdata only
33
+ gives organizations a single telephone number and has no knowledge
34
+ of emails. It does, however, have a photo field, which is missing
35
+ from hCard.
36
+
37
+ To use it, first include the Microformats::Helper mixin into your view
38
+ layer, like this in Rails:
39
+
40
+ module Application Helper
41
+ include Microformats::Helpers
42
+ end
43
+
44
+ Then, you can do something like this in your view (using ERB here):
45
+
46
+ <% vcard do |card| %>
47
+ <%= card.photo "/images/me.jpg", :size => '200x300' %>
48
+ <%= card.name "John Doe" %>
49
+ <%= card.url "Visit my Site", :href => "http://mydomain.com" %>
50
+ <%= card.phone "999.888.7766", :type => 'Home' %>
51
+ <%= card.phone "111.222.3344", :type => 'Work' %>
52
+ <%= card.email "me@mydomain.com", :type => 'Home' %>
53
+
54
+ I work at <%= card.company "Acme Co." %>
55
+ <% vcard_address(:type => 'Work') do |adr| %>
56
+ <%= adr.street "123 Main" %>
57
+ <%= adr.city "Chicago" %>, <%= adr.state 'IL' %> <%= adr.zip '60010' %>
58
+ <% end %>
59
+ <%= card.download_link "http://mydomain.com" %>
60
+ <% end %>
61
+
62
+ This will output the following markup:
63
+
64
+ <div class='vcard' itemscope='itemscope' itemtype='http://data-vocabulary.org/Person'>
65
+ <img itemprop='photo' src='/images/me.jpg' width='200' height='300' />
66
+ <span class='fn' itemprop='name'>John Doe</span>
67
+ <a class='url' href='http://mydomain.com' itemprop='url'>Visit my Site</a>
68
+ <span class='tel'><span class='type'>Home</span> 999.888.7766</span>
69
+ <span class='tel'><span class='type'>Work</span> 111.222.3344</span>
70
+ <span class='email'><span class='type'>Home</span> me@mydomain.com</span>
71
+
72
+ I work at <span class='org' itemprop='affiliation'>Acme Co.</span>
73
+ <div class='adr' itemscope='itemscope' itemtype='http://data-vocabulary.org/Address'>
74
+ <span class='type'>Work</span>
75
+ <span class='street-address' itemprop='street-address'>123 Main</span>
76
+ <span class='locality' itemprop='locality'>Chicago</span>, <span class='region' itemprop='region'>IL</span> <span class='postal-code' itemprop='postal-code'>60010</span>
77
+ </div>
78
+ <a href='http://h2vx.com/vcf/mydomain.com/page' type='text/directory'>Download vCard</a>
79
+ </div>
80
+
81
+ While these helper methods default to using <span> tags
82
+ (and <a> tags as appropriate), you can easily customize
83
+ the tag used for any given piece of microdata by using the
84
+ <tt>:tag</tt> options:
85
+
86
+ <%= card.name "John Doe", :tag => :h1 %>
87
+
88
+ Also note that you get the <tt>download_link</tt> method
89
+ that builds a link to h2vx.com that will automatically let
90
+ the user download vCards from whatever page url you pass in.
91
+ Usually you will just want to pass in the page that you are
92
+ currently on, so this is a quick way to do this in Rails:
93
+
94
+ <%= card.download_link request.request_uri %>
95
+
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ # require 'rake/rdoctask'
4
+ # require 'rake/gempackagetask'
5
+ # require 'rcov/rcovtask'
6
+ # require 'date'
7
+
8
+ require 'spec/rake/spectask'
9
+
10
+ desc 'Default: run the specs.'
11
+ task :default => :spec
12
+
13
+ Spec::Rake::SpecTask.new do |t|
14
+ t.warning = true
15
+ end
data/lib/address.rb ADDED
@@ -0,0 +1,32 @@
1
+ class Microformats::Address
2
+ def street(str, opts = {})
3
+ content_tag(opts[:tag] || :span, str, :class => 'street-address', :itemprop => 'street-address')
4
+ end
5
+
6
+ def city(str, opts = {})
7
+ content_tag(opts[:tag] || :span, str, :class => 'locality', :itemprop => 'locality')
8
+ end
9
+
10
+ def state(str, opts = {})
11
+ content_tag(opts[:tag] || :span, str, :class => 'region', :itemprop => 'region')
12
+ end
13
+
14
+ def zip(str, opts = {})
15
+ content_tag(opts[:tag] || :span, str, :class => 'postal-code', :itemprop => 'postal-code')
16
+ end
17
+ alias_method :postal_code, :zip
18
+
19
+ def country(str, opts = {})
20
+ content_tag(opts[:tag] || :span, str, :class => 'country-name', :itemprop => 'country-name')
21
+ end
22
+
23
+ def content_tag(tag, content, opts={})
24
+ attrs = opts.inject([]) do |out, tuple|
25
+ k,v = tuple
26
+ out << "#{k}='#{v}'"
27
+ end
28
+ attr_string = attrs.sort.join(' ')
29
+ open_tag = attr_string == '' ? tag : "#{tag} #{attr_string}"
30
+ "<#{open_tag}>#{content}</#{tag}>"
31
+ end
32
+ end
data/lib/helpers.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Microformats::Helpers
2
+ # FIXME: Figure out how to make this non-Rails specific
3
+ # i.e. not rely on using concat
4
+ def vcard(&block)
5
+ concat "<div class='vcard' itemscope='itemscope' itemtype='http://data-vocabulary.org/Person'>\n"
6
+ block.call(Microformats::Vcard.new)
7
+ concat "</div>\n"
8
+ end
9
+
10
+ # FIXME: Figure out how to make this non-Rails specific
11
+ # i.e. not rely on using concat
12
+ def vcard_address(opts = {}, &block)
13
+ address = Microformats::Address.new
14
+ type = opts[:type] ? address.content_tag(:span, opts[:type], :class => 'type') : nil
15
+ concat "<div class='adr' itemscope='itemscope' itemtype='http://data-vocabulary.org/Address'>\n"
16
+ concat type if type
17
+ block.call(address)
18
+ concat "</div>\n"
19
+ end
20
+
21
+ end
@@ -0,0 +1,7 @@
1
+ module Microformats
2
+
3
+ end
4
+
5
+ require 'vcard'
6
+ require 'address'
7
+ require 'helpers'
data/lib/vcard.rb ADDED
@@ -0,0 +1,70 @@
1
+ class Microformats::Vcard
2
+ def initialize
3
+ @default_tag = :span
4
+ end
5
+
6
+ def name(str, opts = {})
7
+ content_tag(opts[:tag] || :span, str, :class => 'fn', :itemprop => 'name')
8
+ end
9
+
10
+ def company(str, opts = {})
11
+ content_tag(opts[:tag] || :span, str, :class => 'org', :itemprop => 'affiliation')
12
+ end
13
+ alias_method :organization, :company
14
+
15
+ def url(str, opts = {})
16
+ if opts[:href]
17
+ content_tag(:a, str, :href => opts[:href], :class => 'url', :itemprop => 'url')
18
+ elsif opts[:tag]
19
+ content_tag(opts[:tag], str, :class => 'url', :itemprop => 'url')
20
+ else
21
+ content_tag(:a, str, :class => 'url', :href => str, :itemprop => 'url')
22
+ end
23
+ end
24
+
25
+ def photo(str, opts = {})
26
+ image_tag(str, opts.merge(:itemprop => 'photo'))
27
+ end
28
+
29
+ def phone(str, opts = {})
30
+ type = opts[:type] ? content_tag(:span, opts[:type], :class => 'type') + ' ' : ''
31
+ content_tag(opts[:tag] || :span, type + str, :class => 'tel')
32
+ end
33
+
34
+ def email(str, opts = {})
35
+ type = opts[:type] ? content_tag(:span, opts[:type], :class => 'type') + ' ' : ''
36
+ if opts[:tag] == :a
37
+ content_tag(:a, type + str, :class => 'email', :href => "mailto:#{str}")
38
+ else
39
+ content_tag(opts[:tag] || :span, type + str, :class => 'email')
40
+ end
41
+ end
42
+
43
+ def download_link(url, opts = {})
44
+ str = opts.delete(:text) || "Download vCard"
45
+ new_url = "http://h2vx.com/vcf/" + url.gsub("http://", '')
46
+ content_tag(:a, str, :href => new_url, :type => 'text/directory')
47
+ end
48
+
49
+ def content_tag(tag, content, opts={})
50
+ attrs = opts.inject([]) do |out, tuple|
51
+ k,v = tuple
52
+ out << "#{k}='#{v}'"
53
+ end
54
+ attr_string = attrs.sort.join(' ')
55
+ open_tag = attr_string == '' ? tag : "#{tag} #{attr_string}"
56
+ if [:img].include?(tag)
57
+ "<#{open_tag} />"
58
+ else
59
+ "<#{open_tag}>#{content}</#{tag}>"
60
+ end
61
+ end
62
+
63
+ def image_tag(src, opts={})
64
+ if size = opts.delete(:size)
65
+ opts[:width], opts[:height] = size.split('x')
66
+ end
67
+ opts[:src] = src
68
+ content_tag(:img, nil, opts)
69
+ end
70
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Microformats::Address do
4
+ before(:each) do
5
+ @address = Microformats::Address.new
6
+ end
7
+
8
+ describe "street" do
9
+ it "should wrap the string with street-address" do
10
+ @address.street("123 Main").should == "<span class='street-address' itemprop='street-address'>123 Main</span>"
11
+ end
12
+
13
+ it "should use the given tag" do
14
+ @address.street("123 Main", :tag => :strong).should == "<strong class='street-address' itemprop='street-address'>123 Main</strong>"
15
+ end
16
+ end
17
+
18
+ describe "city" do
19
+ it "should wrap the string with locality" do
20
+ @address.city("Chicago").should == "<span class='locality' itemprop='locality'>Chicago</span>"
21
+ end
22
+
23
+ it "should use the given tag" do
24
+ @address.city("Chicago", :tag => :strong).should == "<strong class='locality' itemprop='locality'>Chicago</strong>"
25
+ end
26
+ end
27
+
28
+ describe "state" do
29
+ it "should wrap the string with region" do
30
+ @address.state("IL").should == "<span class='region' itemprop='region'>IL</span>"
31
+ end
32
+
33
+ it "should use the given tag" do
34
+ @address.state("IL", :tag => :strong).should == "<strong class='region' itemprop='region'>IL</strong>"
35
+ end
36
+ end
37
+
38
+ describe "zip" do
39
+ it "should wrap the string with postal-code" do
40
+ @address.zip("60085").should == "<span class='postal-code' itemprop='postal-code'>60085</span>"
41
+ end
42
+
43
+ it "should use the given tag" do
44
+ @address.zip("60085", :tag => :strong).should == "<strong class='postal-code' itemprop='postal-code'>60085</strong>"
45
+ end
46
+ end
47
+
48
+ describe "country" do
49
+ it "should wrap the string with country-name" do
50
+ @address.country("USA").should == "<span class='country-name' itemprop='country-name'>USA</span>"
51
+ end
52
+
53
+ it "should use the given tag" do
54
+ @address.country("USA", :tag => :strong).should == "<strong class='country-name' itemprop='country-name'>USA</strong>"
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Microformats::Helpers do
4
+ class MyTester
5
+ include Microformats::Helpers
6
+
7
+ def concat(str)
8
+ @output ||= ''
9
+ @output << str
10
+ end
11
+
12
+ def output
13
+ @output
14
+ end
15
+ end
16
+
17
+ before(:each) do
18
+ @tester = MyTester.new
19
+ end
20
+
21
+ describe "vcard" do
22
+ it "should wrap a block in a vcard div" do
23
+ @tester.should_receive(:do_something)
24
+ @tester.vcard do
25
+ @tester.do_something
26
+ end
27
+ @tester.output.should == "<div class='vcard' itemscope='itemscope' itemtype='http://data-vocabulary.org/Person'>\n</div>\n"
28
+ end
29
+ end
30
+
31
+ describe "vcard_address" do
32
+ context "with type" do
33
+ it "should wrap the block in an adr div and output the type" do
34
+ @tester.should_receive(:do_something)
35
+ @tester.vcard_address :type => 'Work' do
36
+ @tester.do_something
37
+ end
38
+ @tester.output.should == "<div class='adr' itemscope='itemscope' itemtype='http://data-vocabulary.org/Address'>\n<span class='type'>Work</span></div>\n"
39
+ end
40
+ end
41
+
42
+ context "without type" do
43
+ it "should wrap the block in an adr div" do
44
+ @tester.should_receive(:do_something)
45
+ @tester.vcard_address do
46
+ @tester.do_something
47
+ end
48
+ @tester.output.should == "<div class='adr' itemscope='itemscope' itemtype='http://data-vocabulary.org/Address'>\n</div>\n"
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'microformats.rb')
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe Microformats::Vcard do
4
+ before(:each) do
5
+ @vcard = Microformats::Vcard.new
6
+ end
7
+
8
+ describe "name" do
9
+ it "should wrap a string with fn class, default to span" do
10
+ @vcard.name("John Doe").should == "<span class='fn' itemprop='name'>John Doe</span>"
11
+ end
12
+
13
+ it "should use the given tag" do
14
+ @vcard.name("John Doe", :tag => :strong).should == "<strong class='fn' itemprop='name'>John Doe</strong>"
15
+ end
16
+ end
17
+
18
+ describe "company" do
19
+ it "should wrap a string with org class, default to span" do
20
+ @vcard.company("Acme Co.").should == "<span class='org' itemprop='affiliation'>Acme Co.</span>"
21
+ end
22
+
23
+ it "should use the given tag" do
24
+ @vcard.company("Acme Co.", :tag => :strong).should == "<strong class='org' itemprop='affiliation'>Acme Co.</strong>"
25
+ end
26
+ end
27
+
28
+ describe "url" do
29
+ it "should default to a tag with url class, using the URL for text and href" do
30
+ @vcard.url("http://google.com").should == "<a class='url' href='http://google.com' itemprop='url'>http://google.com</a>"
31
+ end
32
+
33
+ it "should use given href" do
34
+ @vcard.url('Google', :href => "http://google.com").should == "<a class='url' href='http://google.com' itemprop='url'>Google</a>"
35
+ end
36
+
37
+ it "should use given tag" do
38
+ @vcard.url('http://google.com', :tag => :strong).should == "<strong class='url' itemprop='url'>http://google.com</strong>"
39
+ end
40
+ end
41
+
42
+ describe "photo" do
43
+ it "should create an image tag using the passed string as the src, adding itemprop photo" do
44
+ @vcard.photo("/images/me.png").should == "<img itemprop='photo' src='/images/me.png' />"
45
+ end
46
+
47
+ it "should use :size option to set width and height" do
48
+ @vcard.photo("/images/me.png", :size => "200x100").should == "<img height='100' itemprop='photo' src='/images/me.png' width='200' />"
49
+ end
50
+
51
+ it "should pass through options" do
52
+ @vcard.photo("/images/me.png", :height => 100, :width => 200).should == "<img height='100' itemprop='photo' src='/images/me.png' width='200' />"
53
+ end
54
+
55
+ end
56
+
57
+ describe "phone" do
58
+ it "should wrap string with a tel class" do
59
+ @vcard.phone('123.456.7890').should == "<span class='tel'>123.456.7890</span>"
60
+ end
61
+
62
+ it "should add a type span if given" do
63
+ out = @vcard.phone('123.456.7890', :type => 'Work')
64
+ out.should == "<span class='tel'><span class='type'>Work</span> 123.456.7890</span>"
65
+ end
66
+
67
+ it "should use the given tag" do
68
+ out = @vcard.phone('123.456.7890', :type => 'Work', :tag => :strong)
69
+ out.should == "<strong class='tel'><span class='type'>Work</span> 123.456.7890</strong>"
70
+ end
71
+ end
72
+
73
+ describe "email" do
74
+ it "should wrap string with a email class" do
75
+ @vcard.email('john@doe.com').should == "<span class='email'>john@doe.com</span>"
76
+ end
77
+
78
+ it "should add a type span if given" do
79
+ out = @vcard.email('john@doe.com', :type => 'Work')
80
+ out.should == "<span class='email'><span class='type'>Work</span> john@doe.com</span>"
81
+ end
82
+
83
+ it "should use the given tag" do
84
+ out = @vcard.email('john@doe.com', :type => 'Work', :tag => :strong)
85
+ out.should == "<strong class='email'><span class='type'>Work</span> john@doe.com</strong>"
86
+ end
87
+
88
+ it "should use mailto if using an 'a' tag" do
89
+ out = @vcard.email('john@doe.com', :type => 'Work', :tag => :a)
90
+ out.should == "<a class='email' href='mailto:john@doe.com'><span class='type'>Work</span> john@doe.com</a>"
91
+ end
92
+ end
93
+
94
+ describe "download_link" do
95
+ it "should output a link to h2vx.com using the passed url" do
96
+ out = @vcard.download_link('mydomain.com/page')
97
+ out.should == "<a href='http://h2vx.com/vcf/mydomain.com/page' type='text/directory'>Download vCard</a>"
98
+ end
99
+
100
+ it "should strip the protocol from a passed url" do
101
+ out = @vcard.download_link('http://mydomain.com/page')
102
+ out.should == "<a href='http://h2vx.com/vcf/mydomain.com/page' type='text/directory'>Download vCard</a>"
103
+ end
104
+
105
+ it "should use :text option as text node if present" do
106
+ out = @vcard.download_link('mydomain.com/page', :text => "Download Me Now")
107
+ out.should == "<a href='http://h2vx.com/vcf/mydomain.com/page' type='text/directory'>Download Me Now</a>"
108
+ end
109
+ end
110
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: microformats
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Chris Powers
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-11 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description:
22
+ email: chrisjpowers@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - README.rdoc
31
+ - CHANGELOG.rdoc
32
+ - LICENSE
33
+ - Rakefile
34
+ - lib/microformats.rb
35
+ - lib/address.rb
36
+ - lib/helpers.rb
37
+ - lib/vcard.rb
38
+ - spec/address_spec.rb
39
+ - spec/helpers_spec.rb
40
+ - spec/spec_helper.rb
41
+ - spec/vcard_spec.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/chrisjpowers/microformats
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.3.7
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: The Microformats gem gives you helper methods for richly marking up your HTML with microformats and HTML5 microdata.
76
+ test_files: []
77
+