microformats2 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -1,8 +1,10 @@
1
1
  .autotest
2
2
  History.txt
3
3
  Manifest.txt
4
- README.txt
4
+ README.md
5
5
  Rakefile
6
6
  bin/microformats2
7
7
  lib/microformats2.rb
8
8
  test/test_microformats2.rb
9
+ test/simple.html
10
+ test/IndieWebCamp.html
@@ -14,7 +14,7 @@ Generic Microformats 2 Extractor
14
14
 
15
15
  ## SYNOPSIS
16
16
 
17
- Microformats2.parse(File.open("http://iamshane.html"))
17
+ Microformats2.parse(File.open("example.html"))
18
18
 
19
19
  ## REQUIREMENTS
20
20
 
@@ -36,6 +36,6 @@ run the tests/specs, and generate the RDoc.
36
36
 
37
37
  ## LICENSE
38
38
 
39
- PUBLIC DOMAIN.
39
+ **PUBLIC DOMAIN.**
40
40
  Your heart is as free as the air you breathe.
41
41
  The ground you stand on is liberated territory.
data/Rakefile CHANGED
@@ -6,6 +6,7 @@ require 'hoe'
6
6
  Hoe.spec 'microformats2' do
7
7
  developer('Shane Becker', 'veganstraightedge@gmail.com')
8
8
  extra_deps << ['nokogiri', ">= 0"]
9
+ self.readme_file = "README.md"
9
10
  end
10
11
 
11
12
 
data/lib/microformats2.rb CHANGED
@@ -3,37 +3,39 @@ require 'time'
3
3
  require 'date'
4
4
 
5
5
  module Microformats2
6
- VERSION = "1.0.0"
6
+ VERSION = "1.0.1"
7
7
 
8
8
  class LoadError < StandardError; end
9
9
 
10
10
  def self.parse(html)
11
11
  raise LoadError, "argument must be a String or File" unless [String, File].include?(html.class)
12
12
 
13
+ html = html.read if IO === html
14
+
13
15
  doc = Nokogiri::HTML(html)
14
16
  microformats = Hash.new{|hash, key| hash[key] = Array.new}
15
- doc.css("*[class^=h-]").each do |microformat|
16
- constant_name = classify(microformat.attribute("class").to_s.gsub("-","_"))
17
+ doc.css("*[class*=h-]").each do |microformat|
18
+ microformat.attribute("class").to_s.split.each do |mf_class|
19
+ if mf_class =~ /^h-/
20
+ constant_name = mf_class.gsub("-","_").gsub(/^([a-z])/){$1.upcase}.gsub(/_(.)/) { $1.upcase }
17
21
 
18
- if Object.const_defined?(constant_name)
19
- klass = Object.const_get(constant_name)
20
- else
21
- klass = Class.new
22
- Object.const_set constant_name, klass
23
- end
22
+ if Object.const_defined?(constant_name)
23
+ klass = Object.const_get(constant_name)
24
+ else
25
+ klass = Class.new
26
+ Object.const_set constant_name, klass
27
+ end
24
28
 
25
- obj = klass.new
29
+ obj = klass.new
26
30
 
27
- # Add any properties to the object
28
- add_properties(microformat, obj)
29
- add_urls(microformat, obj)
30
- add_dates(microformat, obj)
31
- add_times(microformat, obj)
31
+ add_properties(microformat, obj)
32
32
 
33
- microformats[constant_name.downcase.to_sym] << obj
33
+ microformats[constant_name.downcase.to_sym] << obj
34
+ end
35
+ end
34
36
  end
35
37
 
36
- return microformats
38
+ microformats
37
39
  end
38
40
 
39
41
  def self.add_method(obj, method_name)
@@ -44,122 +46,66 @@ module Microformats2
44
46
  obj
45
47
  end
46
48
 
47
- def self.add_properties(mf, obj)
48
- %w(p n e i).each do |letter|
49
- mf.css("*[class|=#{letter}]").each do |property|
50
- property.attribute("class").to_s.split.each do |css_class|
51
- if css_class =~ /^[pnei]/
52
- css_class = css_class[2..-1].gsub("-","_")
53
- method_name = css_class.gsub("-","_")
54
- value = property.text.gsub(/\n+/, " ").gsub(/\s+/, " ").strip
55
-
56
- add_method(obj, method_name)
57
-
58
- if cur = obj.send(method_name)
59
- if cur.kind_of? Array
60
- cur << value
61
- else
62
- obj.send("#{method_name}=", [cur, value])
63
- end
64
- else
65
- obj.send("#{method_name}=", value)
66
- end
67
- end
68
- end
49
+ def self.populate_method(obj, method_name, value)
50
+ if cur = obj.send(method_name)
51
+ if cur.kind_of? Array
52
+ cur << value
53
+ else
54
+ obj.send("#{method_name}=", [cur, value])
69
55
  end
56
+ else
57
+ obj.send("#{method_name}=", value)
70
58
  end
71
59
  end
72
60
 
73
- def self.add_urls(mf, obj)
74
- mf.css("*[class*=u-]").each do |property|
75
- property.attribute("class").to_s.split.each do |css_class|
76
- if css_class =~ /^u/
77
- css_class = css_class[2..-1].gsub("-","_")
78
- method_name = css_class.gsub("-","_")
79
- value = property.attribute("href").to_s
80
-
81
- add_method(obj, method_name)
82
-
83
- if cur = obj.send(method_name)
84
- if cur.kind_of? Array
85
- cur << value
86
- else
87
- obj.send("#{method_name}=", [cur, value])
88
- end
89
- else
90
- obj.send("#{method_name}=", value)
91
- end
92
- end
93
- end
61
+ class Stripper
62
+ def transform(property)
63
+ property.text.gsub(/\n+/, " ").gsub(/\s+/, " ").strip
94
64
  end
95
65
  end
96
66
 
97
- def self.add_dates(mf, obj)
98
- mf.css("*[class*=d-]").each do |property|
99
- property.attribute("class").to_s.split.each do |css_class|
100
- if css_class =~ /^d/
101
- css_class = css_class[2..-1].gsub("-","_")
102
- method_name = css_class.gsub("-","_")
103
- value = DateTime.parse((property.attribute("title") || property.text).to_s)
104
-
105
- add_method(obj, method_name)
106
-
107
- if cur = obj.send(method_name)
108
- if cur.kind_of? Array
109
- cur << value
110
- else
111
- obj.send("#{method_name}=", [cur, value])
112
- end
113
- else
114
- obj.send("#{method_name}=", value)
115
- end
116
- end
117
- end
67
+ class URL
68
+ def transform(property)
69
+ property.attribute("href").to_s
118
70
  end
119
71
  end
120
72
 
121
- def self.add_times(mf, obj)
122
- mf.css("*[class*=t-]").each do |property|
123
- property.attribute("class").to_s.split.each do |css_class|
124
- if css_class =~ /^t/
125
- css_class = css_class[2..-1].gsub("-","_")
126
- method_name = css_class.gsub("-","_")
127
- value = Time.parse((property.attribute("title") || property.text).to_s)
128
-
129
- add_method(obj, method_name)
130
-
131
- if cur = obj.send(method_name)
132
- if cur.kind_of? Array
133
- cur << value
134
- else
135
- obj.send("#{method_name}=", [cur, value])
136
- end
137
- else
138
- obj.send("#{method_name}=", value)
139
- end
140
- end
141
- end
73
+ class Date
74
+ def transform(property)
75
+ DateTime.parse((property.attribute("title") || property.text).to_s)
142
76
  end
143
77
  end
144
78
 
145
- # Thank you Rails Developers for your unitentional contribution to this project
146
- # File activesupport/lib/active_support/inflector/inflections.rb, line 206
147
- def self.classify(str)
148
- # strip out any leading schema name
149
- camelize(singularize(str.to_s.sub(/.*\./, '')))
79
+ class TimeThingy
80
+ def transform(property)
81
+ Time.parse((property.attribute("title") || property.text).to_s)
82
+ end
150
83
  end
151
84
 
152
- # File activesupport/lib/active_support/inflector/inflections.rb, line 148
153
- def self.singularize(word)
154
- result = word.to_s.dup
155
- end
85
+ FormatClass = {
86
+ "p" => Stripper.new,
87
+ "n" => Stripper.new,
88
+ "e" => Stripper.new,
89
+ "i" => Stripper.new,
90
+ "u" => URL.new,
91
+ "d" => Date.new,
92
+ "t" => TimeThingy.new
93
+ }
156
94
 
157
- # File activesupport/lib/active_support/inflector/methods.rb, line 28
158
- def self.camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
159
- if first_letter_in_uppercase
160
- lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
161
- else
162
- lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1]
95
+ def self.add_properties(mf, obj)
96
+ FormatClass.each do |letter, trans|
97
+ mf.css("*[class*=#{letter}-]").each do |property|
98
+ property.attribute("class").to_s.split.each do |css_class|
99
+ if css_class[0..1] == "#{letter}-"
100
+ css_class = css_class[2..-1].gsub("-","_")
101
+ method_name = css_class.gsub("-","_")
102
+ value = trans.transform(property)
103
+
104
+ add_method(obj, method_name)
105
+ populate_method(obj, method_name, value)
106
+ end
107
+ end
108
+ end
163
109
  end
164
110
  end
165
111
  end
@@ -0,0 +1,351 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
3
+
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
6
+ <meta http-equiv="Content-Style-Type" content="text/css" />
7
+ <meta name="generator" content="MediaWiki 1.15.4" />
8
+ <meta name="keywords" content="Main Page,Guest List,Schedule,Projects,Sessions,Planning,Issues,Why,Contribute,why,Session Notes" />
9
+ <link rel="alternate" type="application/x-wiki" title="Edit" href="/wiki/index.php?title=Main_Page&amp;action=edit" />
10
+ <link rel="edit" title="Edit" href="/wiki/index.php?title=Main_Page&amp;action=edit" />
11
+ <link rel="shortcut icon" href="/favicon.ico" />
12
+ <link rel="search" type="application/opensearchdescription+xml" href="/wiki/opensearch_desc.php" title="IndieWebCamp (en)" />
13
+ <link title="Creative Commons" type="application/rdf+xml" href="/wiki/index.php?title=Main_Page&amp;action=creativecommons" rel="meta" />
14
+ <link rel="copyright" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" />
15
+ <link rel="alternate" type="application/rss+xml" title="IndieWebCamp RSS feed" href="/wiki/index.php?title=Special:RecentChanges&amp;feed=rss" />
16
+ <link rel="alternate" type="application/atom+xml" title="IndieWebCamp Atom feed" href="/wiki/index.php?title=Special:RecentChanges&amp;feed=atom" />
17
+ <title>IndieWebCamp</title>
18
+ <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "/wiki/skins/indieweb/gumax_main.css?207"; /*]]>*/</style>
19
+ <link rel="stylesheet" type="text/css" media="print" href="/wiki/skins/common/commonPrint.css?207" />
20
+ <link rel="stylesheet" type="text/css" media="handheld" href="/wiki/skins/indieweb/handheld.css?207" />
21
+ <link rel="stylesheet" type="text/css" media="print" href="/wiki/skins/indieweb/print.css?207" />
22
+ <!--[if lt IE 5.5000]><style type="text/css">@import "/wiki/skins/indieweb/IE50Fixes.css?207";</style><![endif]-->
23
+ <!--[if IE 5.5000]><style type="text/css">@import "/wiki/skins/indieweb/IE55Fixes.css?207";</style><![endif]-->
24
+ <!--[if IE 6]><style type="text/css">@import "/wiki/skins/indieweb/IE60Fixes.css?207";</style><![endif]-->
25
+ <!--[if IE 7]><style type="text/css">@import "/wiki/skins/indieweb/IE70Fixes.css?207";</style><![endif]-->
26
+ <!--[if lt IE 7]><script type="text/javascript" src="/wiki/skins/common/IEFixes.js?207"></script>
27
+ <meta http-equiv="imagetoolbar" content="no" /><![endif]-->
28
+ <meta property="og:title" content="IndieWebCamp" />
29
+ <meta property="og:type" content="event" />
30
+ <meta property="og:url" content="http://indiewebcamp.com" />
31
+ <meta property="og:image" content="http://indiewebcamp.com/wiki/skins/indieweb/images/indiewebcamp_logo_color.png" />
32
+ <meta property="og:site_name" content="IndieWebCamp" />
33
+ <meta property="fb:admins" content="11500459,31600719,214611" />
34
+ <script language="javascript" type="text/javascript" src="/files/jquery.js"></script>
35
+ <script type= "text/javascript">/*<![CDATA[*/
36
+ var skin = "IndieWeb";
37
+ var stylepath = "/wiki/skins";
38
+ var wgArticlePath = "/$1";
39
+ var wgScriptPath = "/wiki";
40
+ var wgScript = "/wiki/index.php";
41
+ var wgVariantArticlePath = false;
42
+ var wgActionPaths = {};
43
+ var wgServer = "http://indiewebcamp.com";
44
+ var wgCanonicalNamespace = "";
45
+ var wgCanonicalSpecialPageName = false;
46
+ var wgNamespaceNumber = 0;
47
+ var wgPageName = "Main_Page";
48
+ var wgTitle = "Main Page";
49
+ var wgAction = "view";
50
+ var wgArticleId = "1";
51
+ var wgIsArticle = true;
52
+ var wgUserName = "Iamshane.com";
53
+ var wgUserGroups = ["*", "user", "autoconfirmed"];
54
+ var wgUserLanguage = "en";
55
+ var wgContentLanguage = "en";
56
+ var wgBreakFrames = false;
57
+ var wgCurRevisionId = 428;
58
+ var wgVersion = "1.15.4";
59
+ var wgEnableAPI = true;
60
+ var wgEnableWriteAPI = true;
61
+ var wgSeparatorTransformTable = ["", ""];
62
+ var wgDigitTransformTable = ["", ""];
63
+ var wgRestrictionEdit = [];
64
+ var wgRestrictionMove = [];
65
+ var wgAjaxWatch = {"watchMsg": "Watch", "unwatchMsg": "Unwatch", "watchingMsg": "Watching...", "unwatchingMsg": "Unwatching..."};
66
+ /*]]>*/</script>
67
+
68
+ <script type="text/javascript" src="/wiki/skins/common/wikibits.js?207"><!-- wikibits js --></script>
69
+ <script type="text/javascript" src="/wiki/index.php?title=-&amp;action=raw&amp;smaxage=0&amp;gen=js&amp;useskin=IndieWeb"><!-- site js --></script>
70
+ <!-- Head Scripts -->
71
+ <script type="text/javascript" src="/wiki/skins/common/ajax.js?207"></script>
72
+ <script type="text/javascript" src="/wiki/skins/common/ajaxwatch.js?207"></script>
73
+ <style type="text/css">/*<![CDATA[*/ .firstHeading, .subtitle, #siteSub, #contentSub, .pagetitle { display:none; } /*]]>*/</style>
74
+ </head>
75
+
76
+ <body class="mediawiki ltr ns-0 ns-subject page-Main_Page">
77
+
78
+ <div class="gumax-center" align="center">
79
+ <div id="gumax-rbox" align="left">
80
+ <div class="gumax-rbroundbox"><div class="gumax-rbtop"><div><div>
81
+ <a href="/" class="headContent"><h1>IndieWebCamp</h1></a>
82
+ </div></div></div>
83
+ <div class="gumax-rbcontentwrap"><div class="gumax-rbcontent">
84
+
85
+ <!-- =================== gumax-page =================== -->
86
+ <div id="gumax-page">
87
+
88
+ <!-- ===== Header ===== -->
89
+ <div id="gumax-header">
90
+ <div id="header-text"> IndieWebCamp is a 2-day dev camp in Portland, Oregon focused on building a more open Web.</div>
91
+ <a id="topHeader"></a>
92
+
93
+ <!-- Search -->
94
+ <!--
95
+ <div id="gumax-p-search" class="gumax-portlet">
96
+ <div id="gumax-searchBody" class="gumax-pBody">
97
+ <form action="/Special:Search" id="searchform"><div>
98
+ <input id="searchInput" name="search" type="text" accesskey="f" value="" />
99
+ <input type='submit' name="go" class="searchButton" id="searchGoButton" value="Go" />
100
+ <input type='submit' name="fulltext" class="searchButton" id="mw-searchButton" value="Search" />
101
+ </div></form>
102
+ </div>
103
+ </div> --> <!-- end of gumax-p-search DIV -->
104
+ <!-- end of Search -->
105
+
106
+ </div> <!-- end of header DIV -->
107
+ <!-- ===== end of Header ===== -->
108
+
109
+ <!-- ===== Content body ===== -->
110
+ <div id="gumax-content-body">
111
+
112
+ <table id="gumax-content-body-table"><tr><td class="gumax-content-left">
113
+ <!-- Navigation Menu -->
114
+ <div id="gumax-p-navigation-wrapper">
115
+
116
+ <div class='gumax-portlet' id='p-navigation'>
117
+ <h5>Navigation</h5>
118
+ <div class="gumax-p-navigation">
119
+ <ul>
120
+ <li id="n-mainpage-description"><a href="/Main_Page">Main page</a></li>
121
+ <li id="n-Log-in-with-your-OpenID"><a href="/Special:OpenIDLogin">Log in with your OpenID</a></li>
122
+ <li id="n-Guest-List"><a href="/Guest_List">Guest List</a></li>
123
+ <li id="n-Schedule"><a href="/Schedule">Schedule</a></li>
124
+ <li id="n-Sessions"><a href="/Sessions">Sessions</a></li>
125
+ <li id="n-Sponsors"><a href="/Sponsors">Sponsors</a></li>
126
+ <li id="n-recentchanges"><a href="/Special:RecentChanges">Recent changes</a></li>
127
+ </ul>
128
+ </div>
129
+ </div>
130
+ <div class='gumax-portlet' id='p-Resources'>
131
+ <h5>Resources</h5>
132
+ <div class="gumax-p-navigation">
133
+ <ul>
134
+ <li id="n-Projects"><a href="/Projects">Projects</a></li>
135
+ <li id="n-Set-up-your-domain"><a href="/How_to_set_up_OpenID_on_your_own_domain">Set up your domain</a></li>
136
+ <li id="n-search"><a href="/Special:Search">Search</a></li>
137
+ </ul>
138
+ </div>
139
+ </div>
140
+
141
+ <div class="gumax-portlet" id="p-Links">
142
+ <div class="gumax-p-navigation banners">
143
+ <ul style="border: 0;">
144
+ <li style="border: 0; margin-top: 20px;">
145
+ <a href="/Sponsors"><img src="http://indiewebcamp.com/wiki/images/thumb/1/1f/ualogo.png/160px-ualogo.png" alt="Urban Airship" border="0" width="160" /></a>
146
+ </li>
147
+ <li style="border: 0; margin-top: 20px;">
148
+ <a href="/Sponsors"><img src="http://indiewebcamp.com/wiki/images/thumb/4/41/tropologo-vert.png/110px-tropologo-vert.png" alt="Tropo" border="0" width="110" /></a>
149
+ </li>
150
+ <li style="border: 0; margin-top: 20px;">
151
+ <a href="/Sponsors"><img src="http://indiewebcamp.com/wiki/images/5/54/wklogo.png" alt="Wieden+Kennedy" border="0" width="157" /></a>
152
+ </li>
153
+ </ul>
154
+ </div>
155
+ </div>
156
+
157
+
158
+ </div>
159
+ <!-- end of Navigation Menu -->
160
+
161
+ </td><td class="gumax-content-right"> <!-- Main Content TD -->
162
+
163
+ <!-- Main Content -->
164
+ <div id="content">
165
+
166
+ <a name="top" id="top"></a>
167
+ <h1 class="firstHeading">Main Page</h1>
168
+ <div id= "bodyContent" class="gumax-bodyContent">
169
+ <div id="contentSub"></div>
170
+ <!-- start content -->
171
+ <p><br />
172
+ </p>
173
+ <div class="vevent h-event">
174
+ <table id="toc" class="toc" summary="Contents"><tr><td><div id="toctitle"><h2>Contents</h2></div>
175
+ <ul>
176
+ <li class="toclevel-1"><a href="#IndieWebCamp"><span class="tocnumber">1</span> <span class="toctext">IndieWebCamp</span></a></li>
177
+ <li class="toclevel-1"><a href="#Session_Notes"><span class="tocnumber">2</span> <span class="toctext">Session Notes</span></a></li>
178
+ <li class="toclevel-1"><a href="#When"><span class="tocnumber">3</span> <span class="toctext">When</span></a></li>
179
+ <li class="toclevel-1"><a href="#Where"><span class="tocnumber">4</span> <span class="toctext">Where</span></a>
180
+ <ul>
181
+ <li class="toclevel-2"><a href="#Travel"><span class="tocnumber">4.1</span> <span class="toctext">Travel</span></a></li>
182
+ </ul>
183
+ </li>
184
+ <li class="toclevel-1"><a href="#Who"><span class="tocnumber">5</span> <span class="toctext">Who</span></a></li>
185
+ <li class="toclevel-1"><a href="#What"><span class="tocnumber">6</span> <span class="toctext">What</span></a></li>
186
+ <li class="toclevel-1"><a href="#Why"><span class="tocnumber">7</span> <span class="toctext">Why</span></a></li>
187
+ <li class="toclevel-1"><a href="#How"><span class="tocnumber">8</span> <span class="toctext">How</span></a></li>
188
+ <li class="toclevel-1"><a href="#More"><span class="tocnumber">9</span> <span class="toctext">More</span></a></li>
189
+ </ul>
190
+ </td></tr></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
191
+ <a name="IndieWebCamp" id="IndieWebCamp"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: IndieWebCamp">edit</a>]</span> <span class="mw-headline"> <span class="summary p-summary p-name">IndieWebCamp</span> </span></h2>
192
+ <div class="description p-description">
193
+ <p>Rather than posting content on many third-party silos of data, we should all begin owning the data we're creating. Publish short status updates on your own domain, and syndicate to Twitter. Publish photos on your own domain, syndicate to Flickr, etc, etc.
194
+ </p><p>This is the basis of the "Indie Web" movement (see <a href="/why" title="why">why</a> for more). We'll get together for a weekend to talk about what has been done in the field, and what still needs to be done. There will be workshops and breakout sessions.
195
+ </p>
196
+ </div>
197
+ <p><a href="/Planning" title="Planning">Planners</a>: <span class="organizer vcard p-organizer h-card"><span class="fn"><a href="http://tantek.com" class="external text" title="http://tantek.com">Tantek Çelik</a></span></span>, <span class="organizer vcard p-organizer h-card"><span class="fn"><a href="http://aaron.pk" class="external text" title="http://aaron.pk">Aaron Parecki</a></span></span>, <span class="organizer vcard p-organizer h-card"><span class="fn"><a href="http://caseorganic.com" class="external text" title="http://caseorganic.com">Amber Case</a></span></span>, and <span class="organizer vcard p-organizer h-card"><span class="fn"><a href="http://skinnywhitegirl.com" class="external text" title="http://skinnywhitegirl.com">Crystal Beasley</a></span></span>. Want to help? <a href="/Planning" title="Planning">Sign up to volunteer!</a>.
198
+ </p>
199
+ <a name="Session_Notes" id="Session_Notes"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=2" title="Edit section: Session Notes">edit</a>]</span> <span class="mw-headline"> Session Notes </span></h2>
200
+ <p>See the <b><a href="/Schedule" title="Schedule">Schedule</a></b> to read and add session notes. Click on the session title to add notes to the page. To see all session notes, see <b><a href="/Category:Session_Notes" title="Category:Session Notes">Category:Session Notes</a></b>
201
+ </p>
202
+ <a name="When" id="When"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=3" title="Edit section: When">edit</a>]</span> <span class="mw-headline"> When </span></h2>
203
+ <p>IndieWebCamp was on <span class="dtstart d-start">2011-06-25</span> and <span class="dtend d-end">2011-06-26</span>. See the <a href="/Schedule" title="Schedule">Schedule</a> for more details. Note: <a href="http://opensourcebridge.org/" class="external text" title="http://opensourcebridge.org/">OSBridge</a> was June 21-24 immediately beforehand, consider attending that as well.
204
+ </p>
205
+ <a name="Where" id="Where"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=4" title="Edit section: Where">edit</a>]</span> <span class="mw-headline"> Where </span></h2>
206
+ <p><b><span class="location vcard p-location h-card"><span class="fn org p-name p-org">Urban Airship</span>, <span class="adr p-adr"><a href="http://maps.google.com/maps?q=334+NW+11th+Ave.,+Portland,+Oregon" class="external text" title="http://maps.google.com/maps?q=334+NW+11th+Ave.,+Portland,+Oregon">334 NW 11th Ave., Portland, Oregon</a></span></span></b>.
207
+ </p><p><a href="http://urbanairship.com/company/" class="external text" title="http://urbanairship.com/company/">Urban Airship</a> is graciously providing the space for IndieWebCamp.
208
+ </p>
209
+ <a name="Travel" id="Travel"></a><h3><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=5" title="Edit section: Travel">edit</a>]</span> <span class="mw-headline"> Travel </span></h3>
210
+ <p>Flights: If you're flying from the SF/Bay Area to Portland (PDX), Alaska Airlines and Southwest Airlines are recommended and have frequent flights to PDX.
211
+ </p>
212
+ <a name="Who" id="Who"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=6" title="Edit section: Who">edit</a>]</span> <span class="mw-headline"> Who </span></h2>
213
+ <p>To get on the <a href="/Guest_List" title="Guest List">guest list</a>, <a href="/Special:OpenIDLogin" title="Special:OpenIDLogin">log in</a> to this wiki with your personal OpenID and <a href="/Guest_List" title="Guest List">add yourself</a>!
214
+ </p><p><i>IndieWebCamp is for active builders only in order to focus the limited time we have on productive real world discussions and code/design/ux sharing that will help us move forward.</i>
215
+ </p><p>Attendees must have a personal URL enabled with OpenID, or be an apprentice to someone who has one in order to attend.
216
+ </p>
217
+ </div>
218
+ <a name="What" id="What"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=7" title="Edit section: What">edit</a>]</span> <span class="mw-headline"> What </span></h2>
219
+ <ul><li> <a href="/Projects" title="Projects">Projects</a>
220
+ </li><li> <a href="/Sessions" title="Sessions">Sessions</a>
221
+ </li></ul>
222
+ <a name="Why" id="Why"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=8" title="Edit section: Why">edit</a>]</span> <span class="mw-headline"> Why </span></h2>
223
+ <ul><li> <a href="/Why" title="Why">Why</a>
224
+ </li></ul>
225
+ <a name="How" id="How"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=9" title="Edit section: How">edit</a>]</span> <span class="mw-headline"> How </span></h2>
226
+ <ul><li> How to <a href="/Contribute" title="Contribute">Contribute</a>
227
+ </li></ul>
228
+ <a name="More" id="More"></a><h2><span class="editsection">[<a href="/wiki/index.php?title=Main_Page&amp;action=edit&amp;section=10" title="Edit section: More">edit</a>]</span> <span class="mw-headline"> More </span></h2>
229
+ <ul><li> <a href="/Issues" title="Issues">Issues</a> - any problems with the wiki, the website, or anything else to do with IndiWebCamp
230
+ </li><li> <a href="/Planning" title="Planning">Planning</a> - want to help out with IndieWebCamp? <a href="/Planning" title="Planning">Volunteer!</a>.
231
+ </li><li> <a href="irc://irc.freenode.net/indiewebcamp" class="external free" title="irc://irc.freenode.net/indiewebcamp">irc://irc.freenode.net/indiewebcamp</a>
232
+ </li></ul>
233
+
234
+ <!--
235
+ NewPP limit report
236
+ Preprocessor node count: 50/1000000
237
+ Post-expand include size: 0/2097152 bytes
238
+ Template argument size: 0/2097152 bytes
239
+ Expensive parser function count: 0/100
240
+ -->
241
+
242
+ <!-- Saved in parser cache with key indiewebcamp:pcache:idhash:1-0!1!0!!en!2 and timestamp 20110627011606 -->
243
+ <div class="printfooter">
244
+ Retrieved from "<a href="http://indiewebcamp.com/Main_Page">http://indiewebcamp.com/Main_Page</a>"</div>
245
+ <!-- end content -->
246
+ <div class="visualClear"></div>
247
+ </div>
248
+ </div>
249
+ <!-- end of Main Content -->
250
+ </td></tr></table>
251
+ </div>
252
+ <!-- ===== end of Content body ===== -->
253
+
254
+ </div> <!-- end of gumax-page DIV -->
255
+ <!-- =================== end of gumax-page =================== -->
256
+
257
+ <!-- ===== gumax-page-actions ===== -->
258
+ <div id="gumax-page-actions">
259
+ <div id="gumax-content-actions">
260
+ <ul>
261
+ <li id="ca-nstab-main" class="selected" ><a href="/Main_Page">Page</a> </li>
262
+ <li id="ca-talk" class="new" ><a href="/wiki/index.php?title=Talk:Main_Page&amp;action=edit&amp;redlink=1">Discussion</a> </li>
263
+ <li id="ca-edit" ><a href="/wiki/index.php?title=Main_Page&amp;action=edit">Edit</a> </li>
264
+ <li id="ca-history" ><a href="/wiki/index.php?title=Main_Page&amp;action=history">History</a> </li>
265
+ <li id="ca-move" ><a href="/Special:MovePage/Main_Page">Move</a> </li>
266
+ <li id="ca-watch" ><a href="/wiki/index.php?title=Main_Page&amp;action=watch">Watch</a> </li>
267
+
268
+ <!-- show back to top link only if the body is longer than the window height -->
269
+ <!--
270
+ <script type="text/javascript">
271
+ var winheight = parseInt(document.documentElement.clientHeight)
272
+ var boheight = parseInt(document.body.clientHeight)
273
+ if(winheight <= boheight) {
274
+ document.write('<li><a href="#" onclick="window.scrollTo(0,0);return false;" title="Back to the top of the page">Back to top</a></li>');
275
+ }
276
+ </script>
277
+ -->
278
+ <!-- end of show back to top link only -->
279
+
280
+ </ul>
281
+ </div>
282
+ </div>
283
+ <!-- ===== end of gumax-page-actions ===== -->
284
+
285
+ <!-- =================== gumax-page-footer =================== -->
286
+ <div id="gumax-page-footer">
287
+
288
+ <!-- personal tools -->
289
+ <div id="gumax-personal-tools">
290
+ <ul>
291
+ <li id="t-upload"><a href="/Special:Upload">Upload file</a> | </li>
292
+ <li id="t-specialpages"><a href="/Special:SpecialPages">Special pages</a> </li>
293
+ <li id="t-permalink"> | <a href="/wiki/index.php?title=Main_Page&amp;oldid=428">Permanent link</a></li>
294
+ </ul>
295
+
296
+
297
+ <!-- Login -->
298
+ <div id="gumax-footer-login">
299
+ <ul>
300
+ <li id="gumax-pt-userpage"><a href="/User:Iamshane.com">Iamshane.com</a>
301
+ |</li>
302
+ <li id="gumax-pt-mytalk"><a href="/User_talk:Iamshane.com" class="new">My talk</a>
303
+ |</li>
304
+ <li id="gumax-pt-preferences"><a href="/Special:Preferences">My preferences</a>
305
+ |</li>
306
+ <li id="gumax-pt-watchlist"><a href="/Special:Watchlist">My watchlist</a>
307
+ |</li>
308
+ <li id="gumax-pt-mycontris"><a href="/Special:Contributions/Iamshane.com">My contributions</a>
309
+ |</li>
310
+ <li id="gumax-pt-logout"><a href="/wiki/index.php?title=Special:UserLogout&amp;returnto=Main_Page">Log out</a>
311
+ </li>
312
+ </ul>
313
+ </div>
314
+ <!-- end of Login -->
315
+
316
+ </div> <!-- end of personal-tools DIV -->
317
+ <!-- end of personal tools -->
318
+
319
+ <!-- gumax-footer -->
320
+ <div id="gumax-footer">
321
+ <div id="gumax-f-message">
322
+ <span id="f-lastmod"> This page was last modified on 26 June 2011, at 18:16.</span>
323
+ <span id="f-viewcount">This page has been accessed 23,017 times. </span>
324
+ </div>
325
+ </div>
326
+ <!-- end of gumax-footer -->
327
+
328
+ <script type="text/javascript">if (window.runOnloadHook) runOnloadHook();</script>
329
+ </div>
330
+ <!-- =================== end of gumax-page-footer =================== -->
331
+
332
+ </div></div>
333
+ <div class="gumax-rbbot"><div><div></div></div></div></div>
334
+ </div>
335
+ </div>
336
+
337
+ <!-- Served in 0.136 secs. --><script type="text/javascript">
338
+
339
+ var _gaq = _gaq || [];
340
+ _gaq.push(['_setAccount', 'UA-16359758-21']);
341
+ _gaq.push(['_trackPageview']);
342
+
343
+ (function() {
344
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
345
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
346
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
347
+ })();
348
+
349
+ </script>
350
+
351
+ </body></html>
data/test/simple.html ADDED
@@ -0,0 +1,30 @@
1
+ <html>
2
+ <head>
3
+ <title>Simple hCard</title>
4
+ </head>
5
+
6
+ <body>
7
+ <h1 class="h-card">
8
+ <a class="p-fn u-url" href="http://factoryjoe.com/">
9
+ <span class="foxtrot echo niner p-given-name">Chris</span>
10
+ <abbr class="p-additional-name">R.</abbr>
11
+ <span class="p-family-name">Messina</span>
12
+ </a>
13
+ </h1>
14
+
15
+ <h1 class="panda h-card">
16
+ <a class="p-fn u-url" href="http://iamshane.com">
17
+ <span class="p-given-name">Shane</span>
18
+ <abbr class="p-additional-name">B</abbr>
19
+ <span class="p-family-name">Becker</span>
20
+ </a>
21
+ </h1>
22
+
23
+ <h1 class="h-mitch">
24
+ <a class="p-snap" href="http://iamshane.com">
25
+ <span class="p-krackle">Breakfast</span>
26
+ <span class="p-pop">Cereal</span>
27
+ </a>
28
+ </h1>
29
+ </body>
30
+ </html>
@@ -19,19 +19,20 @@ class TestMicroformats2 < Test::Unit::TestCase
19
19
  end
20
20
 
21
21
  def test_extracts_hcard_from_an_html_file
22
- hcard = <<-END
23
- <html>
24
- <head>
25
- <title>Simple hCard</title>
26
- </head>
27
-
28
- <body>
29
- <h1 class="h-card">Chris</h1>
30
- </body>
31
- </html>
32
- END
33
- result = Microformats2.parse(File.open(File.join(File.dirname(__FILE__), "hcard.html")))
22
+ result = Microformats2.parse(File.open(File.join(File.dirname(__FILE__), "simple.html")))
34
23
  assert_equal HCard, result[:hcard].first.class
24
+ assert_equal 2, result[:hcard].length
25
+ end
26
+
27
+ def test_extracts_name_from_tag_with_multiple_classes
28
+ result = Microformats2.parse(File.open(File.join(File.dirname(__FILE__), "simple.html")))
29
+ assert_equal "Chris", result[:hcard].first.given_name
30
+ end
31
+
32
+ def test_extracts_hcalendar_from_an_html_file
33
+ result = Microformats2.parse(File.open(File.join(File.dirname(__FILE__), "IndieWebCamp.html")))
34
+ assert_equal 1, result[:hevent].length
35
+ assert result[:hcard].map { |h| h.name }.include?("Urban Airship")
35
36
  end
36
37
 
37
38
  def test_extracts_hcard_from_html
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: microformats2
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 0
10
- version: 1.0.0
9
+ - 1
10
+ version: 1.0.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Shane Becker
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-25 00:00:00 Z
18
+ date: 2011-06-29 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: nokogiri
@@ -37,13 +37,14 @@ dependencies:
37
37
  requirement: &id002 !ruby/object:Gem::Requirement
38
38
  none: false
39
39
  requirements:
40
- - - ~>
40
+ - - ">="
41
41
  - !ruby/object:Gem::Version
42
- hash: 17
42
+ hash: 35
43
43
  segments:
44
44
  - 2
45
45
  - 9
46
- version: "2.9"
46
+ - 4
47
+ version: 2.9.4
47
48
  type: :development
48
49
  version_requirements: *id002
49
50
  description: Generic Microformats 2 Extractor
@@ -56,16 +57,17 @@ extensions: []
56
57
  extra_rdoc_files:
57
58
  - History.txt
58
59
  - Manifest.txt
59
- - README.txt
60
60
  files:
61
61
  - .autotest
62
62
  - History.txt
63
63
  - Manifest.txt
64
- - README.txt
64
+ - README.md
65
65
  - Rakefile
66
66
  - bin/microformats2
67
67
  - lib/microformats2.rb
68
68
  - test/test_microformats2.rb
69
+ - test/simple.html
70
+ - test/IndieWebCamp.html
69
71
  - .gemtest
70
72
  homepage: http://github.com/veganstraightedge/microformats2
71
73
  licenses: []
@@ -73,7 +75,7 @@ licenses: []
73
75
  post_install_message:
74
76
  rdoc_options:
75
77
  - --main
76
- - README.txt
78
+ - README.md
77
79
  require_paths:
78
80
  - lib
79
81
  required_ruby_version: !ruby/object:Gem::Requirement