You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.8 KiB
114 lines
3.8 KiB
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;
|
|
|