changeset 14:03be0717d3f8

Use the same code for client- and server-side Atom parsing.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 03 Nov 2011 16:42:00 -0700
parents 161d4ea1c3f8
children 5149a856d9dd
files atom.js nothing.js server.js
diffstat 3 files changed, 81 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/atom.js
+++ b/atom.js
@@ -1,19 +1,61 @@
 'use strict';
 
-if (!document)
+if (typeof window === 'undefined') {
+	var Element = require('ltx').Element;
+	var JID = require('./jid');
+	var ns = require('./ns');
+	var config = require('./configuration');
+
 	var document = {};
 
-if (!document.createElementNS)
 	document.createElementNS = function(ns, name) {
 		return new Element(name, {xmlns: ns});
 	};
 
-if (!document.createTextNode)
 	document.createTextNode = function(text) {
 		return text;
 	};
 
-parsers[ns.atom] = function(item) {
+	Element.prototype.getAttributeNS = function(ns, name) {
+		// TODO: use the namespace.
+		return this.attrs[name];
+	};
+
+	Element.prototype.setAttributeNS = function(ns, name, value) {
+		// TODO: use the namespace.
+		this.attrs[name] = value;
+	};
+
+	Element.prototype.cloneNode = function(depth) {
+		// XXX
+		return this;
+	};
+
+	Element.prototype.appendChild = function(child) {
+		if (typeof child === 'string')
+			this.t(child);
+		else
+			this.cnode(child);
+	};
+
+	Element.prototype.getElementsByTagNameNS = function(ns, name) {
+		return this.getChildren(name, ns);
+	};
+
+	Element.prototype.__defineGetter__('textContent', function() {
+		return this.getText();
+	});
+
+	Element.prototype.__defineGetter__('firstChild', function() {
+		return this.children[0];
+	});
+
+	Element.prototype.__defineGetter__('childNodes', function() {
+		return this.children;
+	});
+}
+
+var atomParser = function(item) {
 	var toDate = function(atom) {
 		var d = new Date;
 
@@ -38,11 +80,10 @@ parsers[ns.atom] = function(item) {
 
 	var toHTML = function(item, date) {
 		var atom = item.payload;
-		var id = item.id;
 
 		var article = document.createElementNS(ns.xhtml, 'article');
 
-		article.setAttributeNS(ns.e, 'id', id);
+		article.setAttributeNS(ns.e, 'id', item.id);
 		var d8601 = date.to8601();
 		article.setAttributeNS(ns.e, 'date', d8601);
 
@@ -70,7 +111,7 @@ parsers[ns.atom] = function(item) {
 			try {
 				var atomURI = atomAuthor.getElementsByTagNameNS(ns.atom, 'uri')[0].textContent;
 				var a = document.createElementNS(ns.xhtml, 'a');
-				a.href = atomURI;
+				a.setAttributeNS(null, 'href', atomURI);
 				var atomJID = new JID;
 				atomJID.uri = atomURI;
 
@@ -78,7 +119,7 @@ parsers[ns.atom] = function(item) {
 				cite.appendChild(a);
 
 				var img = document.createElementNS(ns.xhtml, 'img');
-				img.src = config.avatarRoot + atomJID.bare;
+				img.setAttributeNS(null, 'src', config.avatarRoot + atomJID.bare);
 				aside.appendChild(img);
 			} catch (e) {
 				cite.appendChild(document.createTextNode(atomName));
@@ -91,7 +132,7 @@ parsers[ns.atom] = function(item) {
 				var atomEmail = atomAuthor.getElementsByTagNameNS(ns.atom, 'email')[0].textContent;
 				footer.appendChild(document.createTextNode(' ('));
 				var a = document.createElementNS(ns.xhtml, 'a');
-				a.href = 'mailto:' + atomEmail;
+				a.setAttributeNS(null, 'href', 'mailto:' + atomEmail);
 				a.appendChild(document.createTextNode('email'));
 				footer.appendChild(a);
 				footer.appendChild(document.createTextNode(')'));
@@ -102,7 +143,11 @@ parsers[ns.atom] = function(item) {
 		} catch (e) {
 		}
 
-		footer.innerHTML += ', <time datetime="' + d8601 + '">' + date.getRelative() + '</time>';
+		var time = document.createElementNS(ns.xhtml, 'time');
+		time.setAttributeNS(null, 'datetime', d8601);
+		time.appendChild(document.createTextNode(date.getRelative()));
+		footer.appendChild(document.createTextNode(', '));
+		footer.appendChild(time);
 
 		try {
 			var atomSummary = atomAuthor.getElementsByTagNameNS(ns.atom, 'summary')[0].textContent;
@@ -120,12 +165,20 @@ parsers[ns.atom] = function(item) {
 				p.appendChild(document.createTextNode(atomContent.textContent));
 				article.appendChild(p);
 			} else if (/^html$/.test(contentType)) {
-				article.insertAdjacentHTML('beforeend', atomContent.textContent); // FIXME: could be not-well-formed.
+				if (!article.insertAdjacentHTML)
+					article.appendChild(document.createTextNode('Inline HTML inclusion not yet supported server-side.'));
+				else
+					article.insertAdjacentHTML('beforeend', atomContent.textContent); // FIXME: could be not-well-formed.
 			} else if (/^xhtml$/.test(contentType)) {
 				var div = atomContent.firstChild;
 				var children = div.childNodes;
-				for (var i=0; i<children.length; i++)
-					article.appendChild(children[i].cloneNode(true));
+				for (var i=0; i<children.length; i++) {
+					var child = children[i];
+					if (typeof child === 'string')
+						article.appendChild(child);
+					else
+						article.appendChild(child.cloneNode(true));
+				}
 			} else {
 				var contentSrc = atomContent.getAttributeNS(null, 'src');
 				if (contentSrc) {
@@ -166,7 +219,10 @@ parsers[ns.atom] = function(item) {
 			var href = new JID;
 			href.uri = atomLink.getAttributeNS(null, 'href');
 
-			article.innerHTML += '<a href="?jid=' + href.bare + ';node=' + href.query.node + ';comments=' + params.jid + '/' + params.node + '">Comments !</a>';
+			var a = document.createElementNS(ns.xhtml, 'a');
+			a.setAttributeNS(null, 'href', '?jid=' + href.bare + ';node=' + href.query.node);
+			a.appendChild(document.createTextNode('Comments'));
+			article.appendChild(a);
 		}
 
 		return article;
@@ -175,4 +231,9 @@ parsers[ns.atom] = function(item) {
 	this.xml = item.payload;
 	this.date = toDate(item.payload);
 	this.html = toHTML(item, this.date);
-}
+};
+
+if (typeof parsers !== 'undefined')
+	parsers[ns.atom] = atomParser;
+else if (typeof module !== 'undefined')
+	module.exports = atomParser;
--- a/nothing.js
+++ b/nothing.js
@@ -7,7 +7,7 @@ parsers[''] = function(item) {
 
 	var toHTML = function(item, date) {
 		var article = document.createElementNS(ns.xhtml, 'article');
-		article.setAttributeNS(ns.e, 'id', id);
+		article.setAttributeNS(ns.e, 'id', item.id);
 		article.setAttributeNS(ns.e, 'date', date.to8601());
 		article.appendChild(document.createElementNS(ns.xhtml, 'h2').appendChild(document.createTextNode('This post is in an unknown namespace.')));
 		return article;
--- a/server.js
+++ b/server.js
@@ -14,6 +14,7 @@ var JID = require('./jid');
 var ns = require('./ns');
 var forms = require('./forms');
 require('./date');
+var Atom = require('./atom');
 
 var received = {};
 
@@ -148,89 +149,6 @@ cl.on('stanza', function(stanza) {
 	}
 });
 
-var parseAtom = function(atom, id, jid) {
-	var article = new Element('article', {'e:id': id});
-
-	var avatar = article.c('aside').c('img')
-	article.up();
-
-	try {
-		var title = atom.getChild('title', ns.atom).getText();
-		if (title)
-			article.c('h2').t(title).up();
-	} catch (e) { }
-
-	var footer = article.c('footer');
-	article.up();
-
-	var author = atom.getChild('author', ns.atom);
-	if (author) {
-		footer.t('By ');
-		var name = author.getChild('name', ns.atom).getText();
-
-		try{
-			var uri = author.getChild('uri', ns.atom).getText();
-			footer.c('cite').c('a', {href: uri}).t(name).up();
-			avatar.attrs.src = config.avatarRoot + uri.substring(5);
-			avatar.attrs.alt = uri.substring(5);
-		} catch (e) {
-			footer.c('cite').t(name);
-		}
-
-		try {
-			var email = author.getChild('email', ns.atom).getText();
-			footer.t(' (').c('a', {href: 'mailto:' + email}).t('email').up().t(')');
-		} catch (e) { }
-		footer.up();
-	}
-
-	var published = (function() {
-		try {
-			var elem = atom.getChild('published', ns.atom);
-			var iso8601 = elem.getText();
-			var d = (new Date).set8601(iso8601);
-			var relative = d.getRelative();
-
-			return {iso8601: iso8601, relative: relative};
-		} catch (e) {
-			var d = new Date;
-			return {iso8601: d.to8601(), relative: d.getRelative()};
-		}
-	})();
-
-	if (author)
-		footer.t(', ');
-	footer.c('time', {datetime: published.iso8601}).t(published.relative).up();
-	article.attrs['e:date'] = published.iso8601;
-
-	try {
-		var summary = atom.getChild('summary', ns.atom).getText();
-		if (summary)
-			article.c('p').t(summary).up();
-	} catch (e) { }
-
-	try {
-		var links = atom.getChildren('link');
-		for (var i in links) {
-			var link = links[i];
-
-			if (link.attrs.rel !== 'replies')
-				continue;
-
-			if (link.attrs.title !== 'comments')
-				continue;
-
-			var href = new JID;
-			href.uri = link.attrs.href;
-
-			article.c('a', {href: '?jid=' + href.bare + ';node=' + href.query.node + ';origjid=' + jid.bare + ';orignode=' + jid.resource + ';origitem=' + id}).t('Comments !');
-			break;
-		}
-	} catch (e) { }
-
-	return article;
-};
-
 var generatePage = function(jid) {
 	var r = received[jid.full];
 	var s = r.wait;
@@ -251,9 +169,9 @@ var makePage = function(res, jid, form, 
 	var body = '</div>';
 
 	for (var id in data) {
-		var item = data[id];
-		var article = parseAtom(item, id, jid);
-		body = article + body;
+		var payload = data[id];
+		var article = new Atom({id: id, ns: payload.attrs['xmlns'], payload: payload}); // , jid ?
+		body = article.html + body;
 	}
 	body = '<div e:jid="' + jid.full + '">' + body;