Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 49 additions & 28 deletions lib/rss.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ function ifTruePush(bool, array, data) {
}
}

function ifTruePushArray(bool, array, dataArray) {
if(!bool) {
return;
}

dataArray.forEach(function(item) {
ifTruePush(item, array, item);
});
}

function generateXML (data){

var channel = [];
Expand Down Expand Up @@ -40,6 +50,8 @@ function generateXML (data){
});
}

ifTruePushArray(data.custom_elements, channel, data.custom_elements);

data.items.forEach(function(item) {
var item_values = [
{ title: { _cdata: item.title } }
Expand Down Expand Up @@ -84,6 +96,8 @@ function generateXML (data){
}
}

ifTruePushArray(item.custom_elements, item_values, item.custom_elements);

channel.push({ item: item_values });

});
Expand All @@ -96,6 +110,10 @@ function generateXML (data){
version: '2.0'
};

Object.keys(data.custom_namespaces).forEach(function(name) {
_attr['xmlns:' + name] = data.custom_namespaces[name];
});

//only add namespace if GeoRSS is true
if(data.geoRSS){
_attr['xmlns:geo'] = 'http://www.w3.org/2003/01/geo/wgs84_pos#';
Expand All @@ -112,39 +130,42 @@ function generateXML (data){
function RSS (options, items) {
options = options || {};

this.title = options.title || 'Untitled RSS Feed';
this.description = options.description || '';
this.generator = options.generator || 'RSS for Node';
this.feed_url = options.feed_url;
this.site_url = options.site_url;
this.image_url = options.image_url;
this.author = options.author;
this.categories = options.categories;
this.pubDate = options.pubDate;
this.hub = options.hub;
this.docs = options.docs;
this.copyright = options.copyright;
this.language = options.language;
this.managingEditor = options.managingEditor;
this.webMaster = options.webMaster;
this.ttl = options.ttl;
this.title = options.title || 'Untitled RSS Feed';
this.description = options.description || '';
this.generator = options.generator || 'RSS for Node';
this.feed_url = options.feed_url;
this.site_url = options.site_url;
this.image_url = options.image_url;
this.author = options.author;
this.categories = options.categories;
this.pubDate = options.pubDate;
this.hub = options.hub;
this.docs = options.docs;
this.copyright = options.copyright;
this.language = options.language;
this.managingEditor = options.managingEditor;
this.webMaster = options.webMaster;
this.ttl = options.ttl;
//option to return feed as GeoRSS is set automatically if feed.lat/long is used
this.geoRSS = options.geoRSS || false;
this.items = items || [];
this.geoRSS = options.geoRSS || false;
this.custom_namespaces = options.custom_namespaces || {};
this.custom_elements = options.custom_elements || [];
this.items = items || [];

this.item = function (options) {
options = options || {};
var item = {
title: options.title || 'No title',
description: options.description || '',
url: options.url,
guid: options.guid,
categories: options.categories || [],
author: options.author,
date: options.date,
lat: options.lat,
long: options.long,
enclosure: options.enclosure || false
title: options.title || 'No title',
description: options.description || '',
url: options.url,
guid: options.guid,
categories: options.categories || [],
author: options.author,
date: options.date,
lat: options.lat,
long: options.long,
enclosure: options.enclosure || false,
custom_elements: options.custom_elements || []
};

this.items.push(item);
Expand Down
44 changes: 42 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ var feed = new RSS(feedOptions);
* `pubDate` _optional_ **Date object or date string** The publication date for content in the feed
* `ttl` _optional_ **integer** Number of minutes feed can be cached before refreshing from source.
* `hub` _optional_ **PubSubHubbub hub url** Where is the PubSubHub hub located.
* `custom_namespaces` _optional_ **object** Put additional namespaces in <rss> element (without 'xmlns:' prefix)
* `custom_elements` _optional_ **array** Put additional elements in the feed (node-xml syntax)

#### Add items to a feed

Expand Down Expand Up @@ -64,6 +66,7 @@ feed.item(itemOptions);
if the content should be presented as unread.
* `lat` _optional_ **number** The latitude coordinate of the item.
* `long` _optional_ **number** The longitude coordinate of the item.
* `custom_elements` _optional_ **array** Put additional elements in the item (node-xml syntax)

##### Feed XML

Expand Down Expand Up @@ -96,7 +99,34 @@ var feed = new RSS({
language: 'en',
categories: ['Category 1','Category 2','Category 3'],
pubDate: 'May 20, 2012 04:00:00 GMT',
ttl: '60'
ttl: '60',
customNamespaces: {
'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'
},
custom: [
{'itunes:subtitle': 'A show about everything'},
{'itunes:author': 'John Doe'},
{'itunes:summary': 'All About Everything is a show about everything. Each week we dive into any subject known to man and talk about it as much as we can. Look for our podcast in the Podcasts app or in the iTunes Store'},
{'itunes:owner': [
{'itunes:name': 'John Doe'},
{'itunes:email': 'john.doe@example.com'}
]},
{'itunes:image': {
_attr: {
href: 'http://example.com/podcasts/everything/AllAboutEverything.jpg'
}
}},
{'itunes:category': [
{_attr: {
text: 'Technology'
}},
{'itunes:category': {
_attr: {
text: 'Gadgets'
}
}}
]}
]
});

/* loop over data and add to feed */
Expand All @@ -110,7 +140,17 @@ feed.item({
date: 'May 27, 2012', // any format that js Date can parse.
lat: 33.417974, //optional latitude field for GeoRSS
long: -111.933231, //optional longitude field for GeoRSS
enclosure: {url:'...', file:'path-to-file'} // optional enclosure
enclosure: {url:'...', file:'path-to-file'}, // optional enclosure
custom: [
{'itunes:author': 'John Doe'},
{'itunes:subtitle': 'A short primer on table spices'},
{'itunes:image': {
_attr: {
href: 'http://example.com/podcasts/everything/AllAboutEverything/Episode1.jpg'
}
}},
{'itunes:duration': '7:04'}
]
});

// cache the xml to send to clients
Expand Down
198 changes: 197 additions & 1 deletion test/rss.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,5 +262,201 @@ describe('rss module', function(done) {
expect(result).to.equal(expectedResult);
done();
});
});

it('should work with custom elements', function(done) {
var feed = new RSS({
title: 'title',
description: 'description',
feed_url: 'http://example.com/rss.xml',
site_url: 'http://example.com',
author: 'Dylan Greene',
pubDate: 'May 20, 2012 04:00:00 GMT',
language: 'en',
ttl: '60',
custom_elements: [
{'itunes:subtitle': 'A show about everything'},
{'itunes:author': 'John Doe'},
{'itunes:summary': 'All About Everything is a show about everything. Each week we dive into any subject known to man and talk about it as much as we can. Look for our podcast in the Podcasts app or in the iTunes Store'},
{'itunes:owner': [
{'itunes:name': 'John Doe'},
{'itunes:email': 'john.doe@example.com'}
]},
{'itunes:image': {
_attr: {
href: 'http://example.com/podcasts/everything/AllAboutEverything.jpg'
}
}},
{'itunes:category': [
{_attr: {
text: 'Technology'
}},
{'itunes:category': {
_attr: {
text: 'Gadgets'
}
}}
]}
]
});

feed.item({
title: 'item 1',
description: 'description 1',
url: 'http://example.com/article1',
date: 'May 24, 2012 04:00:00 GMT',
custom_elements: [
{'itunes:author': 'John Doe'},
{'itunes:subtitle': 'A short primer on table spices'},
{'itunes:image': {
_attr: {
href: 'http://example.com/podcasts/everything/AllAboutEverything/Episode1.jpg'
}
}},
{'itunes:duration': '7:04'}
]
});

var expectedResult ='<?xml version="1.0" encoding="UTF-8"?>\n'+
'<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">'+
'<channel>' +
'<title><![CDATA[title]]></title>' +
'<description><![CDATA[description]]></description>' +
'<link>http://example.com</link>' +
'<generator>RSS for Node</generator>' +
'<lastBuildDate>' + new Date().toUTCString() +'</lastBuildDate>' +
'<atom:link href="http://example.com/rss.xml" rel="self" type="application/rss+xml"/>' +
'<author><![CDATA[Dylan Greene]]></author>' +
'<pubDate>Sun, 20 May 2012 04:00:00 GMT</pubDate>' +
'<language><![CDATA[en]]></language>' +
'<ttl>60</ttl>' +
'<itunes:subtitle>A show about everything</itunes:subtitle>' +
'<itunes:author>John Doe</itunes:author>' +
'<itunes:summary>All About Everything is a show about everything. Each week we dive into any subject known to man and talk about it as much as we can. Look for our podcast in the Podcasts app or in the iTunes Store</itunes:summary>' +
'<itunes:owner>' +
'<itunes:name>John Doe</itunes:name>' +
'<itunes:email>john.doe@example.com</itunes:email>' +
'</itunes:owner>' +
'<itunes:image href="http://example.com/podcasts/everything/AllAboutEverything.jpg"/>' +
'<itunes:category text="Technology">' +
'<itunes:category text="Gadgets"/>' +
'</itunes:category>' +
'<item>' +
'<title><![CDATA[item 1]]></title>' +
'<description><![CDATA[description 1]]></description>' +
'<link>http://example.com/article1</link>' +
'<guid isPermaLink="true">http://example.com/article1</guid>' +
'<dc:creator><![CDATA[Dylan Greene]]></dc:creator>' +
'<pubDate>Thu, 24 May 2012 04:00:00 GMT</pubDate>' +
'<itunes:author>John Doe</itunes:author>' +
'<itunes:subtitle>A short primer on table spices</itunes:subtitle>' +
'<itunes:image href="http://example.com/podcasts/everything/AllAboutEverything/Episode1.jpg"/>' +
'<itunes:duration>7:04</itunes:duration>' +
'</item>' +
'</channel>' +
'</rss>';
var result = feed.xml();

expect(result).to.equal(expectedResult);
done();
});

it('should work with custom namespaces', function(done) {
var feed = new RSS({
title: 'title',
description: 'description',
feed_url: 'http://example.com/rss.xml',
site_url: 'http://example.com',
author: 'Dylan Greene',
pubDate: 'May 20, 2012 04:00:00 GMT',
language: 'en',
ttl: '60',
custom_namespaces: {
'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'
},
custom_elements: [
{'itunes:subtitle': 'A show about everything'},
{'itunes:author': 'John Doe'},
{'itunes:summary': 'All About Everything is a show about everything. Each week we dive into any subject known to man and talk about it as much as we can. Look for our podcast in the Podcasts app or in the iTunes Store'},
{'itunes:owner': [
{'itunes:name': 'John Doe'},
{'itunes:email': 'john.doe@example.com'}
]},
{'itunes:image': {
_attr: {
href: 'http://example.com/podcasts/everything/AllAboutEverything.jpg'
}
}},
{'itunes:category': [
{_attr: {
text: 'Technology'
}},
{'itunes:category': {
_attr: {
text: 'Gadgets'
}
}}
]}
]
});

feed.item({
title: 'item 1',
description: 'description 1',
url: 'http://example.com/article1',
date: 'May 24, 2012 04:00:00 GMT',
custom_elements: [
{'itunes:author': 'John Doe'},
{'itunes:subtitle': 'A short primer on table spices'},
{'itunes:image': {
_attr: {
href: 'http://example.com/podcasts/everything/AllAboutEverything/Episode1.jpg'
}
}},
{'itunes:duration': '7:04'}
]
});

var expectedResult ='<?xml version="1.0" encoding="UTF-8"?>\n'+
'<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">'+
'<channel>' +
'<title><![CDATA[title]]></title>' +
'<description><![CDATA[description]]></description>' +
'<link>http://example.com</link>' +
'<generator>RSS for Node</generator>' +
'<lastBuildDate>' + new Date().toUTCString() +'</lastBuildDate>' +
'<atom:link href="http://example.com/rss.xml" rel="self" type="application/rss+xml"/>' +
'<author><![CDATA[Dylan Greene]]></author>' +
'<pubDate>Sun, 20 May 2012 04:00:00 GMT</pubDate>' +
'<language><![CDATA[en]]></language>' +
'<ttl>60</ttl>' +
'<itunes:subtitle>A show about everything</itunes:subtitle>' +
'<itunes:author>John Doe</itunes:author>' +
'<itunes:summary>All About Everything is a show about everything. Each week we dive into any subject known to man and talk about it as much as we can. Look for our podcast in the Podcasts app or in the iTunes Store</itunes:summary>' +
'<itunes:owner>' +
'<itunes:name>John Doe</itunes:name>' +
'<itunes:email>john.doe@example.com</itunes:email>' +
'</itunes:owner>' +
'<itunes:image href="http://example.com/podcasts/everything/AllAboutEverything.jpg"/>' +
'<itunes:category text="Technology">' +
'<itunes:category text="Gadgets"/>' +
'</itunes:category>' +
'<item>' +
'<title><![CDATA[item 1]]></title>' +
'<description><![CDATA[description 1]]></description>' +
'<link>http://example.com/article1</link>' +
'<guid isPermaLink="true">http://example.com/article1</guid>' +
'<dc:creator><![CDATA[Dylan Greene]]></dc:creator>' +
'<pubDate>Thu, 24 May 2012 04:00:00 GMT</pubDate>' +
'<itunes:author>John Doe</itunes:author>' +
'<itunes:subtitle>A short primer on table spices</itunes:subtitle>' +
'<itunes:image href="http://example.com/podcasts/everything/AllAboutEverything/Episode1.jpg"/>' +
'<itunes:duration>7:04</itunes:duration>' +
'</item>' +
'</channel>' +
'</rss>';
var result = feed.xml();

expect(result).to.equal(expectedResult);
done();
});
});