From dd222d546306921c5d89d3276843ef4bf47eba3d Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Mon, 2 Dec 2019 15:28:14 +0100 Subject: [PATCH] feat(gatsby-plugin-feed): Allows to override default feed url generation (#19869) --- packages/gatsby-plugin-feed/README.md | 3 + .../__snapshots__/gatsby-ssr.js.snap | 87 +++++++++++++++++++ .../src/__tests__/gatsby-ssr.js | 81 +++++++++++++++++ packages/gatsby-plugin-feed/src/gatsby-ssr.js | 8 +- .../gatsby-plugin-feed/src/plugin-options.js | 1 + 5 files changed, 175 insertions(+), 5 deletions(-) diff --git a/packages/gatsby-plugin-feed/README.md b/packages/gatsby-plugin-feed/README.md index e4dab953e44bf..b6cb778cc4992 100644 --- a/packages/gatsby-plugin-feed/README.md +++ b/packages/gatsby-plugin-feed/README.md @@ -66,6 +66,8 @@ module.exports = { // current page satisfied this regular expression; // if not provided or `undefined`, all pages will have feed reference inserted match: "^/blog/", + // optional configuration to specify external rss feed, such as feedburner + link: "https://feeds.feedburner.com/gatsby/blog", }, ], }, @@ -77,6 +79,7 @@ module.exports = { Each feed must include `output`, `query`, and `title`. Additionally, it is strongly recommended to pass a custom `serialize` function, otherwise an internal serialize function will be used which may not exactly match your particular use case. `match` is an optional configuration, indicating which pages will have feed reference included. The accepted types of `match` are `string` or `undefined`. By default, when `match` is not configured, all pages will have feed reference inserted. If `string` is provided, it will be used to build a RegExp and then to test whether `pathname` of current page satisfied this regular expression. Only pages that satisfied this rule will have feed reference included. +`link` is an optional configuration that will override the default generated rss link from `output`. All additional options are passed through to the [`rss`][rss] utility. For more info on those additional options, [explore the `itemOptions` section of the `rss` package](https://www.npmjs.com/package/rss#itemoptions). diff --git a/packages/gatsby-plugin-feed/src/__tests__/__snapshots__/gatsby-ssr.js.snap b/packages/gatsby-plugin-feed/src/__tests__/__snapshots__/gatsby-ssr.js.snap index b1c8b0a8a37d6..35306a9095567 100644 --- a/packages/gatsby-plugin-feed/src/__tests__/__snapshots__/gatsby-ssr.js.snap +++ b/packages/gatsby-plugin-feed/src/__tests__/__snapshots__/gatsby-ssr.js.snap @@ -72,6 +72,35 @@ exports[`Adds for feed to head creates Link only if pathname satisfied ma } `; +exports[`Adds for feed to head creates Link that override href link generation from output with link set 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Array [ + , + , + ], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + exports[`Adds for feed to head creates Link with a title if it does exist 1`] = ` [MockFunction] { "calls": Array [ @@ -127,3 +156,61 @@ exports[`Adds for feed to head creates multiple Link if feeds are several ], } `; + +exports[`Adds for feed to head testing output prefixes with __PATH_PREFIX__ without path prefix set 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Array [ + , + , + ], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Adds for feed to head testing output with and without prefixes set 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Array [ + , + , + ], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; diff --git a/packages/gatsby-plugin-feed/src/__tests__/gatsby-ssr.js b/packages/gatsby-plugin-feed/src/__tests__/gatsby-ssr.js index d8ffd67d1df97..00e74cd30dbc4 100644 --- a/packages/gatsby-plugin-feed/src/__tests__/gatsby-ssr.js +++ b/packages/gatsby-plugin-feed/src/__tests__/gatsby-ssr.js @@ -134,4 +134,85 @@ describe(`Adds for feed to head`, () => { expect(setHeadComponents).toMatchSnapshot() expect(setHeadComponents).toHaveBeenCalledTimes(1) }) + + it(`creates Link that override href link generation from output with link set`, async () => { + const pluginOptions = { + feeds: [ + { + output: `gryffindor/feed.xml`, + title: `Gryffindor's RSS Feed`, + }, + { + output: `gryffindor/feed.xml`, + title: `Gryffindor's RSS Feed`, + link: `https://harreypetter.com/gryffindor`, + }, + ], + } + const setHeadComponents = jest.fn() + + await onRenderBody( + { + setHeadComponents, + }, + pluginOptions + ) + + expect(setHeadComponents).toMatchSnapshot() + expect(setHeadComponents).toHaveBeenCalledTimes(1) + }) + + it(`testing output with and without prefixes set`, async () => { + const pluginOptions = { + feeds: [ + { + output: `/with-slash-prefix/feed.xml`, + title: `With slash prefix RSS Feed`, + }, + { + output: `without-slash-prefix/feed.xml`, + title: `Without slash prefix RSS Feed`, + }, + ], + } + const setHeadComponents = jest.fn() + + await onRenderBody( + { + setHeadComponents, + }, + pluginOptions + ) + + expect(setHeadComponents).toMatchSnapshot() + expect(setHeadComponents).toHaveBeenCalledTimes(1) + }) + + it(`testing output prefixes with __PATH_PREFIX__ without path prefix set`, async () => { + global.__PATH_PREFIX__ = `without-path-prefix` + + const pluginOptions = { + feeds: [ + { + output: `/output-with-slash-prefix/feed.xml`, + title: `With slash prefix RSS Feed`, + }, + { + output: `output-without-slash-prefix/feed.xml`, + title: `Without slash prefix RSS Feed`, + }, + ], + } + const setHeadComponents = jest.fn() + + await onRenderBody( + { + setHeadComponents, + }, + pluginOptions + ) + + expect(setHeadComponents).toMatchSnapshot() + expect(setHeadComponents).toHaveBeenCalledTimes(1) + }) }) diff --git a/packages/gatsby-plugin-feed/src/gatsby-ssr.js b/packages/gatsby-plugin-feed/src/gatsby-ssr.js index 4a1f9aaf0341f..61bc6da0bb4bf 100644 --- a/packages/gatsby-plugin-feed/src/gatsby-ssr.js +++ b/packages/gatsby-plugin-feed/src/gatsby-ssr.js @@ -16,10 +16,8 @@ exports.onRenderBody = ({ setHeadComponents, pathname }, pluginOptions) => { if (typeof match === `string`) return new RegExp(match).exec(pathname) return true }) - .map(({ output, title }, i) => { - if (output.charAt(0) !== `/`) { - output = `/` + output - } + .map(({ output, title, link }, i) => { + const href = link || withPrefix(output.replace(/^\/?/, `/`)) return ( { rel="alternate" type="application/rss+xml" title={title} - href={withPrefix(output)} + href={href} /> ) }) diff --git a/packages/gatsby-plugin-feed/src/plugin-options.js b/packages/gatsby-plugin-feed/src/plugin-options.js index 095c062e4e470..44a12e417fa96 100644 --- a/packages/gatsby-plugin-feed/src/plugin-options.js +++ b/packages/gatsby-plugin-feed/src/plugin-options.js @@ -7,6 +7,7 @@ const feed = Joi.object({ title: Joi.string(), serialize: Joi.func(), match: Joi.string(), + link: Joi.string(), }).unknown(true) // TODO: make feeds required in next major version bump