Skip to content

Commit

Permalink
feat: accept a factory function as feed parameter
Browse files Browse the repository at this point in the history
If only one feed should be generated, an object can be passed as well now
  • Loading branch information
manniL committed Apr 18, 2018
1 parent bcdb2e6 commit 740ec07
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 3 deletions.
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,52 @@ Feed creation is based on the [feed](https://github.com/jpmonette/feed) package.
Please use it as reference and further documentation for modifying the `feed` object
that is passed to the `create` function.
Using the `create` function gives you unlimited possibilities to customize your feed!
Using the `create` function gives you almost unlimited possibilities to customize your feed!
### Using a feed factory function
There is one more thing. Imagine you want to add a feed per blog category, but you don't want
to add every category by hand.
You can use a `factory function` to solve that problem. Instead of a hardcoded array, you can setup
a function that will be called up on feed generation. The function **must** return an array with all
feeds you want to generate.

```js
{
feed: async () => {
const posts = (await axios.get('https://my-url.com/posts')).data
const tags = (await axios.get('https://my-url.com/tags')).data

return tags.map(t => {
const relevantPosts = posts.filter(/*filter posts somehow*/)

return {
path: `/${t.slug}.xml`, // The route to your feed.
async create (feed) {
feed.options = {
title: `${t.name} - My blog`,
description: `All posts related to ${t.name} of my blog`,
}

relevantPosts.forEach(post => {
feed.addItem({
title: post.title,
id: post.id,
link: `https://blog.lichter.io/posts/${post.slug}`,
description: post.excerpt,
content: post.text
})
})
},
cacheTime: 1000 * 60 * 15,
type: 'rss2'
}
})
},
}
```
## Development
Expand Down
12 changes: 10 additions & 2 deletions lib/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@ const defaults = {
cacheTime: 1000 * 60 * 15
}

module.exports = async function feed (moduleOptions) {
const options = Object.assign([], this.options.feed, moduleOptions).map(o => Object.assign({}, defaults, o))
module.exports = async function feed () {
if (typeof this.options.feed === 'function') {
this.options.feed = await this.options.feed()
}

if (!Array.isArray(this.options.feed)) {
this.options.feed = [this.options.feed]
}

const options = Object.assign([], this.options.feed).map(o => Object.assign({}, defaults, o))

const feedCache = new AsyncCache({
maxAge: options.cacheTime,
Expand Down
36 changes: 36 additions & 0 deletions test/fixture/configs/function_rss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const { resolve } = require('path')

module.exports = {
rootDir: resolve(__dirname, '../../../'),
srcDir: resolve(__dirname, '../'),
dev: false,
render: {
resourceHints: false
},
modules: ['@@'],
feed: () => ({
create (feed) {
feed.options = {
title: 'Feed Title',
description: 'This is my personal feed!',
id: 'http://example.com/',
link: 'http://example.com/',
image: 'http://example.com/image.png',
favicon: 'http://example.com/favicon.ico',
updated: new Date(2000, 6, 14), // optional, default = today
copyright: 'All rights reserved 2013, John Doe',
generator: 'awesome', // optional, default = 'Feed for Node.js'
feedLinks: {
json: 'https://example.com/json',
atom: 'https://example.com/atom'
},
author: {
name: 'John Doe',
email: 'johndoe@example.com',
link: 'https://example.com/johndoe'
}
}
},
type: 'rss2'
})
}
36 changes: 36 additions & 0 deletions test/fixture/configs/object_rss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const { resolve } = require('path')

module.exports = {
rootDir: resolve(__dirname, '../../../'),
srcDir: resolve(__dirname, '../'),
dev: false,
render: {
resourceHints: false
},
modules: ['@@'],
feed: {
create (feed) {
feed.options = {
title: 'Feed Title',
description: 'This is my personal feed!',
id: 'http://example.com/',
link: 'http://example.com/',
image: 'http://example.com/image.png',
favicon: 'http://example.com/favicon.ico',
updated: new Date(2000, 6, 14), // optional, default = today
copyright: 'All rights reserved 2013, John Doe',
generator: 'awesome', // optional, default = 'Feed for Node.js'
feedLinks: {
json: 'https://example.com/json',
atom: 'https://example.com/atom'
},
author: {
name: 'John Doe',
email: 'johndoe@example.com',
link: 'https://example.com/johndoe'
}
}
},
type: 'rss2'
}
}
46 changes: 46 additions & 0 deletions test/module.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,52 @@ describe('universal', () => {
expect(await get('/feed.xml')).toBe('')
}, timeout)

test('object rss', async () => {
nuxt = await setupNuxt(require('./fixture/configs/object_rss'))
let html = await get('/feed.xml')
expect(html).toBe('<?xml version="1.0" encoding="utf-8"?>\n' +
'<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">\n' +
' <channel>\n' +
' <title>Feed Title</title>\n' +
' <link>http://example.com/</link>\n' +
' <description>This is my personal feed!</description>\n' +
' <lastBuildDate>' + date.rss + '</lastBuildDate>\n' +
' <docs>http://blogs.law.harvard.edu/tech/rss</docs>\n' +
' <generator>awesome</generator>\n' +
' <image>\n' +
' <title>Feed Title</title>\n' +
' <url>http://example.com/image.png</url>\n' +
' <link>http://example.com/</link>\n' +
' </image>\n' +
' <copyright>All rights reserved 2013, John Doe</copyright>\n' +
' <atom:link href="https://example.com/atom" rel="self" type="application/rss+xml"/>\n' +
' </channel>\n' +
'</rss>')
}, timeout)

test('function rss', async () => {
nuxt = await setupNuxt(require('./fixture/configs/function_rss'))
let html = await get('/feed.xml')
expect(html).toBe('<?xml version="1.0" encoding="utf-8"?>\n' +
'<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">\n' +
' <channel>\n' +
' <title>Feed Title</title>\n' +
' <link>http://example.com/</link>\n' +
' <description>This is my personal feed!</description>\n' +
' <lastBuildDate>' + date.rss + '</lastBuildDate>\n' +
' <docs>http://blogs.law.harvard.edu/tech/rss</docs>\n' +
' <generator>awesome</generator>\n' +
' <image>\n' +
' <title>Feed Title</title>\n' +
' <url>http://example.com/image.png</url>\n' +
' <link>http://example.com/</link>\n' +
' </image>\n' +
' <copyright>All rights reserved 2013, John Doe</copyright>\n' +
' <atom:link href="https://example.com/atom" rel="self" type="application/rss+xml"/>\n' +
' </channel>\n' +
'</rss>')
}, timeout)

test('multi rss', async () => {
nuxt = await setupNuxt(require('./fixture/configs/multi_rss'))

Expand Down

0 comments on commit 740ec07

Please sign in to comment.