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 19 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
75 changes: 75 additions & 0 deletions examples/simple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
var RSS = require('../lib/index');

/* let's create an rss feed */
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 too 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);
82 changes: 62 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'),
Copy link
Owner

Choose a reason for hiding this comment

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

you changed this accidently back to mime.

Copy link
Author

Choose a reason for hiding this comment

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

Whoops!

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 "items" handled below

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

// replace items
this.replace_items = function(items) {
items = items || [];
if (items && items.length > 0) {
this.items = [];
return this.concat_items(items);
} else {
return this;
}
};

// Concat new items to this.items
this.concat_items = 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"?>\n' +
xml(generateXML(this), indent);
};

// handle passed in "items" on obj creation using item()
if (items) {
return this.replace_items(items);
}
}

module.exports = RSS;
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"Patrick Garman <[email protected]>",
"Fred Morstatter",
"Eric Vantillard <[email protected]>",
"Jason Karns <jasonkarns>"
"Jason Karns <jasonkarns>",
"Kip Gebhardt <rv-kip>"
],
"repository": {
"type": "git",
Expand All @@ -57,10 +58,10 @@
"dependencies": {
"folderify": "^0.6.0",
"mime-types": "^2.0.3",
"mime": "^1.2.11",
Copy link
Owner

Choose a reason for hiding this comment

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

mime-types should be good enough

Copy link
Author

Choose a reason for hiding this comment

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

When I clone (or rm -rf node_modules), npm i, and npm test, I get an error for missing mime module unless mime is in package.json

Copy link
Owner

Choose a reason for hiding this comment

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

see above :)

"xml": "^1.0.0"
},
Copy link
Owner

Choose a reason for hiding this comment

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

This is for browserify.

Copy link
Author

Choose a reason for hiding this comment

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

It's already found in the regular dependencies. Npm was warning on the duplicate so I removed it. If it needs to be in both blocks, I can add it back.

Copy link
Owner

Choose a reason for hiding this comment

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

ha, good find, thanks, i'll fix that right now.

Copy link
Owner

Choose a reason for hiding this comment

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

fixed in master

"devDependencies": {
"folderify": "^0.6.0",
"grunt": "^0.4.5",
"grunt-contrib-jshint": "^0.10.0",
"grunt-release": "^0.9.0",
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 @@ -67,8 +68,20 @@ feed.item(itemOptions);
* `long` _optional_ **number** The longitude coordinate of the item.
* `custom_elements` _optional_ **array** Put additional elements in the item (node-xml syntax)

##### Feed XML
###### 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 All @@ -82,7 +95,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
15 changes: 14 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 @@ -56,8 +57,20 @@ feed.item(itemOptions);
* `long` _optional_ **number** The longitude coordinate of the item.
* `custom_elements` _optional_ **array** Put additional elements in the item (node-xml syntax)

#### Feed XML
##### 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
71 changes: 71 additions & 0 deletions test/expectedOutput/concatenateItems.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?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