microformats 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+