From e005f07dca1a83842b7d206b30145a0836aaf27f Mon Sep 17 00:00:00 2001 From: Sivasubramanyam A Date: Sat, 23 Mar 2019 13:36:48 +0530 Subject: [PATCH] Generate RSS Feeds --- README.md | 10 ++++---- lib/lego.js | 3 ++- lib/site.js | 11 ++++----- lib/tasks/generateRSSFeeds.js | 43 +++++++++++++++++++++++++++++++++++ lib/tasks/generateSiteMap.js | 2 +- lib/utils/getPathForPost.js | 14 ++++++++++++ package.json | 1 + yarn.lock | 21 +++++++++++++++++ 8 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 lib/tasks/generateRSSFeeds.js create mode 100644 lib/utils/getPathForPost.js diff --git a/README.md b/README.md index 823a52e..48312f3 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ This was a great learning experience to be honest. * Built with NodeJS. * Supports Liquid templates. -* Supports transpilation, minification and uglification of JS and CSS file(using the provided `browserslist` to determine transpilation targets). -* Does asset revisioning of CSS, JS and image files files. +* Supports minification and uglification of JS and CSS files(using the provided `browserslist` to determine transpilation targets). +* Does asset revisioning of CSS, JS and image files. * JPG and PNG images under `static` will be optimised with `imageoptim`. * Code highlighting at build time using [highlight.js](https://highlightjs.org/). -* Automatic sitemap generation. +* Automatic sitemap and RSS feeds generation. * Supports extracting and inlining critical CSS with [critical](https://github.com/addyosmani/critical). * Supports inlining assets using [inline-source](https://www.npmjs.com/package/inline-source). * Generates images for various resolutions and automatically inserts `picture` elements with the corresponding `source` elements. @@ -142,6 +142,8 @@ that are already included in lego. ] } ``` +* `rss`: Options to pass to the RSS feeds generator. Refer [rss feedOptions](https://www.npmjs.com/package/rss#feedoptions). + Categories and Publishing Date will be automatically populated. ### Installation @@ -158,7 +160,7 @@ that are already included in lego. ``` ::: lego-image src="static/images/${IMAGE}" res="1080,500,320" alt="alternate text" class="img-responsive center-block" ::: ``` -* lego also exposes a `isDevelopment` variable that you can use to disable certain stuff in development. For example, analytics. +* lego also exposes an `isDevelopment` variable that you can use to disable certain stuff in development. For example, analytics. ``` {% unless isDevelopment %} diff --git a/lib/lego.js b/lib/lego.js index b63137c..6c70bec 100644 --- a/lib/lego.js +++ b/lib/lego.js @@ -67,7 +67,8 @@ module.exports = async function(args) { 'optimiseImages', 'extractCritical', 'inlineAssets', - 'generateSiteMap' + 'generateSiteMap', + 'generateRSSFeeds' ] ], site); diff --git a/lib/site.js b/lib/site.js index c3d546b..47ce6ee 100644 --- a/lib/site.js +++ b/lib/site.js @@ -8,6 +8,7 @@ const cleanBuild = require('./utils/cleanBuild'); const filterFileList = require('./utils/filterFileList'); const MdRenderer = require('./utils/MarkdownRenderer'); const loadData = require('./utils/loadData'); +const getPathForPost = require('./utils/getPathForPost'); const { BUILD, POSTS } = require('./utils/constants'); @@ -107,13 +108,9 @@ class Site { return mdRenderer; } - getPathForPost(post, meta) { - let config = this.getConfig(); - let parsedPath = path.parse(post); - let urlFromPath = config.skipDirsInPostUrls ? parsedPath.name : path.join(parsedPath.dir, parsedPath.name); - let postPath = meta.url ? meta.url : urlFromPath; - - return postPath; + getPathForPost(post, { url }) { + let { skipDirsInPostUrls } = this.getConfig(); + return getPathForPost(post, url, skipDirsInPostUrls); } async handlePostChange(event, post) { diff --git a/lib/tasks/generateRSSFeeds.js b/lib/tasks/generateRSSFeeds.js new file mode 100644 index 0000000..20692df --- /dev/null +++ b/lib/tasks/generateRSSFeeds.js @@ -0,0 +1,43 @@ +module.exports = function(site) { + const RSS = require('rss'); + const fs = require('fs-extra'); + const { BUILD } = require('../utils/constants'); + + try { + let message = 'Generating RSS Feeds.'; + site.logger.await(message); + + let { rss, url, author } = site.getConfig(); + if (!rss) { + site.logger.success(message); + return; + } + + let tags = [...new Set(site.getTags())]; + let posts = site.getPosts(); + + let options = Object.assign({ + categories: tags, + pubDate: new Date() + }, rss); + + let feed = new RSS(options); + + for (let post of posts) { + feed.item({ + title: post.title, + description: post.description, + url: `${url}${post.path}`, + categories: post.tags, + author: post.author || author, + date: post.date + }); + } + + fs.writeFileSync(`${BUILD}/rss.xml`, feed.xml({ indent: true })); + + site.logger.success(message); + } catch (error) { + throw error; + } +} diff --git a/lib/tasks/generateSiteMap.js b/lib/tasks/generateSiteMap.js index eb74a0d..3f11ac0 100644 --- a/lib/tasks/generateSiteMap.js +++ b/lib/tasks/generateSiteMap.js @@ -6,7 +6,7 @@ module.exports = async function(site) { try { let writer = fs.createWriteStream(`${BUILD}/sitemap.xml`); - let url = site.getConfig().url; + let { url } = site.getConfig(); if (!url) { throw new Error('Please specify a `url` field in lego.js to generate a sitemap.'); diff --git a/lib/utils/getPathForPost.js b/lib/utils/getPathForPost.js new file mode 100644 index 0000000..1dc1116 --- /dev/null +++ b/lib/utils/getPathForPost.js @@ -0,0 +1,14 @@ +const path = require('path'); + +module.exports = function(post, url, skipDirsInPostUrls) { + if (url) { + return url; + } + + let parsedPath = path.parse(post); + let postPath = skipDirsInPostUrls + ? parsedPath.name + : path.join(parsedPath.dir, parsedPath.name); + + return postPath; +}; diff --git a/package.json b/package.json index 2b96c9c..d502277 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "postcss": "^7.0.1", "postcss-preset-env": "^6.4.0", "rev-hash": "^2.0.0", + "rss": "^1.2.2", "sharp": "^0.20.5", "signale": "^1.2.1", "terser": "^3.10.13", diff --git a/yarn.lock b/yarn.lock index 4fc4b20..8dcec28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3376,6 +3376,16 @@ mime-db@^1.28.0, mime-db@~1.37.0: version "1.37.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" +mime-db@~1.25.0: + version "1.25.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392" + +mime-types@2.1.13: + version "2.1.13" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88" + dependencies: + mime-db "~1.25.0" + mime-types@^2.1.12, mime-types@^2.1.19, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.21" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" @@ -5002,6 +5012,13 @@ rimraf@^2.6.1, rimraf@~2.6.2: dependencies: glob "^7.1.3" +rss@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/rss/-/rss-1.2.2.tgz#50a1698876138133a74f9a05d2bdc8db8d27a921" + dependencies: + mime-types "2.1.13" + xml "1.0.1" + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -5974,6 +5991,10 @@ xdg-basedir@^2.0.0: dependencies: os-homedir "^1.0.0" +xml@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" + xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"