├── husky.config.js ├── renovate.json ├── .eslintrc.js ├── .eslintignore ├── lib ├── logger.js └── module.js ├── commitlint.config.js ├── .gitignore ├── jest.config.js ├── .editorconfig ├── test ├── fixture │ └── nuxt.config.js ├── feed-options.js ├── middleware.test.js ├── module.test.js └── __snapshots__ │ └── module.test.js.snap ├── .circleci └── config.yml ├── LICENSE ├── package.json ├── CHANGELOG.md └── README.md /husky.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | } 4 | } 5 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | '@nuxtjs' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Common 2 | node_modules 3 | dist 4 | .nuxt 5 | coverage 6 | 7 | # Plugin 8 | lib/plugin.js 9 | -------------------------------------------------------------------------------- /lib/logger.js: -------------------------------------------------------------------------------- 1 | const consola = require('consola') 2 | 3 | module.exports = consola.withScope('nuxt:feed') 4 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | '@commitlint/config-conventional' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | collectCoverage: true, 4 | collectCoverageFrom: [ 5 | 'lib/**/*.js', 6 | '!lib/plugin.js' 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /test/fixture/nuxt.config.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | const { createFeed } = require('../feed-options') 3 | 4 | module.exports = { 5 | rootDir: resolve(__dirname, '../..'), 6 | buildDir: resolve(__dirname, '.nuxt'), 7 | srcDir: __dirname, 8 | render: { 9 | resourceHints: false 10 | }, 11 | modules: [ 12 | { handler: require('../../') } 13 | ], 14 | feed: [ 15 | createFeed() 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node 6 | steps: 7 | # Checkout repository 8 | - checkout 9 | 10 | # Restore cache 11 | - restore_cache: 12 | key: yarn-cache-{{ checksum "yarn.lock" }} 13 | 14 | # Install dependencies 15 | - run: 16 | name: Install Dependencies 17 | command: NODE_ENV=dev yarn 18 | 19 | # Keep cache 20 | - save_cache: 21 | key: yarn-cache-{{ checksum "yarn.lock" }} 22 | paths: 23 | - "node_modules" 24 | 25 | # Lint 26 | - run: 27 | name: Lint 28 | command: yarn lint 29 | 30 | # Tests 31 | - run: 32 | name: Tests 33 | command: yarn jest 34 | 35 | # Coverage 36 | - run: 37 | name: Coverage 38 | command: yarn codecov 39 | -------------------------------------------------------------------------------- /test/feed-options.js: -------------------------------------------------------------------------------- 1 | const createFeed = (type = 'rss2') => ({ 2 | create (feed) { 3 | feed.options = feedOptions 4 | }, 5 | type 6 | }) 7 | 8 | const feedOptions = { 9 | title: 'Feed Title', 10 | description: 'This is my personal feed!', 11 | id: 'http://example.com/', 12 | link: 'http://example.com/', 13 | image: 'http://example.com/image.png', 14 | favicon: 'http://example.com/favicon.ico', 15 | updated: new Date(Date.UTC(2000, 6, 14)), // optional, default = today 16 | copyright: 'All rights reserved 2013, John Doe', 17 | generator: 'awesome', // optional, default = 'https://github.com/nuxt-community/feed-module' 18 | feedLinks: { 19 | json: 'https://example.com/json', 20 | atom: 'https://example.com/atom' 21 | }, 22 | author: { 23 | name: 'John Doe', 24 | email: 'johndoe@example.com', 25 | link: 'https://example.com/johndoe' 26 | } 27 | } 28 | 29 | module.exports = { 30 | createFeed, 31 | feedOptions 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nuxt Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/middleware.test.js: -------------------------------------------------------------------------------- 1 | jest.setTimeout(60000) 2 | jest.mock('async-cache', () => { 3 | return jest.fn().mockImplementation(() => { 4 | return { get: () => { throw new Error('Error on create feed') } } 5 | }) 6 | }) 7 | 8 | const { Nuxt, Builder } = require('nuxt-edge') 9 | const request = require('request-promise-native') 10 | const getPort = require('get-port') 11 | const logger = require('../lib/logger') 12 | const { createFeed } = require('./feed-options') 13 | 14 | const config = require('./fixture/nuxt.config') 15 | config.dev = false 16 | 17 | let nuxt, port 18 | 19 | logger.mockTypes(() => jest.fn()) 20 | 21 | const url = path => `http://localhost:${port}${path}` 22 | const get = path => request(url(path)) 23 | 24 | describe('middleware', () => { 25 | beforeAll(async () => { 26 | nuxt = new Nuxt({ 27 | ...config, 28 | feed: [ 29 | { ...createFeed(), ...{ path: '/feed-error.xml' } } 30 | ] 31 | }) 32 | await nuxt.ready() 33 | await new Builder(nuxt).build() 34 | port = await getPort() 35 | await nuxt.listen(port) 36 | }) 37 | 38 | beforeEach(() => { 39 | logger.clear() 40 | }) 41 | 42 | afterAll(async () => { 43 | await nuxt.close() 44 | }) 45 | 46 | test('error on handler', async () => { 47 | await expect(get('/feed-error.xml')).rejects.toMatchObject({ 48 | statusCode: 500 49 | }) 50 | }) 51 | }) 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arpitbbhayani-nuxtjs-feed", 3 | "version": "1.1.0", 4 | "description": "Feed module enables everyone to have RSS, Atom and Json.", 5 | "keywords": [ 6 | "nuxtjs", 7 | "nuxt", 8 | "feed", 9 | "blog", 10 | "rss", 11 | "atom", 12 | "json" 13 | ], 14 | "license": "MIT", 15 | "contributors": [ 16 | "Alexander Lichter " 17 | ], 18 | "main": "lib/module.js", 19 | "repository": "nuxt-community/feed-module", 20 | "publishConfig": { 21 | "access": "public" 22 | }, 23 | "scripts": { 24 | "dev": "nuxt test/fixture", 25 | "generate": "nuxt generate test/fixture", 26 | "lint": "eslint --ext .js,.vue lib test", 27 | "test": "yarn lint && jest", 28 | "release": "yarn test && standard-version && git push --follow-tags && npm publish" 29 | }, 30 | "files": [ 31 | "lib" 32 | ], 33 | "dependencies": { 34 | "arpitbbhayani-feed": "^4.1.0", 35 | "async-cache": "^1.1.0", 36 | "consola": "^2.9.0" 37 | }, 38 | "devDependencies": { 39 | "@commitlint/cli": "latest", 40 | "@commitlint/config-conventional": "latest", 41 | "@nuxtjs/eslint-config": "latest", 42 | "codecov": "latest", 43 | "eslint": "latest", 44 | "get-port": "latest", 45 | "husky": "latest", 46 | "jest": "latest", 47 | "nuxt-edge": "latest", 48 | "request": "latest", 49 | "request-promise-native": "latest", 50 | "standard-version": "latest" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | # [1.1.0](https://github.com/nuxt-community/feed-module/compare/v1.0.0...v1.1.0) (2019-01-12) 7 | 8 | 9 | ### Features 10 | 11 | * factory object ([#30](https://github.com/nuxt-community/feed-module/issues/30)) ([0a62219](https://github.com/nuxt-community/feed-module/commit/0a62219)) 12 | 13 | 14 | 15 | 16 | # [1.0.0](https://github.com/nuxt-community/feed-module/compare/v0.2.0...v1.0.0) (2019-01-12) 17 | 18 | 19 | ### Bug Fixes 20 | 21 | * log error before fatal ([#26](https://github.com/nuxt-community/feed-module/issues/26)) ([2a120a5](https://github.com/nuxt-community/feed-module/commit/2a120a5)) 22 | * send utf-8 charset as header ([#18](https://github.com/nuxt-community/feed-module/issues/18)) ([a412ee4](https://github.com/nuxt-community/feed-module/commit/a412ee4)) 23 | 24 | 25 | ### Features 26 | 27 | * introduce data property ([23e819e](https://github.com/nuxt-community/feed-module/commit/23e819e)) 28 | 29 | 30 | 31 | 32 | # [0.2.0](https://github.com/nuxt-community/feed-module/compare/v0.1.1...v0.2.0) (2018-10-05) 33 | 34 | 35 | ### Bug Fixes 36 | 37 | * fix typo in package.json ([ff69039](https://github.com/nuxt-community/feed-module/commit/ff69039)) 38 | 39 | 40 | ### Features 41 | 42 | * set default generator to nuxt-feed module ([2cfc35b](https://github.com/nuxt-community/feed-module/commit/2cfc35b)) 43 | 44 | 45 | 46 | 47 | ## [0.1.1](https://github.com/nuxt-community/feed-module/compare/v0.1.0...v0.1.1) (2018-04-20) 48 | 49 | 50 | ### Bug Fixes 51 | 52 | * name of property error in generate ([52a5155](https://github.com/nuxt-community/feed-module/commit/52a5155)) 53 | 54 | 55 | 56 | 57 | # [0.1.0](https://github.com/nuxt-community/feed-module/compare/v0.0.1...v0.1.0) (2018-04-18) 58 | 59 | 60 | ### Features 61 | 62 | * accept a factory function as feed parameter ([740ec07](https://github.com/nuxt-community/feed-module/commit/740ec07)) 63 | 64 | 65 | 66 | 67 | ## 0.0.1 (2018-04-14) 68 | -------------------------------------------------------------------------------- /lib/module.js: -------------------------------------------------------------------------------- 1 | const { join, resolve } = require('path') 2 | const { promisify } = require('util') 3 | const { writeFileSync } = require('fs') 4 | const { Feed } = require('arpitbbhayani-feed') 5 | const AsyncCache = require('async-cache') 6 | const logger = require('./logger') 7 | 8 | const defaults = { 9 | path: '/feed.xml', 10 | async create (feed) {}, 11 | cacheTime: 1000 * 60 * 15 12 | } 13 | 14 | module.exports = async function (moduleOptions) { 15 | const options = [ 16 | ...await parseOptions(this.options.feed), 17 | ...await parseOptions(moduleOptions) 18 | ].map(o => ({ ...defaults, ...o })) 19 | 20 | const feedCache = new AsyncCache({ 21 | load (feedIndex, callback) { 22 | createFeed(options[feedIndex], callback).catch(err => logger.error(err)) 23 | } 24 | }) 25 | 26 | feedCache.get = promisify(feedCache.get) 27 | 28 | options.forEach((feedOptions, index) => { 29 | this.nuxt.hook('generate:done', async () => { 30 | if (index === 0) { 31 | logger.info('Generating feeds') 32 | } 33 | 34 | const xmlGeneratePath = resolve(this.options.rootDir, join(this.options.generate.dir, feedOptions.path)) 35 | 36 | writeFileSync(xmlGeneratePath, await feedCache.get(index)) 37 | 38 | logger.success('Generated', feedOptions.path) 39 | }) 40 | 41 | this.addServerMiddleware({ 42 | path: feedOptions.path, 43 | async handler (req, res, next) { 44 | try { 45 | const xml = await feedCache.get(index) 46 | res.setHeader('Content-Type', resolveContentType(feedOptions.type)) 47 | res.end(xml) 48 | } catch (err) { 49 | next(err) 50 | } 51 | } 52 | }) 53 | }) 54 | } 55 | 56 | async function parseOptions (options) { 57 | // Factory function 58 | if (typeof options === 'function') { 59 | options = await options() 60 | } 61 | 62 | // Factory object 63 | if (!Array.isArray(options)) { 64 | if (options.factory) { 65 | options = await options.factory(options.data) 66 | } 67 | } 68 | 69 | // Check if is empty 70 | if (Object.keys(options).length === 0) { 71 | return [] 72 | } 73 | 74 | // Single feed 75 | if (!Array.isArray(options)) { 76 | options = [options] 77 | } 78 | 79 | return options 80 | } 81 | 82 | function resolveContentType (type) { 83 | const lookup = { 84 | rss2: 'application/rss+xml', 85 | atom1: 'application/atom+xml', 86 | json1: 'application/json' 87 | } 88 | return (lookup.hasOwnProperty(type) ? lookup[type] : 'application/xml') + '; charset=UTF-8' 89 | } 90 | 91 | async function createFeed (feedOptions, callback) { 92 | if (!['rss2', 'json1', 'atom1'].includes(feedOptions.type)) { 93 | logger.fatal(`Could not create Feed ${feedOptions.path} - Unknown feed type`) 94 | return callback(null, '', feedOptions.cacheTime) 95 | } 96 | 97 | const feed = new Feed() 98 | 99 | try { 100 | await feedOptions.create.call(this, feed, feedOptions.data) 101 | feed.options = { 102 | generator: 'https://github.com/nuxt-community/feed-module', 103 | ...feed.options 104 | } 105 | } catch (err) { 106 | logger.error(err) 107 | logger.fatal('Error while executing feed creation function') 108 | 109 | return callback(null, '', feedOptions.cacheTime) 110 | } 111 | 112 | return callback(null, feed[feedOptions.type](), feedOptions.cacheTime) 113 | } 114 | 115 | module.exports.meta = require('../package.json') 116 | -------------------------------------------------------------------------------- /test/module.test.js: -------------------------------------------------------------------------------- 1 | jest.setTimeout(60000) 2 | 3 | const { resolve, join } = require('path') 4 | const { readFileSync } = require('fs') 5 | const { Nuxt, Builder, Generator } = require('nuxt-edge') 6 | const request = require('request-promise-native') 7 | const getPort = require('get-port') 8 | const logger = require('../lib/logger') 9 | const { createFeed, feedOptions } = require('./feed-options') 10 | 11 | const config = require('./fixture/nuxt.config') 12 | config.dev = false 13 | 14 | let nuxt, port 15 | 16 | logger.mockTypes(() => jest.fn()) 17 | 18 | const url = path => `http://localhost:${port}${path}` 19 | const get = path => request(url(path)) 20 | 21 | const setupNuxt = async (config) => { 22 | const nuxt = new Nuxt(config) 23 | await nuxt.ready() 24 | await new Builder(nuxt).build() 25 | port = await getPort() 26 | await nuxt.listen(port) 27 | 28 | return nuxt 29 | } 30 | 31 | describe('module', () => { 32 | beforeEach(() => { 33 | logger.clear() 34 | }) 35 | 36 | afterEach(async () => { 37 | if (nuxt) { 38 | await nuxt.close() 39 | } 40 | }) 41 | 42 | test('generate simple rss', async () => { 43 | nuxt = new Nuxt(config) 44 | await nuxt.ready() 45 | 46 | const builder = new Builder(nuxt) 47 | const generator = new Generator(nuxt, builder) 48 | await generator.generate() 49 | 50 | const filePath = resolve(nuxt.options.rootDir, join(nuxt.options.generate.dir, 'feed.xml')) 51 | expect(readFileSync(filePath, { encoding: 'utf8' })).toMatchSnapshot() 52 | }) 53 | 54 | test('simple rss', async () => { 55 | nuxt = await setupNuxt(config) 56 | 57 | const html = await get('/feed.xml') 58 | expect(html).toMatchSnapshot() 59 | }) 60 | 61 | test('simple atom', async () => { 62 | nuxt = await setupNuxt({ 63 | ...config, 64 | feed: [ 65 | createFeed('atom1') 66 | ] 67 | }) 68 | 69 | const html = await get('/feed.xml') 70 | expect(html).toMatchSnapshot() 71 | }) 72 | 73 | test('simple json', async () => { 74 | nuxt = await setupNuxt({ 75 | ...config, 76 | feed: [ 77 | createFeed('json1') 78 | ] 79 | }) 80 | 81 | const html = await get('/feed.xml') 82 | expect(html).toMatchSnapshot() 83 | }) 84 | 85 | test('non-latin rss', async () => { 86 | nuxt = await setupNuxt({ 87 | ...config, 88 | feed: [ 89 | { 90 | create (feed) { 91 | feed.options = { 92 | title: 'Популярные новости России и мира', 93 | link: 'http://site.ru/feed.xml', 94 | description: 'Новости России и мира на сайте site.ru', 95 | updated: new Date(Date.UTC(2000, 6, 14)) 96 | } 97 | feed.addContributor({ 98 | name: 'Команда проекта site.ru', 99 | email: 'support@ site.ru', 100 | link: 'http://site.ru/' 101 | }) 102 | }, 103 | type: 'rss2' 104 | } 105 | ] 106 | }) 107 | 108 | const html = await get('/feed.xml') 109 | expect(html).toMatchSnapshot() 110 | }) 111 | 112 | test('object rss', async () => { 113 | nuxt = await setupNuxt({ 114 | ...config, 115 | feed: { 116 | data: { title: 'Feed Title' }, 117 | create (feed, data) { 118 | feedOptions.title = data.title 119 | feed.options = feedOptions 120 | }, 121 | type: 'rss2' 122 | } 123 | }) 124 | 125 | const html = await get('/feed.xml') 126 | expect(html).toMatchSnapshot() 127 | }) 128 | 129 | test('factory rss', async () => { 130 | nuxt = await setupNuxt({ 131 | ...config, 132 | feed: { 133 | data: { title: 'Feed Title' }, 134 | factory: data => ({ 135 | data, 136 | create (feed, { title }) { 137 | feedOptions.title = data.title 138 | feed.options = feedOptions 139 | }, 140 | type: 'rss2' 141 | }) 142 | } 143 | }) 144 | 145 | const html = await get('/feed.xml') 146 | expect(html).toMatchSnapshot() 147 | }) 148 | 149 | test('function rss', async () => { 150 | nuxt = await setupNuxt({ 151 | ...config, 152 | feed: () => createFeed() 153 | }) 154 | 155 | const html = await get('/feed.xml') 156 | expect(html).toMatchSnapshot() 157 | }) 158 | 159 | test('multi rss', async () => { 160 | nuxt = await setupNuxt({ 161 | ...config, 162 | feed: [ 163 | { ...createFeed(), ...{ path: '/feed1.xml' } }, 164 | { ...createFeed(), ...{ path: '/feed2.xml' } } 165 | ] 166 | }) 167 | 168 | const html1 = await get('/feed1.xml') 169 | expect(html1).toMatchSnapshot() 170 | 171 | const html2 = await get('/feed2.xml') 172 | expect(html2).toMatchSnapshot() 173 | }) 174 | 175 | test('no type set', async () => { 176 | nuxt = await setupNuxt({ 177 | ...config, 178 | feed: [ 179 | {} 180 | ] 181 | }) 182 | 183 | const html = await get('/feed.xml') 184 | expect(html).toMatchSnapshot() 185 | 186 | expect(logger.fatal).toHaveBeenCalledWith('Could not create Feed /feed.xml - Unknown feed type') 187 | }) 188 | 189 | test('error on create feed', async () => { 190 | nuxt = await setupNuxt({ 191 | ...config, 192 | feed: [ 193 | { 194 | create (feed) { 195 | throw new Error('Error on create feed') 196 | }, 197 | type: 'rss2' 198 | } 199 | ] 200 | }) 201 | 202 | const html = await get('/feed.xml') 203 | expect(html).toMatchSnapshot() 204 | 205 | expect(logger.error).toHaveBeenCalledWith(new Error('Error on create feed')) 206 | expect(logger.fatal).toHaveBeenCalledWith('Error while executing feed creation function') 207 | }) 208 | }) 209 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Feed module - Everyone deserves RSS, Atom and Json 2 | 3 | [![npm version][npm-version-src]][npm-version-href] 4 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 5 | [![Circle CI][circle-ci-src]][circle-ci-href] 6 | [![Codecov][codecov-src]][codecov-href] 7 | [![License][license-src]][license-href] 8 | 9 | > Feed module enables everyone to have RSS, Atom and Json. 10 | 11 | [📖 **Release Notes**](./CHANGELOG.md) 12 | 13 | ## Features 14 | 15 | - Three different feed types (RSS 2.0, ATOM 1.0 and JSON 1.0) 16 | - As many feeds as you like! 17 | - Completely customizable. Need to fetch data before? No problem! 18 | - Works with **all modes** (yes, even generate!) 19 | - For Nuxt 2.x and higher 20 | 21 | ## Setup 22 | 23 | 1. Add `@nuxtjs/feed` dependency to your project 24 | 25 | ```bash 26 | yarn add @nuxtjs/feed # or npm install @nuxtjs/feed 27 | ``` 28 | 29 | 2. Add `@nuxtjs/feed` to the `modules` section of `nuxt.config.js` 30 | 31 | ```js 32 | { 33 | modules: [ 34 | ['@nuxtjs/feed', { 35 | // Your feeds here 36 | }] 37 | ] 38 | } 39 | ``` 40 | 41 | ### Using top level options 42 | 43 | ```js 44 | { 45 | modules: [ 46 | '@nuxtjs/feed' 47 | ], 48 | feed: [ 49 | // Your feeds here 50 | ] 51 | } 52 | ``` 53 | 54 | ## Configuration 55 | 56 | So.. how to get these feeds working now? 57 | 58 | ### Configuration object overview 59 | 60 | ```js 61 | { 62 | feed: [ 63 | // A default feed configuration object 64 | { 65 | path: '/feed.xml', // The route to your feed. 66 | async create(feed) {}, // The create function (see below) 67 | cacheTime: 1000 * 60 * 15, // How long should the feed be cached 68 | type: 'rss2', // Can be: rss2, atom1, json1 69 | data: ['Some additional data'] // Will be passed as 2nd argument to `create` function 70 | } 71 | ] 72 | } 73 | ``` 74 | 75 | ### Feed create function 76 | 77 | Let's take a closer look on the `create` function. This is the API that 78 | actually modifies your upcoming feed. 79 | 80 | A simple create function could look like this: 81 | 82 | ```js 83 | import axios from 'axios' 84 | 85 | // In your `feed` array: 86 | async create(feed) { 87 | feed.options = { 88 | title: 'My blog', 89 | link: 'https://lichter.io/feed.xml', 90 | description: 'This is my personal feed!' 91 | } 92 | 93 | const posts = await (axios.get('https://blog-api.lichter.io/posts')).data 94 | posts.forEach(post => { 95 | feed.addItem({ 96 | title: post.title, 97 | id: post.url, 98 | link: post.url, 99 | description: post.description, 100 | content: post.content 101 | }) 102 | }) 103 | 104 | feed.addCategory('Nuxt.js') 105 | 106 | feed.addContributor({ 107 | name: 'Alexander Lichter', 108 | email: 'example@lichter.io', 109 | link: 'https://lichter.io/' 110 | }) 111 | } 112 | ``` 113 | 114 | Feed creation is based on the [feed](https://github.com/jpmonette/feed) package. 115 | Please use it as reference and further documentation for modifying the `feed` object 116 | that is passed to the `create` function. 117 | 118 | Using the `create` function gives you almost unlimited possibilities to customize your feed! 119 | 120 | ### Using a feed factory function 121 | 122 | There is one more thing. Imagine you want to add a feed per blog category, but you don't want 123 | to add every category by hand. 124 | 125 | You can use a `factory function` to solve that problem. Instead of a hardcoded array, you can setup 126 | a function that will be called up on feed generation. The function **must** return an array with all 127 | feeds you want to generate. 128 | 129 | ```js 130 | { 131 | feed: async () => { 132 | const posts = (await axios.get('https://blog-api.lichter.io/posts')).data 133 | const tags = (await axios.get('https://blog-api.lichter.io/tags')).data 134 | 135 | return tags.map(t => { 136 | const relevantPosts = posts.filter(/*filter posts somehow*/) 137 | 138 | return { 139 | path: `/${t.slug}.xml`, // The route to your feed. 140 | async create(feed) { 141 | feed.options = { 142 | title: `${t.name} - My blog`, 143 | link: `https://blog.lichter.io/${t.slug}.xml`, 144 | description: `All posts related to ${t.name} of my blog` 145 | } 146 | 147 | relevantPosts.forEach(post => { 148 | feed.addItem({ 149 | title: post.title, 150 | id: post.id, 151 | link: `https://blog.lichter.io/posts/${post.slug}`, 152 | description: post.excerpt, 153 | content: post.text 154 | }) 155 | }) 156 | }, 157 | cacheTime: 1000 * 60 * 15, 158 | type: 'rss2' 159 | } 160 | }) 161 | } 162 | } 163 | ``` 164 | 165 | In case you want to pass in data into the factory function, you can use a *factory object*. 166 | 167 | ```js 168 | { 169 | feed: { 170 | data: ['Your data here'] 171 | factory: (dataFromFeedDotData) => {/* your factory function */} 172 | } 173 | } 174 | ``` 175 | 176 | ## Development 177 | 178 | 1. Clone this repository 179 | 2. Install dependencies using `yarn install` or `npm install` 180 | 3. Start development server using `npm run dev` 181 | 182 | ## License 183 | 184 | [MIT License](./LICENSE) 185 | 186 | Copyright (c) - Nuxt Community 187 | 188 | 189 | [npm-version-src]: https://img.shields.io/npm/v/@nuxtjs/feed/latest.svg?style=flat-square 190 | [npm-version-href]: https://npmjs.com/package/@nuxtjs/feed 191 | 192 | [npm-downloads-src]: https://img.shields.io/npm/dt/@nuxtjs/feed.svg?style=flat-square 193 | [npm-downloads-href]: https://npmjs.com/package/@nuxtjs/feed 194 | 195 | [circle-ci-src]: https://img.shields.io/circleci/project/github/nuxt-community/feed-module.svg?style=flat-square 196 | [circle-ci-href]: https://circleci.com/gh/nuxt-community/feed-module 197 | 198 | [codecov-src]: https://img.shields.io/codecov/c/github/nuxt-community/feed-module.svg?style=flat-square 199 | [codecov-href]: https://codecov.io/gh/nuxt-community/feed-module 200 | 201 | [license-src]: https://img.shields.io/npm/l/@nuxtjs/feed.svg?style=flat-square 202 | [license-href]: https://npmjs.com/package/@nuxtjs/feed 203 | -------------------------------------------------------------------------------- /test/__snapshots__/module.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`module error on create feed 1`] = `""`; 4 | 5 | exports[`module factory rss 1`] = ` 6 | " 7 | 8 | 9 | Feed Title 10 | http://example.com/ 11 | This is my personal feed! 12 | Fri, 14 Jul 2000 00:00:00 GMT 13 | http://blogs.law.harvard.edu/tech/rss 14 | awesome 15 | 16 | Feed Title 17 | http://example.com/image.png 18 | http://example.com/ 19 | 20 | All rights reserved 2013, John Doe 21 | 22 | 23 | " 24 | `; 25 | 26 | exports[`module function rss 1`] = ` 27 | " 28 | 29 | 30 | Feed Title 31 | http://example.com/ 32 | This is my personal feed! 33 | Fri, 14 Jul 2000 00:00:00 GMT 34 | http://blogs.law.harvard.edu/tech/rss 35 | awesome 36 | 37 | Feed Title 38 | http://example.com/image.png 39 | http://example.com/ 40 | 41 | All rights reserved 2013, John Doe 42 | 43 | 44 | " 45 | `; 46 | 47 | exports[`module generate simple rss 1`] = ` 48 | " 49 | 50 | 51 | Feed Title 52 | http://example.com/ 53 | This is my personal feed! 54 | Fri, 14 Jul 2000 00:00:00 GMT 55 | http://blogs.law.harvard.edu/tech/rss 56 | awesome 57 | 58 | Feed Title 59 | http://example.com/image.png 60 | http://example.com/ 61 | 62 | All rights reserved 2013, John Doe 63 | 64 | 65 | " 66 | `; 67 | 68 | exports[`module multi rss 1`] = ` 69 | " 70 | 71 | 72 | Feed Title 73 | http://example.com/ 74 | This is my personal feed! 75 | Fri, 14 Jul 2000 00:00:00 GMT 76 | http://blogs.law.harvard.edu/tech/rss 77 | awesome 78 | 79 | Feed Title 80 | http://example.com/image.png 81 | http://example.com/ 82 | 83 | All rights reserved 2013, John Doe 84 | 85 | 86 | " 87 | `; 88 | 89 | exports[`module multi rss 2`] = ` 90 | " 91 | 92 | 93 | Feed Title 94 | http://example.com/ 95 | This is my personal feed! 96 | Fri, 14 Jul 2000 00:00:00 GMT 97 | http://blogs.law.harvard.edu/tech/rss 98 | awesome 99 | 100 | Feed Title 101 | http://example.com/image.png 102 | http://example.com/ 103 | 104 | All rights reserved 2013, John Doe 105 | 106 | 107 | " 108 | `; 109 | 110 | exports[`module no type set 1`] = `""`; 111 | 112 | exports[`module non-latin rss 1`] = ` 113 | " 114 | 115 | 116 | Популярные новости России и мира 117 | http://site.ru/feed.xml 118 | Новости России и мира на сайте site.ru 119 | Fri, 14 Jul 2000 00:00:00 GMT 120 | http://blogs.law.harvard.edu/tech/rss 121 | https://github.com/nuxt-community/feed-module 122 | 123 | " 124 | `; 125 | 126 | exports[`module object rss 1`] = ` 127 | " 128 | 129 | 130 | Feed Title 131 | http://example.com/ 132 | This is my personal feed! 133 | Fri, 14 Jul 2000 00:00:00 GMT 134 | http://blogs.law.harvard.edu/tech/rss 135 | awesome 136 | 137 | Feed Title 138 | http://example.com/image.png 139 | http://example.com/ 140 | 141 | All rights reserved 2013, John Doe 142 | 143 | 144 | " 145 | `; 146 | 147 | exports[`module simple atom 1`] = ` 148 | " 149 | 150 | http://example.com/ 151 | Feed Title 152 | 2000-07-14T00:00:00.000Z 153 | awesome 154 | 155 | John Doe 156 | johndoe@example.com 157 | https://example.com/johndoe 158 | 159 | 160 | 161 | This is my personal feed! 162 | http://example.com/image.png 163 | http://example.com/favicon.ico 164 | All rights reserved 2013, John Doe 165 | " 166 | `; 167 | 168 | exports[`module simple json 1`] = ` 169 | "{ 170 | \\"version\\": \\"https://jsonfeed.org/version/1\\", 171 | \\"title\\": \\"Feed Title\\", 172 | \\"home_page_url\\": \\"http://example.com/\\", 173 | \\"feed_url\\": \\"https://example.com/json\\", 174 | \\"description\\": \\"This is my personal feed!\\", 175 | \\"icon\\": \\"http://example.com/image.png\\", 176 | \\"author\\": { 177 | \\"name\\": \\"John Doe\\", 178 | \\"url\\": \\"https://example.com/johndoe\\" 179 | }, 180 | \\"items\\": [] 181 | }" 182 | `; 183 | 184 | exports[`module simple rss 1`] = ` 185 | " 186 | 187 | 188 | Feed Title 189 | http://example.com/ 190 | This is my personal feed! 191 | Fri, 14 Jul 2000 00:00:00 GMT 192 | http://blogs.law.harvard.edu/tech/rss 193 | awesome 194 | 195 | Feed Title 196 | http://example.com/image.png 197 | http://example.com/ 198 | 199 | All rights reserved 2013, John Doe 200 | 201 | 202 | " 203 | `; 204 | --------------------------------------------------------------------------------