Skip to content
Closed
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
44 changes: 27 additions & 17 deletions lib/rss.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function RSS (options, items) {
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.cdata = options.cdata || true; //will wrap content to CDATA
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will result in options.cdata = true when cdata is passed in as false, so CDATA wrapping always occurs.

Add this to the bottom of the tests to expose the bug:

    it('should wrap elements with CDATA', function(done) {
        var feed = new RSS({
            title: 'title',
            description: 'description',
            feed_url: 'http://example.com/rss.xml',
            site_url: 'http://example.com',
            cdata: true
        });

        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"/>'+
                                 '</channel>'+
                             '</rss>';

        var result = feed.xml();

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

    it('should wrap not elements with CDATA', function(done) {
        var feed = new RSS({
            title: 'title',
            description: 'description',
            feed_url: 'http://example.com/rss.xml',
            site_url: 'http://example.com',
            cdata: false
        });

        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>title</title>'+
                                     '<description>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"/>'+
                                 '</channel>'+
                             '</rss>';

        var result = feed.xml();

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

this.items = items || [];

this.item = function (options) {
Expand Down Expand Up @@ -61,11 +62,20 @@ function ifTruePush(bool, array, data) {
}
}

function getValue (bool, argument) {
if(bool){
return {_cdata: argument};
}else{
return argument;
}
}

function generateXML (data){
var cdata = data.cdata;

var channel = [];
channel.push({ title: { _cdata: data.title } });
channel.push({ description: { _cdata: data.description || data.title } });
channel.push({ title: getValue(cdata, data.title) });
channel.push({ description: getValue(cdata, data.description || data.title) });
channel.push({ link: data.site_url || 'http://github.com/dylang/node-rss' });
// image_url set?
if (data.image_url) {
Expand All @@ -74,36 +84,36 @@ function generateXML (data){
channel.push({ generator: data.generator });
channel.push({ lastBuildDate: new Date().toGMTString() });

ifTruePush(data.feed_url, channel, { 'atom:link': { _attr: { href: data.feed_url, rel: 'self', type: 'application/rss+xml' } } });
ifTruePush(data.author, channel, { 'author': { _cdata: data.author } });
ifTruePush(data.pubDate, channel, { 'pubDate': new Date(data.pubDate).toGMTString() });
ifTruePush(data.copyright, channel, { 'copyright': { _cdata: data.copyright } });
ifTruePush(data.language, channel, { 'language': { _cdata: data.language } });
ifTruePush(data.managingEditor, channel, { 'managingEditor': { _cdata: data.managingEditor } });
ifTruePush(data.webMaster, channel, { 'webMaster': { _cdata: data.webMaster } });
ifTruePush(data.docs, channel, { 'docs': data.docs });
ifTruePush(data.ttl, channel, { 'ttl': data.ttl });
ifTruePush(data.hub, channel, { 'atom:link': { _attr: { href: data.hub, rel: 'hub' } } });
ifTruePush(data.feed_url, channel, { 'atom:link': { _attr: { href: data.feed_url, rel: 'self', type: 'application/rss+xml' } } });
ifTruePush(data.author, channel, { 'author': getValue(cdata, data.author) });
ifTruePush(data.pubDate, channel, { 'pubDate': new Date(data.pubDate).toGMTString() });
ifTruePush(data.copyright, channel, { 'copyright': getValue(cdata, data.copyright) });
ifTruePush(data.language, channel, { 'language': getValue(cdata, data.language) });
ifTruePush(data.managingEditor, channel, { 'managingEditor': getValue(cdata, data.managingEditor) });
ifTruePush(data.webMaster, channel, { 'webMaster': getValue(cdata, data.webMaster) });
ifTruePush(data.docs, channel, { 'docs': data.docs });
ifTruePush(data.ttl, channel, { 'ttl': data.ttl });
ifTruePush(data.hub, channel, { 'atom:link': { _attr: { href: data.hub, rel: 'hub' } } });

if (data.categories) {
data.categories.forEach(function(category) {
ifTruePush(category, channel, { category: { _cdata: category } });
ifTruePush(category, channel, { category: getValue(cdata, category) });
});
}

data.items.forEach(function(item) {
var item_values = [
{ title: { _cdata: item.title } }
{ title: getValue(cdata, item.title) }
];
ifTruePush(item.description, item_values, { description: { _cdata: item.description } });
ifTruePush(item.description, item_values, { description: getValue(cdata, item.description) });
ifTruePush(item.url, item_values, { link: item.url });
ifTruePush(item.link || item.guid || item.title, item_values, { guid: [ { _attr: { isPermaLink: !item.guid && !!item.url } }, item.guid || item.url || item.title ] });

item.categories.forEach(function(category) {
ifTruePush(category, item_values, { category: { _cdata: category } });
ifTruePush(category, item_values, { category: getValue(cdata, category) });
});

ifTruePush(item.author || data.author, item_values, { 'dc:creator': { _cdata: item.author || data.author } });
ifTruePush(item.author || data.author, item_values, { 'dc:creator': getValue(cdata, item.author || data.author) });
ifTruePush(item.date, item_values, { pubDate: new Date(item.date).toGMTString() });

//Set GeoRSS to true if lat and long are set
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ 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 PubSubHubb hub located.
* `cdata` _optional_ **boolean** Wrap content to CDATA if **true**. Default value is **true**.

### Add items to a feed

Expand Down