From 1fab44da09caaee6e1932a9a2d4a7f5d41e9d20a Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 12 Dec 2014 16:14:42 -0800 Subject: [PATCH 01/18] Merge from upstream master --- lib/rss.js | 7 ++++--- package.json | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/rss.js b/lib/rss.js index 8199b629..e389b56a 100755 --- a/lib/rss.js +++ b/lib/rss.js @@ -1,8 +1,9 @@ 'use strict'; -var xml = require('xml'), - mime = require('mime'), - fs = require('fs'); +var xml = require('xml'), + mime = require('mime'), + fs = require('fs'), + _ = require('underscore'); function ifTruePush(bool, array, data) { if (bool) { diff --git a/package.json b/package.json index 3c539c18..094e740d 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ }, "dependencies": { "mime": "^1.2.11", + "underscore": "^1.7.0", "xml": "^1.0.0" }, "devDependencies": { From 23aa233b068ec9d394cbf017819f2b19eb1dea2b Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 12 Dec 2014 17:30:01 -0800 Subject: [PATCH 02/18] Allowing selective disabling of CDATA wrapping by field name. Adding concat_items and replace_items. Associated unit tests --- lib/rss.js | 68 +++++++++++++---- test/rss.test.js | 193 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 245 insertions(+), 16 deletions(-) diff --git a/lib/rss.js b/lib/rss.js index e389b56a..1baa79d3 100755 --- a/lib/rss.js +++ b/lib/rss.js @@ -22,11 +22,27 @@ function ifTruePushArray(bool, array, dataArray) { } 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} ] }); @@ -35,37 +51,35 @@ function generateXML (data){ 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.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 @@ -151,6 +165,7 @@ function RSS (options, items) { this.geoRSS = options.geoRSS || false; this.custom_namespaces = options.custom_namespaces || {}; this.custom_elements = options.custom_elements || []; + this.no_cdata_fields = options.no_cdata_fields || []; this.items = items || []; this.item = function (options) { @@ -173,6 +188,29 @@ 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 '\n' + xml(generateXML(this), indent); diff --git a/test/rss.test.js b/test/rss.test.js index 39df2d6c..e39387f1 100644 --- a/test/rss.test.js +++ b/test/rss.test.js @@ -71,7 +71,7 @@ describe('rss module', function(done) { date: 'May 28, 2012 04:00:00 GMT' }); return feed; - } + }; it('should work with indentation', function(done) { var feed = simpleFeed(); @@ -459,4 +459,195 @@ describe('rss module', function(done) { expect(result).to.equal(expectedResult); done(); }); + + 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' + }); + + var expectedResult = '\n'+ + ''+ + ''+ + '<![CDATA[title]]>'+ + ''+ + 'http://example.com'+ + 'RSS for Node'+ + '' + new Date().toUTCString() +''+ + ''+ + ''+ + ''; + + var result = feed.xml(); + + expect(result).to.equal(expectedResult); + done(); + }); + + it('should not wrap specific fields with CDATA', function(done) { + var feed = new RSS({ + title: 'title', + description: 'description', + author: 'Dylan Greene', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + no_cdata_fields: ['title', 'author'] + }); + + var expectedResult = '\n'+ + ''+ + ''+ + 'title'+ + ''+ + 'http://example.com'+ + 'RSS for Node'+ + '' + new Date().toUTCString() +''+ + ''+ + 'Dylan Greene' + + ''+ + ''; + + var result = feed.xml(); + + expect(result).to.equal(expectedResult); + done(); + }); + + it('should allow concatenation of array of items to existing items', function(done) { + var feed = new RSS({ + title: 'title', + description: 'description', + generator: 'Example Generator', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + image_url: 'http://example.com/icon.png', + author: 'Dylan Greene', + categories: ['Category 1','Category 2','Category 3'], + pubDate: 'May 20, 2012 04:00:00 GMT', + docs: 'http://example.com/rss/docs.html', + copyright: '2013 Dylan Green', + language: 'en', + managingEditor: 'Dylan Green', + webMaster: 'Dylan Green', + ttl: '60' + }); + + feed.item({ + title: 'item 1', + description: 'description 1', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }); + + var additional_items = [{ + title: 'item 2', + description: 'description 2', + url: 'http://example.com/article2', + date: 'May 25, 2012 04:00:00 GMT' + }, + { + title: 'item 3', + description: 'description 3', + url: 'http://example.com/article3', + guid: 'item3', + date: 'May 26, 2012 04:00:00 GMT' + }, + { + title: 'item 4 & html test with ', + description: 'description 4 uses some html', + url: 'http://example.com/article4?this&that', + author: 'Guest Author', + date: 'May 27, 2012 04:00:00 GMT' + }, + { + title: 'item 5 & test for categories', + description: 'description 5', + url: 'http://example.com/article5', + categories: ['Category 1','Category 2','Category 3','Category 4'], + author: 'Guest Author', + date: 'May 28, 2012 04:00:00 GMT' + }]; + + feed.concat_items(additional_items); + + var expectedResult = '\n<![CDATA[title]]>http://example.comhttp://example.com/icon.pngtitlehttp://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60<![CDATA[item 1]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT<![CDATA[item 2]]>http://example.com/article2http://example.com/article2Fri, 25 May 2012 04:00:00 GMT<![CDATA[item 3]]>http://example.com/article3item3Sat, 26 May 2012 04:00:00 GMT<![CDATA[item 4 & html test with <strong>]]>html]]>http://example.com/article4?this&thathttp://example.com/article4?this&thatSun, 27 May 2012 04:00:00 GMT<![CDATA[item 5 & test for categories]]>http://example.com/article5http://example.com/article5Mon, 28 May 2012 04:00:00 GMT'; + var result = feed.xml(); + + expect(result).to.equal(expectedResult); + done(); + }); + + it('should allow replacement of all items with of array of new items', function(done) { + var feed = new RSS({ + title: 'title', + description: 'description', + generator: 'Example Generator', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + image_url: 'http://example.com/icon.png', + author: 'Dylan Greene', + categories: ['Category 1','Category 2','Category 3'], + pubDate: 'May 20, 2012 04:00:00 GMT', + docs: 'http://example.com/rss/docs.html', + copyright: '2013 Dylan Green', + language: 'en', + managingEditor: 'Dylan Green', + webMaster: 'Dylan Green', + ttl: '60' + }); + + feed.item({ + title: 'BOGUS ITEM - REPLACE ME', + description: 'BOGUS ITEM - REPLACE ME', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }); + + var additional_items = [ + { + title: 'item 1', + description: 'description 1', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }, + { + title: 'item 2', + description: 'description 2', + url: 'http://example.com/article2', + date: 'May 25, 2012 04:00:00 GMT' + }, + { + title: 'item 3', + description: 'description 3', + url: 'http://example.com/article3', + guid: 'item3', + date: 'May 26, 2012 04:00:00 GMT' + }, + { + title: 'item 4 & html test with ', + description: 'description 4 uses some html', + url: 'http://example.com/article4?this&that', + author: 'Guest Author', + date: 'May 27, 2012 04:00:00 GMT' + }, + { + title: 'item 5 & test for categories', + description: 'description 5', + url: 'http://example.com/article5', + categories: ['Category 1','Category 2','Category 3','Category 4'], + author: 'Guest Author', + date: 'May 28, 2012 04:00:00 GMT' + }]; + + feed.replace_items(additional_items); + + var expectedResult = '\n<![CDATA[title]]>http://example.comhttp://example.com/icon.pngtitlehttp://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60<![CDATA[item 1]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT<![CDATA[item 2]]>http://example.com/article2http://example.com/article2Fri, 25 May 2012 04:00:00 GMT<![CDATA[item 3]]>http://example.com/article3item3Sat, 26 May 2012 04:00:00 GMT<![CDATA[item 4 & html test with <strong>]]>html]]>http://example.com/article4?this&thathttp://example.com/article4?this&thatSun, 27 May 2012 04:00:00 GMT<![CDATA[item 5 & test for categories]]>http://example.com/article5http://example.com/article5Mon, 28 May 2012 04:00:00 GMT'; + var result = feed.xml(); + + expect(result).to.equal(expectedResult); + done(); + }); + }); From ab2ab6616c985410cdaa924e487b57284ae9bab4 Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 12 Dec 2014 17:46:53 -0800 Subject: [PATCH 03/18] Update readme.md --- readme.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 11 deletions(-) diff --git a/readme.md b/readme.md index bbc2bef3..01170c3d 100644 --- a/readme.md +++ b/readme.md @@ -38,18 +38,13 @@ var feed = new RSS(feedOptions); * `hub` _optional_ **PubSubHubbub hub url** Where is the PubSubHub hub located. * `custom_namespaces` _optional_ **object** Put additional namespaces in 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. Default is to wrap #### Add items to a feed - An item can be used for a blog entry, project update, log entry, etc. Your RSS feed can have any number of items. Most feeds use 20 or fewer items. -```js -feed.item(itemOptions); -``` - ##### itemOptions - * `title` **string** Title of this particular item. * `description` **string** Content for the item. Can contain html but link and image urls must be absolute path including hostname. * `url` **url string** Url to the item. This could be a blog entry. @@ -67,7 +62,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); @@ -80,11 +88,12 @@ This returns the XML as a string. ### Example Usage +(examples/simple.js) ```js -var RSS = require('rss'); +var RSS = require('../lib/rss'); -/* lets create an rss feed */ +/* let's create an rss feed */ var feed = new RSS({ title: 'title', description: 'description', @@ -99,6 +108,7 @@ var feed = new RSS({ 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' }, @@ -139,7 +149,8 @@ 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:'https://www.google.com/images/srpr/logo11w.png'}, + // enclosure: {file:'path-to-file'}, // optional enclosure custom: [ {'itunes:author': 'John Doe'}, {'itunes:subtitle': 'A short primer on table spices'}, @@ -153,7 +164,52 @@ feed.item({ }); // cache the xml to send to clients -var xml = feed.xml(); +var xml = feed.xml(" "); +console.log(xml); +``` +#### XML Output: +```xml + + + + title + + http://example.com + + http://example.com/icon.png + title + http://example.com + + RSS for Node + Sat, 13 Dec 2014 01:44:19 GMT + + Sun, 20 May 2012 04:00:00 GMT + + + + + http://example.com/rss/docs.html + 60 + Category 1 + Category 2 + Category 3 + + item title + + http://example.com/article4?this&that + 1123 + Category 1 + Category 2 + Category 3 + Category 4 + + Sun, 27 May 2012 07:00:00 GMT + 33.417974 + -111.933231 + + + + ``` From 87e0c776556033d191ba9f055219441e7b3aee9b Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 12 Dec 2014 17:49:06 -0800 Subject: [PATCH 04/18] Everyone loves an example --- examples/simple.js | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 examples/simple.js diff --git a/examples/simple.js b/examples/simple.js new file mode 100644 index 00000000..c4d78fa9 --- /dev/null +++ b/examples/simple.js @@ -0,0 +1,76 @@ +var RSS = require('../lib/rss'); + +/* 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: [ + {'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 */ +feed.item({ + title: 'item title', + 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','Category 3','Category 4'], // 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'}, // 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 +var xml = feed.xml(" "); + +console.log(xml); \ No newline at end of file From 6ac9af990c2aa200271f69839003e8fe068942df Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 12 Dec 2014 18:02:13 -0800 Subject: [PATCH 05/18] Didn't end up using underscore. --- lib/rss.js | 3 +-- package.json | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/rss.js b/lib/rss.js index 1baa79d3..cbb3224a 100755 --- a/lib/rss.js +++ b/lib/rss.js @@ -2,8 +2,7 @@ var xml = require('xml'), mime = require('mime'), - fs = require('fs'), - _ = require('underscore'); + fs = require('fs'); function ifTruePush(bool, array, data) { if (bool) { diff --git a/package.json b/package.json index 094e740d..3c539c18 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ }, "dependencies": { "mime": "^1.2.11", - "underscore": "^1.7.0", "xml": "^1.0.0" }, "devDependencies": { From 3070e494ecfdf7baee25a69a8dc18e811812fc82 Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Mon, 15 Dec 2014 16:34:37 -0800 Subject: [PATCH 06/18] Changing param name to no_encode_fields in all needed places --- examples/simple.js | 6 +++--- lib/rss.js | 6 +++--- readme.md | 2 +- test/rss.test.js | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/simple.js b/examples/simple.js index c4d78fa9..7b847b4e 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -15,7 +15,7 @@ var feed = new RSS({ categories: ['Category 1','Category 2','Category 3'], pubDate: 'May 20, 2012 04:00:00 GMT', ttl: '60', - no_cdata_fields: ['title', 'category'], + no_encode_fields: ['title', 'category'], customNamespaces: { 'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd' }, @@ -47,7 +47,7 @@ var feed = new RSS({ /* loop over data and add to feed */ feed.item({ - title: 'item title', + 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 @@ -71,6 +71,6 @@ feed.item({ }); // cache the xml to send to clients -var xml = feed.xml(" "); +var xml = feed.xml("\t"); console.log(xml); \ No newline at end of file diff --git a/lib/rss.js b/lib/rss.js index cbb3224a..22a87b6d 100755 --- a/lib/rss.js +++ b/lib/rss.js @@ -22,7 +22,7 @@ function ifTruePushArray(bool, array, dataArray) { function generateXML (data){ // Field names that should not be CDATA wrapped - var no_cdata_fields = data.no_cdata_fields || []; + var no_encode_fields = data.no_encode_fields || []; // Handle formatting of CDATA-able output function output(field_name, value) { @@ -30,7 +30,7 @@ function generateXML (data){ return; } var ret_value = {}; - if (no_cdata_fields.indexOf(field_name) !== -1) { + if (no_encode_fields.indexOf(field_name) !== -1) { ret_value[field_name] = value; } else { ret_value[field_name] = { _cdata: value }; // CDATA @@ -164,7 +164,7 @@ function RSS (options, items) { this.geoRSS = options.geoRSS || false; this.custom_namespaces = options.custom_namespaces || {}; this.custom_elements = options.custom_elements || []; - this.no_cdata_fields = options.no_cdata_fields || []; + this.no_encode_fields = options.no_encode_fields || []; this.items = items || []; this.item = function (options) { diff --git a/readme.md b/readme.md index 01170c3d..3665925a 100644 --- a/readme.md +++ b/readme.md @@ -164,7 +164,7 @@ feed.item({ }); // cache the xml to send to clients -var xml = feed.xml(" "); +var xml = feed.xml("\t"); console.log(xml); ``` #### XML Output: diff --git a/test/rss.test.js b/test/rss.test.js index e39387f1..af58cccd 100644 --- a/test/rss.test.js +++ b/test/rss.test.js @@ -493,7 +493,7 @@ describe('rss module', function(done) { author: 'Dylan Greene', feed_url: 'http://example.com/rss.xml', site_url: 'http://example.com', - no_cdata_fields: ['title', 'author'] + no_encode_fields: ['title', 'author'] }); var expectedResult = '\n'+ From f0fc81fdf0d3f5bfc1130c0ac02ccf42d4f4e1e2 Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Mon, 15 Dec 2014 16:35:31 -0800 Subject: [PATCH 07/18] ... plus one more place --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 3665925a..94b45ed5 100644 --- a/readme.md +++ b/readme.md @@ -38,7 +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 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. Default is to wrap + * `no_encode_fields` _optional_ **array** Field names that shouldn't be wrapped with CDATA. Default is to wrap #### Add items to a feed An item can be used for a blog entry, project update, log entry, etc. Your RSS feed @@ -108,7 +108,7 @@ var feed = new RSS({ categories: ['Category 1','Category 2','Category 3'], pubDate: 'May 20, 2012 04:00:00 GMT', ttl: '60', - no_cdata_fields: ['title', 'category'], + no_encode_fields: ['title', 'category'], customNamespaces: { 'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd' }, From 6fba4536ef985faf41770d4823604a37f62b8f5f Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Tue, 16 Dec 2014 14:18:10 -0800 Subject: [PATCH 08/18] Going back to 'no_cdata_fields' for name. Clarifying use case in docs. Adding test for XML escaping when no_cdata_fields is used --- examples/simple.js | 2 +- lib/rss.js | 6 +++--- readme.md | 4 ++-- test/rss.test.js | 35 ++++++++++++++++++++++++++++++++++- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/examples/simple.js b/examples/simple.js index 7b847b4e..4d161b74 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -15,7 +15,7 @@ var feed = new RSS({ categories: ['Category 1','Category 2','Category 3'], pubDate: 'May 20, 2012 04:00:00 GMT', ttl: '60', - no_encode_fields: ['title', 'category'], + no_cdata_fields: ['title', 'category'], customNamespaces: { 'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd' }, diff --git a/lib/rss.js b/lib/rss.js index 22a87b6d..cbb3224a 100755 --- a/lib/rss.js +++ b/lib/rss.js @@ -22,7 +22,7 @@ function ifTruePushArray(bool, array, dataArray) { function generateXML (data){ // Field names that should not be CDATA wrapped - var no_encode_fields = data.no_encode_fields || []; + var no_cdata_fields = data.no_cdata_fields || []; // Handle formatting of CDATA-able output function output(field_name, value) { @@ -30,7 +30,7 @@ function generateXML (data){ return; } var ret_value = {}; - if (no_encode_fields.indexOf(field_name) !== -1) { + if (no_cdata_fields.indexOf(field_name) !== -1) { ret_value[field_name] = value; } else { ret_value[field_name] = { _cdata: value }; // CDATA @@ -164,7 +164,7 @@ function RSS (options, items) { this.geoRSS = options.geoRSS || false; this.custom_namespaces = options.custom_namespaces || {}; this.custom_elements = options.custom_elements || []; - this.no_encode_fields = options.no_encode_fields || []; + this.no_cdata_fields = options.no_cdata_fields || []; this.items = items || []; this.item = function (options) { diff --git a/readme.md b/readme.md index 94b45ed5..c1dd4495 100644 --- a/readme.md +++ b/readme.md @@ -38,7 +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 element (without 'xmlns:' prefix) * `custom_elements` _optional_ **array** Put additional elements in the feed (node-xml syntax) - * `no_encode_fields` _optional_ **array** Field names that shouldn't be wrapped with CDATA. Default is to wrap + * `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 An item can be used for a blog entry, project update, log entry, etc. Your RSS feed @@ -108,7 +108,7 @@ var feed = new RSS({ categories: ['Category 1','Category 2','Category 3'], pubDate: 'May 20, 2012 04:00:00 GMT', ttl: '60', - no_encode_fields: ['title', 'category'], + no_cdata_fields: ['title', 'category'], customNamespaces: { 'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd' }, diff --git a/test/rss.test.js b/test/rss.test.js index af58cccd..6b88ef02 100644 --- a/test/rss.test.js +++ b/test/rss.test.js @@ -493,7 +493,7 @@ describe('rss module', function(done) { author: 'Dylan Greene', feed_url: 'http://example.com/rss.xml', site_url: 'http://example.com', - no_encode_fields: ['title', 'author'] + no_cdata_fields: ['title', 'author'] }); var expectedResult = '\n'+ @@ -650,4 +650,37 @@ describe('rss module', function(done) { done(); }); + it('should xml escape fields that are specified in no_cdata_fields', function(done) { + var feed = new RSS({ + title: 'title', // This should be escaped + description: 'description', + generator: 'Example Generator', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + image_url: 'http://example.com/icon.png', + author: 'Dylan Greene', + categories: ['Category 1','Category 2','Category 3'], + pubDate: 'May 20, 2012 04:00:00 GMT', + docs: 'http://example.com/rss/docs.html', + copyright: '2013 Dylan Green', + language: 'en', + managingEditor: 'Dylan Green', + webMaster: 'Dylan Green', + ttl: '60', + no_cdata_fields: ['title'] + }); + + feed.item({ + title: 'This & That', // This should be escaped + description: 'BOGUS ITEM - REPLACE ME', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }); + + var expectedResult = '\n<b>title</b>http://example.comhttp://example.com/icon.png<b>title</b>http://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60This & Thathttp://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT'; + var result = feed.xml(); + + expect(result).to.equal(expectedResult); + done(); + }); }); From 38363d18354e5bb0425d5321db861d786012f59d Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Tue, 16 Dec 2014 14:52:55 -0800 Subject: [PATCH 09/18] Fixing typo in example --- examples/simple.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/simple.js b/examples/simple.js index 4d161b74..b6e013ed 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -19,7 +19,7 @@ var feed = new RSS({ customNamespaces: { 'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd' }, - custom: [ + 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'}, @@ -58,7 +58,7 @@ feed.item({ long: -111.933231, //optional longitude field for GeoRSS enclosure: {url:'https://www.google.com/images/srpr/logo11w.png'}, // enclosure: {file:'path-to-file'}, // optional enclosure - custom: [ + custom_elements: [ {'itunes:author': 'John Doe'}, {'itunes:subtitle': 'A short primer on table spices'}, {'itunes:image': { From e23f8f6a18f86cd4dc66f6c9812a7213f13d49ab Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Wed, 17 Dec 2014 11:25:28 -0800 Subject: [PATCH 10/18] README cleanup for custom_namespaces and custom_elements --- readme.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/readme.md b/readme.md index c1dd4495..18394b27 100644 --- a/readme.md +++ b/readme.md @@ -2,13 +2,6 @@ > RSS feed generator. Add RSS feeds to any project. Supports enclosures and GeoRSS. - - - - - - - ### Usage #### Create a new feed @@ -109,10 +102,10 @@ var feed = new RSS({ pubDate: 'May 20, 2012 04:00:00 GMT', ttl: '60', no_cdata_fields: ['title', 'category'], - customNamespaces: { + custom_namespaces: { 'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd' }, - custom: [ + 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'}, @@ -138,7 +131,6 @@ var feed = new RSS({ ] }); -/* loop over data and add to feed */ feed.item({ title: 'item title', description: 'use this for the content. It can include html.', @@ -151,7 +143,7 @@ feed.item({ long: -111.933231, //optional longitude field for GeoRSS enclosure: {url:'https://www.google.com/images/srpr/logo11w.png'}, // enclosure: {file:'path-to-file'}, // optional enclosure - custom: [ + custom_elements: [ {'itunes:author': 'John Doe'}, {'itunes:subtitle': 'A short primer on table spices'}, {'itunes:image': { From f528b848e415c496bc2fc0c0eabef311331703ed Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Wed, 17 Dec 2014 15:57:57 -0800 Subject: [PATCH 11/18] Fixing bug. Items passed in on RSS obj creation did not get processed by item() resulting in inconsistencies like missing category field. Added test for this issue --- lib/rss.js | 7 ++++++- test/rss.test.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/rss.js b/lib/rss.js index cbb3224a..806511c6 100755 --- a/lib/rss.js +++ b/lib/rss.js @@ -165,7 +165,7 @@ function RSS (options, items) { this.custom_namespaces = options.custom_namespaces || {}; this.custom_elements = options.custom_elements || []; this.no_cdata_fields = options.no_cdata_fields || []; - this.items = items || []; + this.items = []; // placeholder, see below for passed in items this.item = function (options) { options = options || {}; @@ -214,6 +214,11 @@ function RSS (options, items) { return '\n' + xml(generateXML(this), indent); }; + + // handle passed in items on obj creation using item() + if (items) { + return this.replace_items(items); + } } module.exports = RSS; diff --git a/test/rss.test.js b/test/rss.test.js index 6b88ef02..8eb50949 100644 --- a/test/rss.test.js +++ b/test/rss.test.js @@ -683,4 +683,38 @@ describe('rss module', function(done) { expect(result).to.equal(expectedResult); done(); }); + + it('should handle item array passed in on obj creation', function(done) { + var feed = new RSS({ + title: 'title', // This should be escaped + description: 'description', + generator: 'Example Generator', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + image_url: 'http://example.com/icon.png', + author: 'Dylan Greene', + categories: ['Category 1','Category 2','Category 3'], + pubDate: 'May 20, 2012 04:00:00 GMT', + docs: 'http://example.com/rss/docs.html', + copyright: '2013 Dylan Green', + language: 'en', + managingEditor: 'Dylan Green', + webMaster: 'Dylan Green', + ttl: '60', + no_cdata_fields: ['title'] + }, + [{ + title: 'This & That', // This should be escaped + description: 'BOGUS ITEM - REPLACE ME', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }]); + + var expectedResult = '\n<b>title</b>http://example.comhttp://example.com/icon.png<b>title</b>http://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60This & Thathttp://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT'; + var result = feed.xml(); + + expect(result).to.equal(expectedResult); + done(); + }); + }); From ce46bbf20e0c913cab38d8133b9d4f9ea3e9ed55 Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 19 Dec 2014 14:15:53 -0800 Subject: [PATCH 12/18] Moving tests from defunct PR into new branch --- examples/simple.js | 2 +- test/expectedOutput/concatenateItems.xml | 71 +++++ .../doNotWrapSomeElementsWithCdata.xml | 12 + test/expectedOutput/escapeCdataFields.xml | 35 +++ test/expectedOutput/replacedItems.xml | 71 +++++ test/expectedOutput/wrapElementsWithCdata.xml | 11 + test/index.js | 251 ++++++++++++++++++ 7 files changed, 452 insertions(+), 1 deletion(-) create mode 100644 test/expectedOutput/concatenateItems.xml create mode 100644 test/expectedOutput/doNotWrapSomeElementsWithCdata.xml create mode 100644 test/expectedOutput/escapeCdataFields.xml create mode 100644 test/expectedOutput/replacedItems.xml create mode 100644 test/expectedOutput/wrapElementsWithCdata.xml diff --git a/examples/simple.js b/examples/simple.js index b6e013ed..a3be5161 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -1,4 +1,4 @@ -var RSS = require('../lib/rss'); +var RSS = require('../lib/index'); /* let's create an rss feed */ var feed = new RSS({ diff --git a/test/expectedOutput/concatenateItems.xml b/test/expectedOutput/concatenateItems.xml new file mode 100644 index 00000000..aa5df699 --- /dev/null +++ b/test/expectedOutput/concatenateItems.xml @@ -0,0 +1,71 @@ + + + + <![CDATA[title]]> + + http://example.com + + http://example.com/icon.png + title + http://example.com + + Example Generator + Wed, 10 Dec 2014 19:04:57 GMT + + + Sun, 20 May 2012 04:00:00 GMT + + + + + http://example.com/rss/docs.html + 60 + + + + + <![CDATA[item 1]]> + + http://example.com/article1 + http://example.com/article1 + + Thu, 24 May 2012 04:00:00 GMT + + + <![CDATA[item 2]]> + + http://example.com/article2 + http://example.com/article2 + + Fri, 25 May 2012 04:00:00 GMT + + + <![CDATA[item 3]]> + + http://example.com/article3 + item3 + + Sat, 26 May 2012 04:00:00 GMT + + + <![CDATA[item 4 & html test with <strong>]]> + html]]> + http://example.com/article4?this&that + http://example.com/article4?this&that + + Sun, 27 May 2012 04:00:00 GMT + + + <![CDATA[item 5 & test for categories]]> + + http://example.com/article5 + http://example.com/article5 + + + + + + Mon, 28 May 2012 04:00:00 GMT + + + \ No newline at end of file diff --git a/test/expectedOutput/doNotWrapSomeElementsWithCdata.xml b/test/expectedOutput/doNotWrapSomeElementsWithCdata.xml new file mode 100644 index 00000000..f34c97b8 --- /dev/null +++ b/test/expectedOutput/doNotWrapSomeElementsWithCdata.xml @@ -0,0 +1,12 @@ + + + + title + + http://example.com + RSS for Node + Wed, 10 Dec 2014 19:04:57 GMT + + Dylan Greene + + \ No newline at end of file diff --git a/test/expectedOutput/escapeCdataFields.xml b/test/expectedOutput/escapeCdataFields.xml new file mode 100644 index 00000000..ffa1a782 --- /dev/null +++ b/test/expectedOutput/escapeCdataFields.xml @@ -0,0 +1,35 @@ + + + + <b>title</b> + + http://example.com + + http://example.com/icon.png + <b>title</b> + http://example.com + + Example Generator + Wed, 10 Dec 2014 19:04:57 GMT + + + Sun, 20 May 2012 04:00:00 GMT + + + + + http://example.com/rss/docs.html + 60 + + + + + This & That + + http://example.com/article1 + http://example.com/article1 + + Thu, 24 May 2012 04:00:00 GMT + + + \ No newline at end of file diff --git a/test/expectedOutput/replacedItems.xml b/test/expectedOutput/replacedItems.xml new file mode 100644 index 00000000..aa5df699 --- /dev/null +++ b/test/expectedOutput/replacedItems.xml @@ -0,0 +1,71 @@ + + + + <![CDATA[title]]> + + http://example.com + + http://example.com/icon.png + title + http://example.com + + Example Generator + Wed, 10 Dec 2014 19:04:57 GMT + + + Sun, 20 May 2012 04:00:00 GMT + + + + + http://example.com/rss/docs.html + 60 + + + + + <![CDATA[item 1]]> + + http://example.com/article1 + http://example.com/article1 + + Thu, 24 May 2012 04:00:00 GMT + + + <![CDATA[item 2]]> + + http://example.com/article2 + http://example.com/article2 + + Fri, 25 May 2012 04:00:00 GMT + + + <![CDATA[item 3]]> + + http://example.com/article3 + item3 + + Sat, 26 May 2012 04:00:00 GMT + + + <![CDATA[item 4 & html test with <strong>]]> + html]]> + http://example.com/article4?this&that + http://example.com/article4?this&that + + Sun, 27 May 2012 04:00:00 GMT + + + <![CDATA[item 5 & test for categories]]> + + http://example.com/article5 + http://example.com/article5 + + + + + + Mon, 28 May 2012 04:00:00 GMT + + + \ No newline at end of file diff --git a/test/expectedOutput/wrapElementsWithCdata.xml b/test/expectedOutput/wrapElementsWithCdata.xml new file mode 100644 index 00000000..687166cf --- /dev/null +++ b/test/expectedOutput/wrapElementsWithCdata.xml @@ -0,0 +1,11 @@ + + + + <![CDATA[title]]> + + http://example.com + RSS for Node + Wed, 10 Dec 2014 19:04:57 GMT + + + \ No newline at end of file diff --git a/test/index.js b/test/index.js index 36dec7a3..4a602550 100644 --- a/test/index.js +++ b/test/index.js @@ -300,3 +300,254 @@ test('custom namespaces', function(t) { t.equal(feed.xml({indent: true}), expectedOutput.customNamespaces); }); + +test('wrap elements with CDATA', function(t) { + t.plan(1); + + var feed = new RSS({ + title: 'title', + description: 'description', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com' + }); + + t.equal(feed.xml({indent: true}), expectedOutput.wrapElementsWithCdata); +}); + +test('do not wrap some elements with CDATA', function(t) { + t.plan(1); + + var feed = new RSS({ + title: 'title', + description: 'description', + author: 'Dylan Greene', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + no_cdata_fields: ['title', 'author'] + }); + + t.equal(feed.xml({indent: true}), expectedOutput.doNotWrapSomeElementsWithCdata); +}); + +test('concatenate array of items to existing items', function(t) { + t.plan(1); + var feed = new RSS({ + title: 'title', + description: 'description', + generator: 'Example Generator', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + image_url: 'http://example.com/icon.png', + author: 'Dylan Greene', + categories: ['Category 1','Category 2','Category 3'], + pubDate: 'May 20, 2012 04:00:00 GMT', + docs: 'http://example.com/rss/docs.html', + copyright: '2013 Dylan Green', + language: 'en', + managingEditor: 'Dylan Green', + webMaster: 'Dylan Green', + ttl: '60' + }); + + feed.item({ + title: 'item 1', + description: 'description 1', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }); + + var additional_items = [ + { + title: 'item 2', + description: 'description 2', + url: 'http://example.com/article2', + date: 'May 25, 2012 04:00:00 GMT' + }, + { + title: 'item 3', + description: 'description 3', + url: 'http://example.com/article3', + guid: 'item3', + date: 'May 26, 2012 04:00:00 GMT' + }, + { + title: 'item 4 & html test with ', + description: 'description 4 uses some html', + url: 'http://example.com/article4?this&that', + author: 'Guest Author', + date: 'May 27, 2012 04:00:00 GMT' + }, + { + title: 'item 5 & test for categories', + description: 'description 5', + url: 'http://example.com/article5', + categories: ['Category 1','Category 2','Category 3','Category 4'], + author: 'Guest Author', + date: 'May 28, 2012 04:00:00 GMT' + } + ]; + + feed.concat_items(additional_items); + + t.equal(feed.xml({indent: true}), expectedOutput.concatenateItems); +}); + +test('replace items with array of new items', function(t) { + t.plan(1); + var feed = new RSS({ + title: 'title', + description: 'description', + generator: 'Example Generator', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + image_url: 'http://example.com/icon.png', + author: 'Dylan Greene', + categories: ['Category 1','Category 2','Category 3'], + pubDate: 'May 20, 2012 04:00:00 GMT', + docs: 'http://example.com/rss/docs.html', + copyright: '2013 Dylan Green', + language: 'en', + managingEditor: 'Dylan Green', + webMaster: 'Dylan Green', + ttl: '60' + }); + + feed.item({ + title: 'BOGUS ITEM - REPLACE ME', + description: 'BOGUS ITEM - REPLACE ME', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }); + + var new_items = [ + { + title: 'item 1', + description: 'description 1', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }, + { + title: 'item 2', + description: 'description 2', + url: 'http://example.com/article2', + date: 'May 25, 2012 04:00:00 GMT' + }, + { + title: 'item 3', + description: 'description 3', + url: 'http://example.com/article3', + guid: 'item3', + date: 'May 26, 2012 04:00:00 GMT' + }, + { + title: 'item 4 & html test with ', + description: 'description 4 uses some html', + url: 'http://example.com/article4?this&that', + author: 'Guest Author', + date: 'May 27, 2012 04:00:00 GMT' + }, + { + title: 'item 5 & test for categories', + description: 'description 5', + url: 'http://example.com/article5', + categories: ['Category 1','Category 2','Category 3','Category 4'], + author: 'Guest Author', + date: 'May 28, 2012 04:00:00 GMT' + } + ]; + + feed.replace_items(new_items); + t.equal(feed.xml({indent: true}), expectedOutput.replacedItems); +}); + +test('xml escape fields specified in no_cdata_fields', function(t) { + t.plan(1); + var feed = new RSS({ + title: 'title', // This should be escaped + description: 'description', + generator: 'Example Generator', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + image_url: 'http://example.com/icon.png', + author: 'Dylan Greene', + categories: ['Category 1','Category 2','Category 3'], + pubDate: 'May 20, 2012 04:00:00 GMT', + docs: 'http://example.com/rss/docs.html', + copyright: '2013 Dylan Green', + language: 'en', + managingEditor: 'Dylan Green', + webMaster: 'Dylan Green', + ttl: '60', + no_cdata_fields: ['title'] + }); + + feed.item({ + title: 'This & That', // This should be escaped + description: 'TEST & SUCCEED', + url: 'http://example.com/article1', + date: 'May 24, 2012 04:00:00 GMT' + }); + + t.equal(feed.xml({indent: true}), expectedOutput.escapeCdataFields); +}); + +test('process item array passed to RSS object creation', function(t) { + t.plan(1); + + var item_array = [ + { + title: 'item 2', + description: 'description 2', + url: 'http://example.com/article2', + date: 'May 25, 2012 04:00:00 GMT' + }, + { + title: 'item 3', + description: 'description 3', + url: 'http://example.com/article3', + guid: 'item3', + date: 'May 26, 2012 04:00:00 GMT' + }, + { + title: 'item 4 & html test with ', + description: 'description 4 uses some html', + url: 'http://example.com/article4?this&that', + author: 'Guest Author', + date: 'May 27, 2012 04:00:00 GMT' + }, + { + title: 'item 5 & test for categories', + description: 'description 5', + url: 'http://example.com/article5', + categories: ['Category 1','Category 2','Category 3','Category 4'], + author: 'Guest Author', + date: 'May 28, 2012 04:00:00 GMT' + } + ]; + + var feed = new RSS({ + title: 'title', // This should be escaped + description: 'description', + generator: 'Example Generator', + feed_url: 'http://example.com/rss.xml', + site_url: 'http://example.com', + image_url: 'http://example.com/icon.png', + author: 'Dylan Greene', + categories: ['Category 1','Category 2','Category 3'], + pubDate: 'May 20, 2012 04:00:00 GMT', + docs: 'http://example.com/rss/docs.html', + copyright: '2013 Dylan Green', + language: 'en', + managingEditor: 'Dylan Green', + webMaster: 'Dylan Green', + ttl: '60', + no_cdata_fields: ['title'] + }, + item_array); + + console.log(feed.xml({indent: true})); + + t.equal(feed.xml({indent: true}), expectedOutput.escapeCdataFields); +}); + + From 5993cd5568c6bc376b3f797df092a251ea2338cc Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 19 Dec 2014 17:11:35 -0800 Subject: [PATCH 13/18] Added tests for new functionality --- .../processItemArrayOnObjCreation.xml | 63 +++++++++++++++++++ test/index.js | 4 +- 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 test/expectedOutput/processItemArrayOnObjCreation.xml diff --git a/test/expectedOutput/processItemArrayOnObjCreation.xml b/test/expectedOutput/processItemArrayOnObjCreation.xml new file mode 100644 index 00000000..5cd806e6 --- /dev/null +++ b/test/expectedOutput/processItemArrayOnObjCreation.xml @@ -0,0 +1,63 @@ + + + + <b>title</b> + + http://example.com + + http://example.com/icon.png + <b>title</b> + http://example.com + + Example Generator + Wed, 10 Dec 2014 19:04:57 GMT + + + Sun, 20 May 2012 04:00:00 GMT + + + + + http://example.com/rss/docs.html + 60 + + + + + item 2 + + http://example.com/article2 + http://example.com/article2 + + Fri, 25 May 2012 04:00:00 GMT + + + item 3 + + http://example.com/article3 + item3 + + Sat, 26 May 2012 04:00:00 GMT + + + item 4 & html test with <strong> + html]]> + http://example.com/article4?this&that + http://example.com/article4?this&that + + Sun, 27 May 2012 04:00:00 GMT + + + item 5 & test for categories + + http://example.com/article5 + http://example.com/article5 + + + + + + Mon, 28 May 2012 04:00:00 GMT + + + \ No newline at end of file diff --git a/test/index.js b/test/index.js index 4a602550..2de08713 100644 --- a/test/index.js +++ b/test/index.js @@ -545,9 +545,9 @@ test('process item array passed to RSS object creation', function(t) { }, item_array); - console.log(feed.xml({indent: true})); + // console.log(feed.xml({indent: true})); - t.equal(feed.xml({indent: true}), expectedOutput.escapeCdataFields); + t.equal(feed.xml({indent: true}), expectedOutput.processItemArrayOnObjCreation); }); From 6478f12abd83fed1ba2f2ddaaa7d52f0b81d3024 Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 19 Dec 2014 17:14:14 -0800 Subject: [PATCH 14/18] Missing mime dependency and a dupe dep --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index eaa2646e..07475029 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "Patrick Garman ", "Fred Morstatter", "Eric Vantillard ", - "Jason Karns " + "Jason Karns ", + "Kip Gebhardt " ], "repository": { "type": "git", @@ -60,7 +61,7 @@ "xml": "^1.0.0" }, "devDependencies": { - "folderify": "^0.6.0", + "mime": "^1.2.11", "grunt": "^0.4.5", "grunt-contrib-jshint": "^0.10.0", "grunt-release": "^0.9.0", From 65a9d4295cbeea3e4118e0cad5d6f8085174847b Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 19 Dec 2014 17:16:52 -0800 Subject: [PATCH 15/18] Removing old mocha test --- test/rss.test.js | 720 ----------------------------------------------- 1 file changed, 720 deletions(-) delete mode 100644 test/rss.test.js diff --git a/test/rss.test.js b/test/rss.test.js deleted file mode 100644 index 8eb50949..00000000 --- a/test/rss.test.js +++ /dev/null @@ -1,720 +0,0 @@ -/* - use `npm test` to run tests using mocha -*/ - -var RSS = require('../lib/rss'); -var expect = require('chai').expect; -var xml2js = require('xml2js'); -var Q = require('q'); - -describe('rss module', function(done) { - - it('should work with an empty feed', function(done) { - var feed = new RSS(); - expect(feed.xml()).to.equal('\n<![CDATA[Untitled RSS Feed]]>http://github.com/dylang/node-rssRSS for Node' + new Date().toUTCString() +''); - feed.item(); - expect(feed.xml()).to.equal('\n<![CDATA[Untitled RSS Feed]]>http://github.com/dylang/node-rssRSS for Node' + new Date().toUTCString() +'<![CDATA[No title]]>No title'); - done(); - }); - - var simpleFeed = function() { - var feed = new RSS({ - title: 'title', - description: 'description', - generator: 'Example Generator', - feed_url: 'http://example.com/rss.xml', - site_url: 'http://example.com', - image_url: 'http://example.com/icon.png', - author: 'Dylan Greene', - categories: ['Category 1','Category 2','Category 3'], - pubDate: 'May 20, 2012 04:00:00 GMT', - docs: 'http://example.com/rss/docs.html', - copyright: '2013 Dylan Green', - language: 'en', - managingEditor: 'Dylan Green', - webMaster: 'Dylan Green', - ttl: '60' - }); - - feed.item({ - title: 'item 1', - description: 'description 1', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT' - }) - .item({ - title: 'item 2', - description: 'description 2', - url: 'http://example.com/article2', - date: 'May 25, 2012 04:00:00 GMT' - }) - .item({ - title: 'item 3', - description: 'description 3', - url: 'http://example.com/article3', - guid: 'item3', - date: 'May 26, 2012 04:00:00 GMT' - }) - .item({ - title: 'item 4 & html test with ', - description: 'description 4 uses some html', - url: 'http://example.com/article4?this&that', - author: 'Guest Author', - date: 'May 27, 2012 04:00:00 GMT' - }) - .item({ - title: 'item 5 & test for categories', - description: 'description 5', - url: 'http://example.com/article5', - categories: ['Category 1','Category 2','Category 3','Category 4'], - author: 'Guest Author', - date: 'May 28, 2012 04:00:00 GMT' - }); - return feed; - }; - - it('should work with indentation', function(done) { - var feed = simpleFeed(); - var xml = feed.xml(true); - var parseString = Q.nbind(xml2js.parseString,xml2js); - - var feedToXml = parseString(feed.xml()); - var feedToXmlIndent = parseString(feed.xml(true)); - Q.all([feedToXml,feedToXmlIndent]).spread(function (xml,xmlIndent){ - expect(JSON.stringify(xml)).to.equal(JSON.stringify(xmlIndent)); - }).done(done()); - }); - - it('should work with an easy test', function(done) { - var feed = simpleFeed(); - var expectedResult = '\n<![CDATA[title]]>http://example.comhttp://example.com/icon.pngtitlehttp://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60<![CDATA[item 1]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT<![CDATA[item 2]]>http://example.com/article2http://example.com/article2Fri, 25 May 2012 04:00:00 GMT<![CDATA[item 3]]>http://example.com/article3item3Sat, 26 May 2012 04:00:00 GMT<![CDATA[item 4 & html test with <strong>]]>html]]>http://example.com/article4?this&thathttp://example.com/article4?this&thatSun, 27 May 2012 04:00:00 GMT<![CDATA[item 5 & test for categories]]>http://example.com/article5http://example.com/article5Mon, 28 May 2012 04:00:00 GMT'; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - it('should work without image_url', 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', - categories: ['Category 1','Category 2','Category 3'], - pubDate: 'May 20, 2012 04:00:00 GMT', - docs: 'http://example.com/rss/docs.html', - copyright: '2013 Dylan Green', - language: 'en', - managingEditor: 'Dylan Green', - webMaster: 'Dylan Green', - ttl: '60' - }); - - feed.item({ - title: 'item 1', - description: 'description 1', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT' - }) - .item({ - title: 'item 2', - description: 'description 2', - url: 'http://example.com/article2', - date: 'May 25, 2012 04:00:00 GMT' - }) - .item({ - title: 'item 3', - description: 'description 3', - url: 'http://example.com/article3', - guid: 'item3', - date: 'May 26, 2012 04:00:00 GMT' - }) - .item({ - title: 'item 4 & html test with ', - description: 'description 4 uses some html', - url: 'http://example.com/article4?this&that', - author: 'Guest Author', - date: 'May 27, 2012 04:00:00 GMT' - }) - .item({ - title: 'item 5 & test for categories', - description: 'description 5', - url: 'http://example.com/article5', - categories: ['Category 1','Category 2','Category 3','Category 4'], - author: 'Guest Author', - date: 'May 28, 2012 04:00:00 GMT' - }); - - var expectedResult = '\n<![CDATA[title]]>http://example.comRSS for Node' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60<![CDATA[item 1]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT<![CDATA[item 2]]>http://example.com/article2http://example.com/article2Fri, 25 May 2012 04:00:00 GMT<![CDATA[item 3]]>http://example.com/article3item3Sat, 26 May 2012 04:00:00 GMT<![CDATA[item 4 & html test with <strong>]]>html]]>http://example.com/article4?this&thathttp://example.com/article4?this&thatSun, 27 May 2012 04:00:00 GMT<![CDATA[item 5 & test for categories]]>http://example.com/article5http://example.com/article5Mon, 28 May 2012 04:00:00 GMT'; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - it('should work with an enclosure', 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' - }); - - feed.item({ - title: 'item 1', - description: 'description 1', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT', - enclosure : 'incorrect value' - }); - - feed.item({ - title: 'item 2', - description: 'description 2', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT', - enclosure : {url: '/media/some-file.flv'} - }); - - feed.item({ - title: 'item 3', - description: 'description 3', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT', - enclosure : {url: '/media/image.png', file : __dirname+'/image.png'} - }); - - var expectedResult = '\n<![CDATA[title]]>http://example.comRSS for Node' + new Date().toUTCString() +''+ - '' + - '<![CDATA[item 1]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT'+ - '<![CDATA[item 2]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT'+ - '<![CDATA[item 3]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT'+ - ''; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - - it('should work with geoRSS', 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' - }); - - feed.item({ - title: 'item 1', - description: 'description 1', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT', - lat: 12232, - long: 13333.23323 - }); - - feed.item({ - title: 'item 2', - description: 'description 2', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT' - }); - - var expectedResult = '\n<![CDATA[title]]>http://example.comRSS for Node' + new Date().toUTCString() +''+ - '' + - '<![CDATA[item 1]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT1223213333.23323'+ - '<![CDATA[item 2]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT'+ - ''; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - it('should work with PubSubHubbub hub', function(done) { - var feed = new RSS({ - title: 'title', - description: 'description', - feed_url: 'http://example.com/rss.xml', - site_url: 'http://example.com', - hub: 'http://example.com/hub' - }); - - var expectedResult = '\n'+ - ''+ - ''+ - '<![CDATA[title]]>'+ - ''+ - 'http://example.com'+ - 'RSS for Node'+ - '' + new Date().toUTCString() +''+ - ''+ - ''+ - ''+ - ''; - - var result = feed.xml(); - - 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 ='\n'+ - ''+ - '' + - '<![CDATA[title]]>' + - '' + - 'http://example.com' + - 'RSS for Node' + - '' + new Date().toUTCString() +'' + - '' + - '' + - 'Sun, 20 May 2012 04:00:00 GMT' + - '' + - '60' + - 'A show about everything' + - 'John Doe' + - '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' + - '' + - 'John Doe' + - 'john.doe@example.com' + - '' + - '' + - '' + - '' + - '' + - '' + - '<![CDATA[item 1]]>' + - '' + - 'http://example.com/article1' + - 'http://example.com/article1' + - '' + - 'Thu, 24 May 2012 04:00:00 GMT' + - 'John Doe' + - 'A short primer on table spices' + - '' + - '7:04' + - '' + - '' + - ''; - 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 ='\n'+ - ''+ - '' + - '<![CDATA[title]]>' + - '' + - 'http://example.com' + - 'RSS for Node' + - '' + new Date().toUTCString() +'' + - '' + - '' + - 'Sun, 20 May 2012 04:00:00 GMT' + - '' + - '60' + - 'A show about everything' + - 'John Doe' + - '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' + - '' + - 'John Doe' + - 'john.doe@example.com' + - '' + - '' + - '' + - '' + - '' + - '' + - '<![CDATA[item 1]]>' + - '' + - 'http://example.com/article1' + - 'http://example.com/article1' + - '' + - 'Thu, 24 May 2012 04:00:00 GMT' + - 'John Doe' + - 'A short primer on table spices' + - '' + - '7:04' + - '' + - '' + - ''; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - 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' - }); - - var expectedResult = '\n'+ - ''+ - ''+ - '<![CDATA[title]]>'+ - ''+ - 'http://example.com'+ - 'RSS for Node'+ - '' + new Date().toUTCString() +''+ - ''+ - ''+ - ''; - - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - it('should not wrap specific fields with CDATA', function(done) { - var feed = new RSS({ - title: 'title', - description: 'description', - author: 'Dylan Greene', - feed_url: 'http://example.com/rss.xml', - site_url: 'http://example.com', - no_cdata_fields: ['title', 'author'] - }); - - var expectedResult = '\n'+ - ''+ - ''+ - 'title'+ - ''+ - 'http://example.com'+ - 'RSS for Node'+ - '' + new Date().toUTCString() +''+ - ''+ - 'Dylan Greene' + - ''+ - ''; - - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - it('should allow concatenation of array of items to existing items', function(done) { - var feed = new RSS({ - title: 'title', - description: 'description', - generator: 'Example Generator', - feed_url: 'http://example.com/rss.xml', - site_url: 'http://example.com', - image_url: 'http://example.com/icon.png', - author: 'Dylan Greene', - categories: ['Category 1','Category 2','Category 3'], - pubDate: 'May 20, 2012 04:00:00 GMT', - docs: 'http://example.com/rss/docs.html', - copyright: '2013 Dylan Green', - language: 'en', - managingEditor: 'Dylan Green', - webMaster: 'Dylan Green', - ttl: '60' - }); - - feed.item({ - title: 'item 1', - description: 'description 1', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT' - }); - - var additional_items = [{ - title: 'item 2', - description: 'description 2', - url: 'http://example.com/article2', - date: 'May 25, 2012 04:00:00 GMT' - }, - { - title: 'item 3', - description: 'description 3', - url: 'http://example.com/article3', - guid: 'item3', - date: 'May 26, 2012 04:00:00 GMT' - }, - { - title: 'item 4 & html test with ', - description: 'description 4 uses some html', - url: 'http://example.com/article4?this&that', - author: 'Guest Author', - date: 'May 27, 2012 04:00:00 GMT' - }, - { - title: 'item 5 & test for categories', - description: 'description 5', - url: 'http://example.com/article5', - categories: ['Category 1','Category 2','Category 3','Category 4'], - author: 'Guest Author', - date: 'May 28, 2012 04:00:00 GMT' - }]; - - feed.concat_items(additional_items); - - var expectedResult = '\n<![CDATA[title]]>http://example.comhttp://example.com/icon.pngtitlehttp://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60<![CDATA[item 1]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT<![CDATA[item 2]]>http://example.com/article2http://example.com/article2Fri, 25 May 2012 04:00:00 GMT<![CDATA[item 3]]>http://example.com/article3item3Sat, 26 May 2012 04:00:00 GMT<![CDATA[item 4 & html test with <strong>]]>html]]>http://example.com/article4?this&thathttp://example.com/article4?this&thatSun, 27 May 2012 04:00:00 GMT<![CDATA[item 5 & test for categories]]>http://example.com/article5http://example.com/article5Mon, 28 May 2012 04:00:00 GMT'; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - it('should allow replacement of all items with of array of new items', function(done) { - var feed = new RSS({ - title: 'title', - description: 'description', - generator: 'Example Generator', - feed_url: 'http://example.com/rss.xml', - site_url: 'http://example.com', - image_url: 'http://example.com/icon.png', - author: 'Dylan Greene', - categories: ['Category 1','Category 2','Category 3'], - pubDate: 'May 20, 2012 04:00:00 GMT', - docs: 'http://example.com/rss/docs.html', - copyright: '2013 Dylan Green', - language: 'en', - managingEditor: 'Dylan Green', - webMaster: 'Dylan Green', - ttl: '60' - }); - - feed.item({ - title: 'BOGUS ITEM - REPLACE ME', - description: 'BOGUS ITEM - REPLACE ME', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT' - }); - - var additional_items = [ - { - title: 'item 1', - description: 'description 1', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT' - }, - { - title: 'item 2', - description: 'description 2', - url: 'http://example.com/article2', - date: 'May 25, 2012 04:00:00 GMT' - }, - { - title: 'item 3', - description: 'description 3', - url: 'http://example.com/article3', - guid: 'item3', - date: 'May 26, 2012 04:00:00 GMT' - }, - { - title: 'item 4 & html test with ', - description: 'description 4 uses some html', - url: 'http://example.com/article4?this&that', - author: 'Guest Author', - date: 'May 27, 2012 04:00:00 GMT' - }, - { - title: 'item 5 & test for categories', - description: 'description 5', - url: 'http://example.com/article5', - categories: ['Category 1','Category 2','Category 3','Category 4'], - author: 'Guest Author', - date: 'May 28, 2012 04:00:00 GMT' - }]; - - feed.replace_items(additional_items); - - var expectedResult = '\n<![CDATA[title]]>http://example.comhttp://example.com/icon.pngtitlehttp://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60<![CDATA[item 1]]>http://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT<![CDATA[item 2]]>http://example.com/article2http://example.com/article2Fri, 25 May 2012 04:00:00 GMT<![CDATA[item 3]]>http://example.com/article3item3Sat, 26 May 2012 04:00:00 GMT<![CDATA[item 4 & html test with <strong>]]>html]]>http://example.com/article4?this&thathttp://example.com/article4?this&thatSun, 27 May 2012 04:00:00 GMT<![CDATA[item 5 & test for categories]]>http://example.com/article5http://example.com/article5Mon, 28 May 2012 04:00:00 GMT'; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - it('should xml escape fields that are specified in no_cdata_fields', function(done) { - var feed = new RSS({ - title: 'title', // This should be escaped - description: 'description', - generator: 'Example Generator', - feed_url: 'http://example.com/rss.xml', - site_url: 'http://example.com', - image_url: 'http://example.com/icon.png', - author: 'Dylan Greene', - categories: ['Category 1','Category 2','Category 3'], - pubDate: 'May 20, 2012 04:00:00 GMT', - docs: 'http://example.com/rss/docs.html', - copyright: '2013 Dylan Green', - language: 'en', - managingEditor: 'Dylan Green', - webMaster: 'Dylan Green', - ttl: '60', - no_cdata_fields: ['title'] - }); - - feed.item({ - title: 'This & That', // This should be escaped - description: 'BOGUS ITEM - REPLACE ME', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT' - }); - - var expectedResult = '\n<b>title</b>http://example.comhttp://example.com/icon.png<b>title</b>http://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60This & Thathttp://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT'; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - - it('should handle item array passed in on obj creation', function(done) { - var feed = new RSS({ - title: 'title', // This should be escaped - description: 'description', - generator: 'Example Generator', - feed_url: 'http://example.com/rss.xml', - site_url: 'http://example.com', - image_url: 'http://example.com/icon.png', - author: 'Dylan Greene', - categories: ['Category 1','Category 2','Category 3'], - pubDate: 'May 20, 2012 04:00:00 GMT', - docs: 'http://example.com/rss/docs.html', - copyright: '2013 Dylan Green', - language: 'en', - managingEditor: 'Dylan Green', - webMaster: 'Dylan Green', - ttl: '60', - no_cdata_fields: ['title'] - }, - [{ - title: 'This & That', // This should be escaped - description: 'BOGUS ITEM - REPLACE ME', - url: 'http://example.com/article1', - date: 'May 24, 2012 04:00:00 GMT' - }]); - - var expectedResult = '\n<b>title</b>http://example.comhttp://example.com/icon.png<b>title</b>http://example.comExample Generator' + new Date().toUTCString() +'Sun, 20 May 2012 04:00:00 GMThttp://example.com/rss/docs.html60This & Thathttp://example.com/article1http://example.com/article1Thu, 24 May 2012 04:00:00 GMT'; - var result = feed.xml(); - - expect(result).to.equal(expectedResult); - done(); - }); - -}); From fa4d01575976b3bf31f20ef370a94f4bfa675489 Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 19 Dec 2014 17:24:37 -0800 Subject: [PATCH 16/18] Documentation update and readme generation --- lib/index.js | 4 +- readme.md | 85 +++++++++++------------------------- templates/readme/examples.md | 2 +- templates/readme/usage.md | 15 ++++++- 4 files changed, 42 insertions(+), 64 deletions(-) diff --git a/lib/index.js b/lib/index.js index 0e5ec2e4..0c8fb0d3 100755 --- a/lib/index.js +++ b/lib/index.js @@ -172,7 +172,7 @@ function RSS (options, items) { this.custom_namespaces = options.custom_namespaces || {}; this.custom_elements = options.custom_elements || []; this.no_cdata_fields = options.no_cdata_fields || []; - this.items = []; // placeholder, see below for passed in items + this.items = []; // passed in "items" handled below this.item = function (options) { options = options || {}; @@ -222,7 +222,7 @@ function RSS (options, items) { xml(generateXML(this), indent); }; - // handle passed in items on obj creation using item() + // handle passed in "items" on obj creation using item() if (items) { return this.replace_items(items); } diff --git a/readme.md b/readme.md index f59d8a00..aa66f891 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,13 @@ > RSS feed generator. Add RSS feeds to any project. Supports enclosures and GeoRSS. + + + + + + + ### Usage #### Create a new feed @@ -34,10 +41,16 @@ var feed = new RSS(feedOptions); * `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 + An item can be used for a blog entry, project update, log entry, etc. Your RSS feed can have any number of items. Most feeds use 20 or fewer items. +```js +feed.item(itemOptions); +``` + ##### itemOptions + * `title` **string** Title of this particular item. * `description` **string** Content for the item. Can contain html but link and image urls must be absolute path including hostname. * `url` **url string** Url to the item. This could be a blog entry. @@ -55,21 +68,20 @@ can have any number of items. Most feeds use 20 or fewer items. * `long` _optional_ **number** The longitude coordinate of the item. * `custom_elements` _optional_ **array** Put additional elements in the item (node-xml syntax) -##### Add single item +###### Add single item ```js feed.item(itemOptions); ``` -##### Concatenate an array of items +###### Concatenate an array of items ```js feed.concat_items(arrayOfItemOptions); ``` -##### Replace items with a new array of items +###### Replace items with a new array of items ```js feed.replace_items(arrayOfItemOptions); ``` -#### Feed XML - +##### Feed XML ```js var xml = feed.xml({indent: true}); ``` @@ -84,11 +96,10 @@ For example you can use `'\t'` for tab character, or `' '` for two-space tabs. ### Example Usage (examples/simple.js) - ```js -var RSS = require('../lib/rss'); +var RSS = require('rss'); -/* let's create an rss feed */ +/* lets create an rss feed */ var feed = new RSS({ title: 'title', description: 'description', @@ -103,11 +114,10 @@ var feed = new RSS({ categories: ['Category 1','Category 2','Category 3'], pubDate: 'May 20, 2012 04:00:00 GMT', ttl: '60', - no_cdata_fields: ['title', 'category'], - custom_namespaces: { + customNamespaces: { 'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd' }, - custom_elements: [ + 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'}, @@ -133,6 +143,7 @@ var feed = new RSS({ ] }); +/* loop over data and add to feed */ feed.item({ title: 'item title', description: 'use this for the content. It can include html.', @@ -143,9 +154,8 @@ 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:'https://www.google.com/images/srpr/logo11w.png'}, - // enclosure: {file:'path-to-file'}, // optional enclosure - custom_elements: [ + enclosure: {url:'...', file:'path-to-file'}, // optional enclosure + custom: [ {'itunes:author': 'John Doe'}, {'itunes:subtitle': 'A short primer on table spices'}, {'itunes:image': { @@ -158,52 +168,7 @@ feed.item({ }); // cache the xml to send to clients -var xml = feed.xml("\t"); -console.log(xml); -``` -#### XML Output: -```xml - - - - title - - http://example.com - - http://example.com/icon.png - title - http://example.com - - RSS for Node - Sat, 13 Dec 2014 01:44:19 GMT - - Sun, 20 May 2012 04:00:00 GMT - - - - - http://example.com/rss/docs.html - 60 - Category 1 - Category 2 - Category 3 - - item title - - http://example.com/article4?this&that - 1123 - Category 1 - Category 2 - Category 3 - Category 4 - - Sun, 27 May 2012 07:00:00 GMT - 33.417974 - -111.933231 - - - - +var xml = feed.xml(); ``` diff --git a/templates/readme/examples.md b/templates/readme/examples.md index 90181e3b..07fdabb9 100644 --- a/templates/readme/examples.md +++ b/templates/readme/examples.md @@ -1,5 +1,5 @@ ## Example Usage - +(examples/simple.js) ```js var RSS = require('rss'); diff --git a/templates/readme/usage.md b/templates/readme/usage.md index fe0528eb..465f126d 100644 --- a/templates/readme/usage.md +++ b/templates/readme/usage.md @@ -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 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 @@ -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}); ``` From 5450f8d096d6e5d6cf01799415f13ba2e3c607e0 Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 19 Dec 2014 17:32:52 -0800 Subject: [PATCH 17/18] Moving mime to dependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 07475029..f04c8fdc 100644 --- a/package.json +++ b/package.json @@ -58,10 +58,10 @@ "dependencies": { "folderify": "^0.6.0", "mime-types": "^2.0.3", + "mime": "^1.2.11", "xml": "^1.0.0" }, "devDependencies": { - "mime": "^1.2.11", "grunt": "^0.4.5", "grunt-contrib-jshint": "^0.10.0", "grunt-release": "^0.9.0", From c1f64600a39b5e1800c3405ca72bb6fc10ef738b Mon Sep 17 00:00:00 2001 From: Kip Gebhardt Date: Fri, 19 Dec 2014 17:39:18 -0800 Subject: [PATCH 18/18] Indenting change on example. Commenting. --- examples/simple.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/examples/simple.js b/examples/simple.js index a3be5161..224f8a26 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -45,19 +45,19 @@ var feed = new RSS({ ] }); -/* loop over data and add to feed */ +// Add an item/article too the feed feed.item({ - title: 'item title & fun', - description: 'use this for the content. It can include html.', + 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','Category 3','Category 4'], // optional - array of item categories + 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'}, // optional enclosure + 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'}, @@ -70,7 +70,6 @@ feed.item({ ] }); -// cache the xml to send to clients -var xml = feed.xml("\t"); - +// generate xml with default indent (4 sp) +var xml = feed.xml({indent: true}); console.log(xml); \ No newline at end of file