Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CDATA filtering options, new item addition functions, unit tests, bug fixes #38

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1fab44d
Merge from upstream master
Dec 13, 2014
23aa233
Allowing selective disabling of CDATA wrapping by field name. Adding …
Dec 13, 2014
ab2ab66
Update readme.md
rv-kip Dec 13, 2014
87e0c77
Everyone loves an example
Dec 13, 2014
6ac9af9
Didn't end up using underscore.
Dec 13, 2014
3070e49
Changing param name to no_encode_fields in all needed places
Dec 16, 2014
f0fc81f
... plus one more place
Dec 16, 2014
6fba453
Going back to 'no_cdata_fields' for name. Clarifying use case in docs…
Dec 16, 2014
38363d1
Fixing typo in example
Dec 16, 2014
e23f8f6
README cleanup for custom_namespaces and custom_elements
Dec 17, 2014
f528b84
Fixing bug. Items passed in on RSS obj creation did not get processed…
Dec 17, 2014
ff24ee9
Merge branch 'master' of https://github.com/dylang/node-rss into reap…
Dec 19, 2014
ce46bbf
Moving tests from defunct PR into new branch
Dec 19, 2014
5993cd5
Added tests for new functionality
rv-kip Dec 20, 2014
6478f12
Missing mime dependency and a dupe dep
rv-kip Dec 20, 2014
65a9d42
Removing old mocha test
rv-kip Dec 20, 2014
fa4d015
Documentation update and readme generation
rv-kip Dec 20, 2014
5450f8d
Moving mime to dependencies
rv-kip Dec 20, 2014
c1f6460
Indenting change on example. Commenting.
rv-kip Dec 20, 2014
603b252
Removing unecessary mime module.
rv-kip Dec 20, 2014
ddfa350
Updating function names, docs, and unit tests as per discussion
Feb 10, 2015
86f2a74
Merge pull request #1 from rv-kip/function_renaming
rv-kip Feb 10, 2015
706e137
Merge branch 'master' of https://github.com/dylang/node-rss
Apr 22, 2015
8d14204
Merge branch 'master' of https://github.com/dylang/node-rss
May 27, 2015
bfe54b7
Fixing merge conflicts
rv-kip Nov 2, 2015
cd123b6
Removing newlines that were breaking unit tests after 87c956d
rv-kip Nov 3, 2015
a8cfc9e
Merge branch 'master' into master
rv-kip Feb 27, 2018
6b7e4d7
Update package.json
rv-kip Feb 27, 2018
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
28 changes: 28 additions & 0 deletions examples/custom_elements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
var RSS = require('../lib/');

// Create RSS Feed Meta
var feed = new RSS({
title: 'title',
description: 'description',
custom_namespaces : {
"content" : "http://purl.org/rss/1.0/modules/content/"
},
});

// Add an item/article to the feed with a custom_element
feed.item({
title: 'Item Title ',
description: 'The description',
custom_elements: [
{
"content:encoded":
{
_cdata: "This is the long content. <b>This & That</b>"
}
}
]
});

// generate xml with default indent (4 sp)
var xml = feed.xml({indent: true});
console.log(xml);
78 changes: 78 additions & 0 deletions examples/simple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

// A simple RSS feed generation example

var RSS = require('../lib/index');

// Create RSS Feed Meta
var feed = new RSS({
title: 'title',
description: 'description',
feed_url: 'http://example.com/rss.xml',
site_url: 'http://example.com',
image_url: 'http://example.com/icon.png',
docs: 'http://example.com/rss/docs.html',
managingEditor: 'Dylan Greene',
webMaster: 'Dylan Greene',
copyright: '2013 Dylan Greene',
language: 'en',
categories: ['Category 1','Category 2','Category 3'],
pubDate: 'May 20, 2012 04:00:00 GMT',
ttl: '60',
no_cdata_fields: ['title', 'category'],
customNamespaces: {
'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': '[email protected]'}
]},
{'itunes:image': {
_attr: {
href: 'http://example.com/podcasts/everything/AllAboutEverything.jpg'
}
}},
{'itunes:category': [
{_attr: {
text: 'Technology'
}},
{'itunes:category': {
_attr: {
text: 'Gadgets'
}
}}
]}
]
});

// Add an item/article to the feed
feed.item({
title: 'Item Title & Fun',
description: 'Use this for the content. It can include html.',
url: 'http://example.com/article4?this&that', // link to the item
guid: '1123', // optional - defaults to url
categories: ['Category 1','Category 2'], // optional - array of item categories
author: 'Guest Author', // optional - defaults to feed author property
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: 'https://www.google.com/images/srpr/logo11w.png' },
// enclosure: {file:'path-to-file'}, // enclosure from file
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'}
]
});

// generate xml with default indent (4 sp)
var xml = feed.xml({indent: true});
console.log(xml);
77 changes: 57 additions & 20 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use strict';

var mime = require('mime-types');
var xml = require('xml');
var fs = require('fs');

var xml = require('xml'),
mime = require('mime-types'),
fs = require('fs');

function ifTruePush(bool, array, data) {
if (bool) {
Expand All @@ -29,11 +28,27 @@ function getSize(filename) {
}

function generateXML (data){
// Field names that should not be CDATA wrapped
var no_cdata_fields = data.no_cdata_fields || [];

// Handle formatting of CDATA-able output
function output(field_name, value) {
if (!value) {
return;
}
var ret_value = {};
if (no_cdata_fields.indexOf(field_name) !== -1) {
ret_value[field_name] = value;
} else {
ret_value[field_name] = { _cdata: value }; // CDATA
}
return ret_value;
}

var channel = [];
channel.push({ title: { _cdata: data.title } });
channel.push({ description: { _cdata: data.description || data.title } });
channel.push({ link: data.site_url || 'http://github.com/dylang/node-rss' });
channel.push( output('title', data.title) );
channel.push( output('description', (data.description || data.title)) );
channel.push({ link: data.site_url || 'http://github.com/dylang/node-rss' });
// image_url set?
if (data.image_url) {
channel.push({ image: [ {url: data.image_url}, {title: data.title}, {link: data.site_url} ] });
Expand All @@ -42,37 +57,35 @@ function generateXML (data){
channel.push({ lastBuildDate: new Date().toUTCString() });

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.author, channel, output('author', 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.copyright, channel, output('copyright', data.copyright) );
ifTruePush(data.language, channel, output('language', data.language) );
ifTruePush(data.managingEditor, channel, output('managingEditor', data.managingEditor) );
ifTruePush(data.webMaster, channel, output('webMaster', 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, output('category', category));
});
}

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

data.items.forEach(function(item) {
var item_values = [
{ title: { _cdata: item.title } }
];
ifTruePush(item.description, item_values, { description: { _cdata: item.description } });
var item_values = [ output('title', item.title) ];
ifTruePush(item.description, item_values, output('description', 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, output('category', category));
});

ifTruePush(item.author || data.author, item_values, { 'dc:creator': { _cdata: item.author || data.author } });
ifTruePush(item.author || data.author, item_values, output('dc:creator', (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 Expand Up @@ -158,7 +171,8 @@ function RSS (options, items) {
this.geoRSS = options.geoRSS || false;
this.custom_namespaces = options.custom_namespaces || {};
this.custom_elements = options.custom_elements || [];
this.items = items || [];
this.no_cdata_fields = options.no_cdata_fields || [];
this.items = []; // passed in array of items is handled below

this.item = function (options) {
options = options || {};
Expand All @@ -180,10 +194,33 @@ function RSS (options, items) {
return this;
};

// removeItems: Remove items that match basic params
this.removeAllItems = function() {
this.items = [];
return this;
};

// Add array of items to this.items via item()
this.addItems = function (items) {
var self = this;
items = items || [];
if (items && items.length > 0) {
items.forEach(function(item){
self.item(item);
});
}
return this;
};

this.xml = function(indent) {
return '<?xml version="1.0" encoding="UTF-8"?>' +
xml(generateXML(this), indent);
};

// handle passed in array of items on obj creation using item()
if (items) {
return this.addItems(items);
}
}

module.exports = RSS;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"Fred Morstatter",
"Eric Vantillard <[email protected]>",
"Jason Karns <jasonkarns>",
"Kip Gebhardt <rv-kip>",
"Hannah Wolfe <[email protected]>"
],
"repository": {
Expand Down
17 changes: 15 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ var feed = new RSS(feedOptions);
* `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)
* `no_cdata_fields` _optional_ **array** Field names that shouldn't be wrapped with CDATA tag. The data will be escaped for XML. Default is to wrap with CDATA. You should only use this to work around problematic XML clients.

#### Add items to a feed

Expand Down Expand Up @@ -85,8 +86,20 @@ feed.item(itemOptions);
}

```
##### Feed XML

###### Add single item
```js
feed.item(itemOptions);
```
###### Concatenate an array of items
```js
feed.addItems(arrayOfItemOptions);
```
###### Delete all items
```js
feed.removeAllItems();
```
##### Feed XML
```js
var xml = feed.xml({indent: true});
```
Expand All @@ -100,7 +113,7 @@ For example you can use `'\t'` for tab character, or `' '` for two-space tabs.


### Example Usage

(examples/simple.js)
```js
var RSS = require('rss');

Expand Down
2 changes: 1 addition & 1 deletion templates/readme/examples.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## Example Usage

(examples/simple.js)
```js
var RSS = require('rss');

Expand Down
14 changes: 13 additions & 1 deletion templates/readme/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var feed = new RSS(feedOptions);
* `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)
* `no_cdata_fields` _optional_ **array** Field names that shouldn't be wrapped with CDATA tag. The data will be escaped for XML. Default is to wrap with CDATA. You should only use this to work around problematic XML clients.

### Add items to a feed

Expand Down Expand Up @@ -74,8 +75,19 @@ feed.item(itemOptions);
}

```
##### Add single item
```js
feed.item(itemOptions);
```
##### Concatenate an array of items
```js
feed.concat_items(arrayOfItemOptions);
```
##### Replace items with a new array of items
```js
feed.replace_items(arrayOfItemOptions);
```
#### Feed XML

```js
var xml = feed.xml({indent: true});
```
Expand Down
70 changes: 70 additions & 0 deletions test/expectedOutput/concatenateItems.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?><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>
<image>
<url>http://example.com/icon.png</url>
<title>title</title>
<link>http://example.com</link>
</image>
<generator>Example Generator</generator>
<lastBuildDate>Wed, 10 Dec 2014 19:04:57 GMT</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>
<copyright><![CDATA[2013 Dylan Green]]></copyright>
<language><![CDATA[en]]></language>
<managingEditor><![CDATA[Dylan Green]]></managingEditor>
<webMaster><![CDATA[Dylan Green]]></webMaster>
<docs>http://example.com/rss/docs.html</docs>
<ttl>60</ttl>
<category><![CDATA[Category 1]]></category>
<category><![CDATA[Category 2]]></category>
<category><![CDATA[Category 3]]></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>
</item>
<item>
<title><![CDATA[item 2]]></title>
<description><![CDATA[description 2]]></description>
<link>http://example.com/article2</link>
<guid isPermaLink="true">http://example.com/article2</guid>
<dc:creator><![CDATA[Dylan Greene]]></dc:creator>
<pubDate>Fri, 25 May 2012 04:00:00 GMT</pubDate>
</item>
<item>
<title><![CDATA[item 3]]></title>
<description><![CDATA[description 3]]></description>
<link>http://example.com/article3</link>
<guid isPermaLink="false">item3</guid>
<dc:creator><![CDATA[Dylan Greene]]></dc:creator>
<pubDate>Sat, 26 May 2012 04:00:00 GMT</pubDate>
</item>
<item>
<title><![CDATA[item 4 & html test with <strong>]]></title>
<description><![CDATA[description 4 uses some <strong>html</strong>]]></description>
<link>http://example.com/article4?this&amp;that</link>
<guid isPermaLink="true">http://example.com/article4?this&amp;that</guid>
<dc:creator><![CDATA[Guest Author]]></dc:creator>
<pubDate>Sun, 27 May 2012 04:00:00 GMT</pubDate>
</item>
<item>
<title><![CDATA[item 5 & test for categories]]></title>
<description><![CDATA[description 5]]></description>
<link>http://example.com/article5</link>
<guid isPermaLink="true">http://example.com/article5</guid>
<category><![CDATA[Category 1]]></category>
<category><![CDATA[Category 2]]></category>
<category><![CDATA[Category 3]]></category>
<category><![CDATA[Category 4]]></category>
<dc:creator><![CDATA[Guest Author]]></dc:creator>
<pubDate>Mon, 28 May 2012 04:00:00 GMT</pubDate>
</item>
</channel>
</rss>
Loading