var DomHandler = require("domhandler"); var DomUtils = require("domutils"); //TODO: make this a streamable handler function FeedHandler(callback, options) { this.init(callback, options); } require("inherits")(FeedHandler, DomHandler); FeedHandler.prototype.init = DomHandler; function getElements(what, where) { return DomUtils.getElementsByTagName(what, where, true); } function getOneElement(what, where) { return DomUtils.getElementsByTagName(what, where, true, 1)[0]; } function fetch(what, where, recurse) { return DomUtils.getText( DomUtils.getElementsByTagName(what, where, recurse, 1) ).trim(); } function addConditionally(obj, prop, what, where, recurse) { var tmp = fetch(what, where, recurse); if (tmp) obj[prop] = tmp; } var isValidFeed = function(value) { return value === "rss" || value === "feed" || value === "rdf:RDF"; }; FeedHandler.prototype.onend = function() { var feed = {}, feedRoot = getOneElement(isValidFeed, this.dom), tmp, childs; if (feedRoot) { if (feedRoot.name === "feed") { childs = feedRoot.children; feed.type = "atom"; addConditionally(feed, "id", "id", childs); addConditionally(feed, "title", "title", childs); if ( (tmp = getOneElement("link", childs)) && (tmp = tmp.attribs) && (tmp = tmp.href) ) feed.link = tmp; addConditionally(feed, "description", "subtitle", childs); if ((tmp = fetch("updated", childs))) feed.updated = new Date(tmp); addConditionally(feed, "author", "email", childs, true); feed.items = getElements("entry", childs).map(function(item) { var entry = {}, tmp; item = item.children; addConditionally(entry, "id", "id", item); addConditionally(entry, "title", "title", item); if ( (tmp = getOneElement("link", item)) && (tmp = tmp.attribs) && (tmp = tmp.href) ) entry.link = tmp; if ((tmp = fetch("summary", item) || fetch("content", item))) entry.description = tmp; if ((tmp = fetch("updated", item))) entry.pubDate = new Date(tmp); return entry; }); } else { childs = getOneElement("channel", feedRoot.children).children; feed.type = feedRoot.name.substr(0, 3); feed.id = ""; addConditionally(feed, "title", "title", childs); addConditionally(feed, "link", "link", childs); addConditionally(feed, "description", "description", childs); if ((tmp = fetch("lastBuildDate", childs))) feed.updated = new Date(tmp); addConditionally(feed, "author", "managingEditor", childs, true); feed.items = getElements("item", feedRoot.children).map(function( item ) { var entry = {}, tmp; item = item.children; addConditionally(entry, "id", "guid", item); addConditionally(entry, "title", "title", item); addConditionally(entry, "link", "link", item); addConditionally(entry, "description", "description", item); if ((tmp = fetch("pubDate", item))) entry.pubDate = new Date(tmp); return entry; }); } } this.dom = feed; DomHandler.prototype._handleCallback.call( this, feedRoot ? null : Error("couldn't find root of feed") ); }; module.exports = FeedHandler;