diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6e38c10 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# Get the plugin for your editor and your +# tab settings will be set automatically. +# http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with no newline ending every file +[*] +end_of_line = lf +insert_final_newline = false + +# Indentation override for all JS under lib directory +[*.js] +indent_style = space +indent_size = 4 diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..f57a8ff --- /dev/null +++ b/.jshintrc @@ -0,0 +1,13 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "sub": true, + "undef": true, + "boss": true, + "eqnull": true, + "node": true +} diff --git a/Gruntfile.js b/Gruntfile.js index 080dd02..3622e9e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,3 +1,55 @@ +'use strict'; + module.exports = function(grunt) { - grunt.loadNpmTasks('grunt-release'); + + /** + * grunt release or grunt release:patch increment the patch number + * grunt release:minor increments the minor version number + * grunt release:major increments the major version number + * + + * grunt readme to generate the readme (you might need to do grunt repos first) + */ + + + require('time-grunt')(grunt); + + grunt.initConfig({ + mochaTest: { + notify: { + src: 'test/**/*.test.js', + options: { + reporter: 'spec' + } + } + }, + + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: [ + 'Gruntfile.js', + 'lib/**/*.js', + 'tests/**/*.js' + ] + } + + }); + + require('load-grunt-tasks')(grunt); + + grunt.registerTask('test', [ + 'jshint', + 'mochaTest' + ]); + + grunt.registerTask('default', [ + 'test' + ]); + + grunt.registerTask('pre-publish', [ + 'test', + 'readme' + ]); }; diff --git a/lib/rss.js b/lib/rss.js index e0c1e53..11ca491 100755 --- a/lib/rss.js +++ b/lib/rss.js @@ -1,58 +1,9 @@ 'use strict'; -var XML = require('xml'), +var xml = require('xml'), mime = require('mime'), fs = require('fs'); -function RSS (options, items) { - options = options || {}; - - this.title = options.title || 'Untitled RSS Feed'; - this.description = options.description || ''; - this.generator = options.generator || 'RSS for Node'; - this.feed_url = options.feed_url; - this.site_url = options.site_url; - this.image_url = options.image_url; - this.author = options.author; - this.categories = options.categories; - this.pubDate = options.pubDate; - this.hub = options.hub; - this.docs = options.docs; - this.copyright = options.copyright; - this.language = options.language; - this.managingEditor = options.managingEditor; - this.webMaster = options.webMaster; - this.ttl = options.ttl; - //option to return feed as GeoRSS is set automatically if feed.lat/long is used - this.geoRSS = options.geoRSS || false; - this.items = items || []; - - this.item = function (options) { - options = options || {}; - var item = { - title: options.title || 'No title', - description: options.description || '', - url: options.url, - guid: options.guid, - categories: options.categories || [], - author: options.author, - date: options.date, - lat: options.lat, - long: options.long, - enclosure: options.enclosure || false - }; - - this.items.push(item); - return this; - }; - - this.xml = function(indent) { - return '\n' - + XML(generateXML(this), indent); - } - -} - function ifTruePush(bool, array, data) { if (bool) { array.push(data); @@ -158,4 +109,52 @@ function generateXML (data){ }; } +function RSS (options, items) { + options = options || {}; + + this.title = options.title || 'Untitled RSS Feed'; + this.description = options.description || ''; + this.generator = options.generator || 'RSS for Node'; + this.feed_url = options.feed_url; + this.site_url = options.site_url; + this.image_url = options.image_url; + this.author = options.author; + this.categories = options.categories; + this.pubDate = options.pubDate; + this.hub = options.hub; + this.docs = options.docs; + this.copyright = options.copyright; + this.language = options.language; + this.managingEditor = options.managingEditor; + this.webMaster = options.webMaster; + this.ttl = options.ttl; + //option to return feed as GeoRSS is set automatically if feed.lat/long is used + this.geoRSS = options.geoRSS || false; + this.items = items || []; + + this.item = function (options) { + options = options || {}; + var item = { + title: options.title || 'No title', + description: options.description || '', + url: options.url, + guid: options.guid, + categories: options.categories || [], + author: options.author, + date: options.date, + lat: options.lat, + long: options.long, + enclosure: options.enclosure || false + }; + + this.items.push(item); + return this; + }; + + this.xml = function(indent) { + return '\n' + + xml(generateXML(this), indent); + }; +} + module.exports = RSS; diff --git a/package.json b/package.json index ef5c297..0671ce9 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,26 @@ { "name": "rss", "version": "1.0.0", - "description": "RSS feed generator. A really simple API to add RSS feeds to any project.", + "description": "RSS feed generator. Add RSS feeds to any project. Supports enclosures and GeoRSS.", + "keywords": [ + "rss", + "xml", + "atom", + "podcasts", + "ghost", + "feed", + "feed builder", + "rss feed" + ], + "main": "lib/rss.js", + "scripts": { + "test": "grunt test" + }, "homepage": "http://github.com/dylang/node-rss", - "author": "Dylan Greene ", + "author": { + "name": "Dylan Greene", + "email": "dylang@gmail.com" + }, "contributors": [ "Dylan Greene ", "Xavier Damman ", @@ -12,7 +29,8 @@ "Danny Graham", "Patrick Garman ", "Fred Morstatter", - "Eric Vantillard " + "Eric Vantillard ", + "Jason Karns " ], "repository": { "type": "git", @@ -29,14 +47,15 @@ "devDependencies": { "chai": "^1.9.1", "grunt": "^0.4.5", + "grunt-contrib-jshint": "^0.10.0", + "grunt-mocha-test": "^0.12.1", "grunt-release": "^0.7.0", + "grunt-templates-dylang": "^1.0.0", + "load-grunt-tasks": "^0.6.0", "mocha": "^1.21.4", "q": "^1.0.0", + "time-grunt": "^1.0.0", "xml2js": "^0.4.1" }, - "main": "lib/rss.js", - "scripts": { - "test": "mocha --reporter spec" - }, "licenses": "MIT" } diff --git a/readme.md b/readme.md index a9eb1a7..af9fbc4 100644 --- a/readme.md +++ b/readme.md @@ -1,16 +1,18 @@ -# RSS for Node [![Build Status](https://api.travis-ci.org/dylang/node-rss.svg)](http://travis-ci.org/dylang/node-rss) +## rss [![NPM version](https://badge.fury.io/js/rss.png)](http://badge.fury.io/js/rss) [![Build Status](http://github.com/dylang/node-rss.png)](http://github.com/dylang/node-rss) - [![NPM](https://nodei.co/npm/rss.png?downloads=true)](https://nodei.co/npm/rss/) +> RSS feed generator. Add RSS feeds to any project. Supports enclosures and GeoRSS. -> Fast and simple RSS generator/builder for Node projects. Supports enclosures and GeoRSS. +[![rss](https://nodei.co/npm/rss.png?downloads=true "rss")](https://nodei.co/npm/rss) -## Install - $ npm install rss -## Usage -### Create a new feed + + + +### Usage + +#### Create a new feed ```js var RSS = require('rss'); @@ -18,7 +20,7 @@ var RSS = require('rss'); var feed = new RSS(feedOptions); ``` -#### `feedOptions` +##### `feedOptions` * `title` **string** Title of your site or feed * `description` _optional_ **string** A short description of the feed. @@ -34,9 +36,9 @@ var feed = new RSS(feedOptions); * `categories` _optional_ **array of strings** One or more categories this feed belongs to. * `pubDate` _optional_ **Date object or date string** The publication date for content in the feed * `ttl` _optional_ **integer** Number of minutes feed can be cached before refreshing from source. - * `hub` _optional_ **PubSubHubbub hub url** Where is the PubSubHubb hub located. + * `hub` _optional_ **PubSubHubbub hub url** Where is the PubSubHub hub located. -### Add items to a feed +#### 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. @@ -45,7 +47,7 @@ can have any number of items. Most feeds use 20 or fewer items. feed.item(itemOptions); ``` -#### 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. @@ -63,7 +65,7 @@ feed.item(itemOptions); * `lat` _optional_ **number** The latitude coordinate of the item. * `long` _optional_ **number** The longitude coordinate of the item. -#### Feed XML +##### Feed XML ```js var xml = feed.xml(indent); @@ -74,7 +76,8 @@ This returns the XML as a string. `indent` _optional_ **string** What to use as a tab. Defaults to no tabs (compressed). For example you can use `'\t'` for tab character, or `' '` for two-space tabs. -## Example Usage + +### Example Usage ```js var RSS = require('rss'); @@ -114,50 +117,71 @@ feed.item({ var xml = feed.xml(); ``` -## Tests -Tests included use Mocha. Use `npm test` to run the tests. - $ npm test -## Notes + +### Notes + * You do not need to escape anything. This module will escape characters when necessary. * This module is very fast but you might as well cache the output of xml() and serve it until something changes. -# History + + +### Inspiration I started this module *years* ago (April 2011) because there weren't any Node modules for creating RSS. [Nearly 50 modules](https://npmjs.org/browse/depended/rss) use RSS, as well as many web sites and the popular [Ghost publishing platform](https://ghost.org/). -# Contributing + + +### Contributing Contributions to the project are welcome. Feel free to fork and improve. I do my best accept pull requests in a timely manor, especially when tests and updated docs are included. -# License -(The MIT License) -Copyright (c) 2011-2014 Dylan Greene +### About the Author -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Hello fellow developer! My name is [Dylan Greene](https://github.com/dylang). When +not overwhelmed with my two kids I enjoy contributing to the open source community. +I'm a tech lead at [Opower](http://opower.com). I lead a team using Grunt and Angular to build software that +successfully helps people like us use less power. +Not too long ago I co-created [Doodle or Die](http://doodleordie.com), a hilarious web game with millions of +doodles that won us Node Knockout for the "most fun" category. +I'm [dylang](https://twitter.com/dylang) on Twitter and other places. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Some of my other Node projects: + +| Name | Description | Github Stars | Npm Installs | +|---|---|--:|--:| +| [`grunt-notify`](https://github.com/dylang/grunt-notify) | Automatic desktop notifications for Grunt errors and warnings using Growl for OS X or Windows, Mountain Lion and Mavericks Notification Center, and Notify-Send. | 810 | 41,939 | +| [`grunt-prompt`](https://github.com/dylang/grunt-prompt) | Interactive prompt for your Grunt config using console checkboxes, text input with filtering, password fields. | 249 | 7,144 | +| [`shortid`](https://github.com/dylang/shortid) | Amazingly short non-sequential url-friendly unique id generator. | 268 | 11,035 | +| [`xml`](https://github.com/dylang/node-xml) | Fast and simple xml generator. Supports attributes, CDATA, etc. Includes tests and examples. | 57 | 22,645 | +| [`changelog`](https://github.com/dylang/changelog) | Command line tool (and Node module) that generates a changelog in color output, markdown, or json for modules in npmjs.org's registry as well as any public github.com repo. | 61 | 297 | +| [`npm-check`](https://github.com/dylang/npm-check) | Check for outdated, incorrect, and unused dependencies. | _New!_ | 237 | +| [`grunt-attention`](https://github.com/dylang/grunt-attention) | Display attention-grabbing messages in the terminal | _New!_ | 7,906 | +| [`logging`](https://github.com/dylang/logging) | Super sexy color console logging with cluster support. | 24 | 239 | +| [`observatory`](https://github.com/dylang/observatory) | Beautiful UI for showing tasks running on the command line. | 31 | 6,624 | +| [`flowdock-refined`](https://github.com/dylang/flowdock-refined) | Flowdock desktop app custom UI | _New!_ | 49 | +| [`anthology`](https://github.com/dylang/anthology) | Module information and stats for any @npmjs user | _New!_ | 244 | +| [`grunt-cat`](https://github.com/dylang/grunt-cat) | Echo a file to the terminal. Works with text, figlets, ascii art, and full-color ansi. | _New!_ | 235 | + +_This list was generated using [anthology](https://github.com/dylang/anthology)._ + + +### License +Copyright (c) 2014 Dylan Greene, contributors. + +Released under the [MIT license](https://tldrlegal.com/license/mit-license). + +Screenshots are [CC BY-SA](http://creativecommons.org/licenses/by-sa/4.0/) (Attribution-ShareAlike). + +*** +_Generated using [grunt-readme](https://github.com/assemble/grunt-readme) with [grunt-templates-dylang](https://github.com/dylang/grunt-templates-dylang) on Tuesday, October 21, 2014._ [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/dylang/rss/trend.png)](https://bitdeli.com/free "Bitdeli Badge") [![Google Analytics](https://ga-beacon.appspot.com/UA-4820261-3/dylang/rss)](https://github.com/igrigorik/ga-beacon) -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/templates/readme/contributing.md b/templates/readme/contributing.md new file mode 100644 index 0000000..93a0192 --- /dev/null +++ b/templates/readme/contributing.md @@ -0,0 +1,5 @@ +## Contributing + +Contributions to the project are welcome. Feel free to fork and improve. +I do my best accept pull requests in a timely manor, especially when tests and updated docs +are included. \ No newline at end of file diff --git a/templates/readme/examples.md b/templates/readme/examples.md new file mode 100644 index 0000000..b2ee772 --- /dev/null +++ b/templates/readme/examples.md @@ -0,0 +1,39 @@ +## Example Usage + +```js +var RSS = require('rss'); + +/* lets 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' +}); + +/* 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:'...', file:'path-to-file'} // optional enclosure +}); + +// cache the xml to send to clients +var xml = feed.xml(); +``` diff --git a/templates/readme/inspiration.md b/templates/readme/inspiration.md new file mode 100644 index 0000000..d754fd6 --- /dev/null +++ b/templates/readme/inspiration.md @@ -0,0 +1,5 @@ +## Inspiration + +I started this module *years* ago (April 2011) because there weren't any Node modules +for creating RSS. [Nearly 50 modules](https://npmjs.org/browse/depended/rss) +use RSS, as well as many web sites and the popular [Ghost publishing platform](https://ghost.org/). diff --git a/templates/readme/notes.md b/templates/readme/notes.md new file mode 100644 index 0000000..713758d --- /dev/null +++ b/templates/readme/notes.md @@ -0,0 +1,5 @@ +## Notes + + * You do not need to escape anything. This module will escape characters when necessary. + * This module is very fast but you might as well cache the output of xml() and serve + it until something changes. diff --git a/templates/readme/tests.md b/templates/readme/tests.md new file mode 100644 index 0000000..83938cf --- /dev/null +++ b/templates/readme/tests.md @@ -0,0 +1,7 @@ +## Tests + +Tests included use Mocha. Use `npm test` to run the tests. + +```sh +$ npm test +``` \ No newline at end of file diff --git a/templates/readme/usage.md b/templates/readme/usage.md new file mode 100644 index 0000000..971f566 --- /dev/null +++ b/templates/readme/usage.md @@ -0,0 +1,65 @@ +## Usage + +### Create a new feed + +```js +var RSS = require('rss'); + +var feed = new RSS(feedOptions); +``` + +#### `feedOptions` + + * `title` **string** Title of your site or feed + * `description` _optional_ **string** A short description of the feed. + * `generator` _optional_ **string** Feed generator. + * `feed_url` **url string** Url to the rss feed. + * `site_url` **url string** Url to the site that the feed is for. + * `image_url` _optional_ **url string* Small image for feed readers to use. + * `docs` _optional_ **url string** Url to documentation on this feed. + * `managingEditor` _optional_ **string** Who manages content in this feed. + * `webMaster` _optional_ **string** Who manages feed availability and technical support. + * `copyright` _optional_ **string** Copyright information for this feed. + * `language` _optional_ **string** The language of the content of this feed. + * `categories` _optional_ **array of strings** One or more categories this feed belongs to. + * `pubDate` _optional_ **Date object or date string** The publication date for content in the feed + * `ttl` _optional_ **integer** Number of minutes feed can be cached before refreshing from source. + * `hub` _optional_ **PubSubHubbub hub url** Where is the PubSubHub hub located. + +### 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. + * `guid` **unique string** A unique string feed readers use to know if an item is new or has already been seen. + If you use a guid never change it. If you don't provide a guid then your item urls must + be unique. + * `categories` _optional_ **array of strings** If provided, each array item will be added as a category element + * `author` _optional_ **string** If included it is the name of the item's creator. + If not provided the item author will be the same as the feed author. This is typical + except on multi-author blogs. + * `date` **Date object or date string** The date and time of when the item was created. Feed + readers use this to determine the sort order. Some readers will also use it to determine + if the content should be presented as unread. + * `lat` _optional_ **number** The latitude coordinate of the item. + * `long` _optional_ **number** The longitude coordinate of the item. + +#### Feed XML + +```js +var xml = feed.xml(indent); +``` + +This returns the XML as a string. + +`indent` _optional_ **string** What to use as a tab. Defaults to no tabs (compressed). + For example you can use `'\t'` for tab character, or `' '` for two-space tabs. \ No newline at end of file diff --git a/templates/rss.md b/templates/rss.md new file mode 100644 index 0000000..5d180cf --- /dev/null +++ b/templates/rss.md @@ -0,0 +1,12 @@ + +{%= _.doc('readme/usage.md') %} + +{%= _.doc('readme/examples.md') %} + +{%= _.doc('readme/test.md') %} + +{%= _.doc('readme/notes.md') %} + +{%= _.doc('readme/inspiration.md') %} + +{%= _.doc('readme/contributing.md') %} \ No newline at end of file