Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…5f17-0410-80e1-b267258107f6
  • Loading branch information
danwebb committed Feb 8, 2007
1 parent 0d661c8 commit 1324dd9
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 37 deletions.
12 changes: 11 additions & 1 deletion hcard.js
@@ -1,11 +1,21 @@
var HCard = Microformat.define('vcard', { var HCard = Microformat.define('vcard', {
one : ['fn', 'bday', 'tz', 'sort-string', 'uid', 'class', { one : ['bday', 'tz', 'sort-string', 'uid', 'class', {
'n' : { 'n' : {
one : ['family-name', 'given-name', 'additional-name'], one : ['family-name', 'given-name', 'additional-name'],
many : ['honorific-prefix', 'honorific-suffix'] many : ['honorific-prefix', 'honorific-suffix']
}, },
'geo' : { 'geo' : {
one : ['latitude', 'longitude'] one : ['latitude', 'longitude']
},
// inferred n from fn special case
'fn' : function(node, data) {
var fn = this._extractData(node, 'simple');
if (m = fn.match(/^(\w+) (\w+)$/)) {
data.n = data.n || {};
data.n.givenName = data.n.givenName || m[1];
data.n.familyName = data.n.familyName || m[2];
}
return fn;
} }
}], }],
many : ['label', 'sound', 'title', 'role', 'key', 'mailer', 'rev', 'nickname', 'category', 'note', { many : ['label', 'sound', 'title', 'role', 'key', 'mailer', 'rev', 'nickname', 'category', 'note', {
Expand Down
5 changes: 5 additions & 0 deletions hreview.js
@@ -0,0 +1,5 @@
HReview = Microformat.define('hreview', {
one : ['version', 'summary', 'type', 'dtreviewed', 'rating', 'description', { 'reviewer' : HCard }, {
item : { one : ['fn'] }
}]
});
90 changes: 56 additions & 34 deletions microformat.js
@@ -1,3 +1,18 @@
// Generic Microformat Parser v0.1 Dan Webb (dan@danwebb.net)
// Licenced under the MIT Licence
//
// var people = HCard.discover();
// people[0].fn => 'Dan Webb'
// people[0].urlList => ['http://danwebb.net', 'http://eventwax.com']
//
// TODO
//
// Fix _propFor to work with old safari
// Find and use unit testing framework on microformats.org test cases
// More formats: HFeed, HEntry, HAtom, RelTag, XFN?


// JavaScript 1.6 Iterators and generics cross-browser
if (!Array.prototype.forEach) { if (!Array.prototype.forEach) {
Array.prototype.forEach = function(func, scope) { Array.prototype.forEach = function(func, scope) {
scope = scope || this; scope = scope || this;
Expand Down Expand Up @@ -32,6 +47,7 @@ if (!Array.prototype.filter) {
} }
}); });


// Main Microformat namespace
Microformat = { Microformat = {
define : function(name, spec) { define : function(name, spec) {
var mf = function(node, data) { var mf = function(node, data) {
Expand All @@ -56,51 +72,54 @@ Microformat = {
}, },
_parse : function(format, node) { _parse : function(format, node) {
var data = {}; var data = {};
Microformat.extend(data, this._parseOne(format, node)); this._process(data, format.one, node, true);
Microformat.extend(data, this._parseMany(format, node)); this._process(data, format.many, node);
return data; return data;
}, },
_parseOne : function(format, context) { _process : function(data, format, context, firstOnly) {
var ones = {}, node; var selection, first;
format.one.forEach(function(item) { format = format || [];
if (typeof item == 'string') { format.forEach(function(item) {
if (node = Microformat.$$(item, context)[0])
ones[this._propFor(item)] = this._extractData(node, 'simple');
} else {
for (var cls in item)
if (node = Microformat.$$(cls, context)[0]) {
ones[this._propFor(cls)] = this._extractData(node, item[cls]);
}
}
}, this);
return ones;
},
_parseMany : function(format, context) {
var manies = {}, nodes;
format.many.forEach(function(item) {
if (typeof item == 'string') { if (typeof item == 'string') {
nodes = Microformat.$$(item, context); selection = Microformat.$$(item, context);
if (nodes.length > 0) manies[this._propFor(item) + 'List'] = nodes.map(function(node) {
return this._extractData(node, 'simple'); if (firstOnly && (first = selection[0])) {
}, this); data[this._propFor(item)] = this._extractData(first, 'simple', data);
} else { } else if (selection.length > 0) {
nodes = Microformat.$$(cls, context); data[this._propFor(item) + 'List'] = selection.map(function(node) {
for (var cls in item) { return this._extractData(node, 'simple', data);
nodes = Microformat.$$(item[cls], context);
if (nodes.length > 0) manies[this._propFor(cls + 'List')] = nodes.map(function(node) {
return this._extractData(node, item[cls]);
}, this); }, this);
} }

} else {

for (var cls in item) {
selection = Microformat.$$(cls, context);

if (firstOnly && (first = selection[0])) {
data[this._propFor(cls)] = this._extractData(first, item[cls], data);
} else if (selection.length > 0) {
data[this._propFor(cls + 'List')] = selection.map(function(node) {
return this._extractData(node, item[cls], data);
}, this);
}
}

} }

}, this); }, this);
return manies; return data;
}, },
_extractData : function(node, dataType) { _extractData : function(node, dataType, data) {
if (typeof dataType == 'function') return dataType.call(this, node, data);

switch (dataType) { switch (dataType) {
case 'simple': return this._extractSimple(node); case 'simple': return this._extractSimple(node);
case 'url': return this._extractURL(node); case 'url': return this._extractURL(node);
} }
return this._parse(dataType, node);
if (dataType._parse) return dataType._parse(dataType.format, node);
else return this._parse(dataType, node);
}, },
_extractURL : function(node) { _extractURL : function(node) {
var href; var href;
Expand All @@ -112,7 +131,7 @@ Microformat = {
case 'object': href = node.data; case 'object': href = node.data;
} }
if (href) { if (href) {
if (href.indexOf('mailto:') == 1) if (href.indexOf('mailto:') == 0)
href = href.replace(/^mailto:/, '').replace(/\?.*$/, ''); href = href.replace(/^mailto:/, '').replace(/\?.*$/, '');
return href; return href;
} }
Expand Down Expand Up @@ -153,6 +172,7 @@ Microformat = {
if (this.handlers[prop]) this.handlers[prop].call(this, item, data); if (this.handlers[prop]) this.handlers[prop].call(this, item, data);
} }
}, },
// In built getElementsByClassName
$$ : function(className, context) { $$ : function(className, context) {
context = context || document; context = context || document;
var nodeList; var nodeList;
Expand All @@ -171,9 +191,11 @@ Microformat = {
var re = new RegExp('(^|\\s)' + className + '(\\s|$)'); var re = new RegExp('(^|\\s)' + className + '(\\s|$)');
return Array.filter(nodeList, function(node) { return node.className.match(re) }); return Array.filter(nodeList, function(node) { return node.className.match(re) });
}, },
// In built Object.extend equivilent
extend : function(dest, source) { extend : function(dest, source) {
for (var prop in source) dest[prop] = source[prop]; for (var prop in source) dest[prop] = source[prop];
return dest; return dest;
}, },
// methods available to all instances of a microformat
Base : {} Base : {}
}; };
29 changes: 27 additions & 2 deletions test/test.html
Expand Up @@ -9,19 +9,24 @@
<script src="../microformat.js"></script> <script src="../microformat.js"></script>
<script src="../hcard.js"></script> <script src="../hcard.js"></script>
<script src="../hcalendar.js"></script> <script src="../hcalendar.js"></script>
<script src="../hreview.js"></script>
</head> </head>


<body> <body>
<h1>Thing</h1> <h1>Thing</h1>
<div id="bung"> <div id="bung">
<h1>Microformat Parsing Tests</h1>

<h2>hCards</h2>
<div class="vcard"> <div class="vcard">
<h2><a href="http://danwebb.net" class="fn n url"><span class="given-name">Dan</span> <span class="family-name">Webb</span></a> <em class="role">Developer</em> <em class="role">Director</em></h2> <h3><a href="http://danwebb.net" class="fn n url"><span class="given-name">Dan</span> <span class="family-name">Webb</span></a> <em class="role">Developer</em> <em class="role">Director</em></h3>
</div> </div>


<div class="vcard"> <div class="vcard">
<h2><a href="http://bob.net" class="fn url">Bob Fucker</a> <em class="role">Underling</em></h2> <h3><a href="http://bob.net" class="fn url">Bob Fucker</a> <em class="role">Underling</em></h3>
</div> </div>


<h2>HCalendars</h2>
<ul class="ll"> <ul class="ll">


<li class="vevent"><a href="http://upcoming.org/event/144326" class="url summary">London Ruby User Group (LRUG) February Meeting</a>, <span class="location">London</span> <abbr title="2007-02-12" class="dtstart">12 FEB</abbr> - <abbr title="2007-02-06" class="dtend">06 FEB</abbr>.</li> <li class="vevent"><a href="http://upcoming.org/event/144326" class="url summary">London Ruby User Group (LRUG) February Meeting</a>, <span class="location">London</span> <abbr title="2007-02-12" class="dtstart">12 FEB</abbr> - <abbr title="2007-02-06" class="dtend">06 FEB</abbr>.</li>
Expand Down Expand Up @@ -53,6 +58,26 @@ <h2><a href="http://bob.net" class="fn url">Bob Fucker</a> <em class="role">Unde




</ul> </ul>

<h2>HReviews</h2>

<div class="hreview">
<span><span class="rating">5</span> out of 5 stars</span>
<h4 class="summary">Crepes on Cole is awesome</h4>
<span class="reviewer vcard">Reviewer: <span class="fn">Tantek</span> -
<abbr class="dtreviewed" title="20050418T2300-0700">April 18, 2005</abbr></span>
<div class="description item vcard"><p>
<span class="fn org">Crepes on Cole</span> is one of the best little
creperies in <span class="adr"><span class="locality">San Francisco</span></span>.
Excellent food and service. Plenty of tables in a variety of sizes
for parties large and small. Window seating makes for excellent
people watching to/from the N-Judah which stops right outside.
I've had many fun social gatherings here, as well as gotten
plenty of work done thanks to neighborhood WiFi.
</p></div>
<p>Visit date: <span>April 2005</span></p>
<p>Food eaten: <span>Florentine crepe</span></p>
</div>
</div> </div>
</body> </body>
</html> </html>

0 comments on commit 1324dd9

Please sign in to comment.