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 +3 -1
- data/{README.txt → README.md} +2 -2
- data/Rakefile +1 -0
- data/lib/microformats2.rb +63 -117
- data/test/IndieWebCamp.html +351 -0
- data/test/simple.html +30 -0
- data/test/test_microformats2.rb +13 -12
- metadata +12 -10
data/Manifest.txt
CHANGED
data/{README.txt → README.md}
RENAMED
@@ -14,7 +14,7 @@ Generic Microformats 2 Extractor
|
|
14
14
|
|
15
15
|
## SYNOPSIS
|
16
16
|
|
17
|
-
|
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
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.
|
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
|
16
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
29
|
+
obj = klass.new
|
26
30
|
|
27
|
-
|
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
|
-
|
33
|
+
microformats[constant_name.downcase.to_sym] << obj
|
34
|
+
end
|
35
|
+
end
|
34
36
|
end
|
35
37
|
|
36
|
-
|
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.
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
74
|
-
|
75
|
-
property.
|
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
|
-
|
98
|
-
|
99
|
-
property.attribute("
|
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
|
-
|
122
|
-
|
123
|
-
property.attribute("
|
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
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
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
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
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
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
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&action=edit" />
|
10
|
+
<link rel="edit" title="Edit" href="/wiki/index.php?title=Main_Page&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&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&feed=rss" />
|
16
|
+
<link rel="alternate" type="application/atom+xml" title="IndieWebCamp Atom feed" href="/wiki/index.php?title=Special:RecentChanges&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=-&action=raw&smaxage=0&gen=js&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&redlink=1">Discussion</a> </li>
|
263
|
+
<li id="ca-edit" ><a href="/wiki/index.php?title=Main_Page&action=edit">Edit</a> </li>
|
264
|
+
<li id="ca-history" ><a href="/wiki/index.php?title=Main_Page&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&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&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&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>
|
data/test/test_microformats2.rb
CHANGED
@@ -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
|
-
|
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:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.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-
|
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:
|
42
|
+
hash: 35
|
43
43
|
segments:
|
44
44
|
- 2
|
45
45
|
- 9
|
46
|
-
|
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.
|
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.
|
78
|
+
- README.md
|
77
79
|
require_paths:
|
78
80
|
- lib
|
79
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|