From c1d07c43a039164a249e6710831ef4522e91143f Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Sat, 13 Apr 2019 22:52:58 +0200 Subject: [PATCH] generate json feed --- config.js | 2 +- gatsby-config.js | 34 ++++++++---------- gatsby-node.js | 44 +++++++++++++++++++++-- gatsby/feeds.js | 66 +++++++++++++++++++++++++++++++++++ package.json | 1 + src/components/atoms/SEO.jsx | 7 ++++ static/apple-touch-icon.png | Bin 0 -> 10894 bytes 7 files changed, 131 insertions(+), 23 deletions(-) create mode 100644 gatsby/feeds.js create mode 100644 static/apple-touch-icon.png diff --git a/config.js b/config.js index 9a52d826..9afbf64f 100644 --- a/config.js +++ b/config.js @@ -1,7 +1,7 @@ module.exports = { siteTitle: 'kremalicious', siteTitleShort: 'krlc', - siteDescription: 'Blog of designer & developer Matthias Kretschmann.', + siteDescription: 'Blog of designer & developer Matthias Kretschmann', siteUrl: 'https://kremalicious.com', themeColor: '#88bec8', backgroundColor: '#e7eef4', diff --git a/gatsby-config.js b/gatsby-config.js index 48837ee4..afcf113f 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -12,6 +12,7 @@ if (!process.env.GITHUB_TOKEN) { const siteConfig = require('./config') const sources = require('./gatsby/sources') +const { feedContent } = require('./gatsby/feeds') // required for gatsby-plugin-meta-redirect require('regenerator-runtime/runtime') @@ -164,15 +165,18 @@ module.exports = { feeds: [ { serialize: ({ query: { allMarkdownRemark } }) => { - return allMarkdownRemark.edges.map(edge => ({ - title: edge.node.frontmatter.title, - date: edge.node.fields.date, - description: feedContent(edge), - url: siteConfig.siteUrl + edge.node.fields.slug, - categories: edge.node.frontmatter.tags, - author: siteConfig.author.name, - guid: siteConfig.siteUrl + edge.node.fields.slug - })) + return allMarkdownRemark.edges.map(edge => { + return Object.assign({}, edge.node.frontmatter, { + title: edge.node.frontmatter.title, + date: edge.node.fields.date, + description: edge.node.excerpt, + url: siteConfig.siteUrl + edge.node.fields.slug, + categories: edge.node.frontmatter.tags, + author: siteConfig.author.name, + guid: siteConfig.siteUrl + edge.node.fields.slug, + custom_elements: [{ 'content:encoded': feedContent(edge) }] + }) + }) }, query: ` { @@ -184,6 +188,7 @@ module.exports = { node { html fields { slug, date } + excerpt frontmatter { title image { @@ -218,14 +223,3 @@ module.exports = { 'gatsby-plugin-offline' ] } - -const feedContent = edge => { - const { image } = edge.node.frontmatter - const { html } = edge.node - const footer = - '
This post was published on kremalicious.com' - - return image - ? `
${html}${footer}` - : `${html}${footer}` -} diff --git a/gatsby-node.js b/gatsby-node.js index c40d5adb..65e691a3 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -6,6 +6,7 @@ const { generateTagPages, generateRedirectPages } = require('./gatsby/createPages') +const { generateJsonFeed } = require('./gatsby/feeds') const { itemsPerPage } = require('./config') exports.onCreateNode = ({ node, actions, getNode }) => { @@ -50,13 +51,52 @@ exports.createPages = async ({ graphql, actions }) => { // Generate posts & posts index generatePostPages(createPage, posts, numPages) - // Generate Tag Pages + // Generate tag pages generateTagPages(createPage, posts, numPages) - // create manual redirects + // Create manual redirects generateRedirectPages(createRedirect) } +exports.onPostBuild = async ({ graphql }) => { + // JSON Feed query + const result = await graphql(` + { + allMarkdownRemark(sort: { order: DESC, fields: [fields___date] }) { + edges { + node { + html + fields { + slug + date + } + excerpt + frontmatter { + title + tags + updated + image { + childImageSharp { + resize(width: 940, quality: 85) { + src + } + } + } + } + } + } + } + } + `) + + if (result.errors) throw result.errors + + // Generate json feed + await generateJsonFeed(result.data.allMarkdownRemark.edges) + + return Promise.resolve() +} + // Fix web3 // https://github.com/ethereum/web3.js/issues/1105#issuecomment-446039296 exports.onCreateWebpackConfig = ({ actions }) => { diff --git a/gatsby/feeds.js b/gatsby/feeds.js new file mode 100644 index 00000000..1ad0ede9 --- /dev/null +++ b/gatsby/feeds.js @@ -0,0 +1,66 @@ +const fs = require('fs') +const path = require('path') +const pify = require('pify') +const { siteUrl, siteTitle, siteDescription, author } = require('../config') +const writeFile = pify(fs.writeFile) + +const feedContent = edge => { + const { image } = edge.node.frontmatter + const { html } = edge.node + const footer = + '
This post was published on kremalicious.com' + + return image + ? `
${html}${footer}` + : `${html}${footer}` +} + +const generateJsonFeed = async posts => { + const jsonItems = await posts.map(edge => { + const { frontmatter, fields, excerpt } = edge.node + const { slug, date } = fields + + return { + id: path.join(siteUrl, slug), + url: path.join(siteUrl, slug), + title: frontmatter.title, + summary: excerpt, + date_published: new Date(date).toISOString(), + date_modified: frontmatter.updated + ? new Date(frontmatter.updated).toISOString() + : new Date(date).toISOString(), + tags: [frontmatter.tags], + content_html: feedContent(edge) + } + }) + + const jsonFeed = { + version: 'https://jsonfeed.org/version/1', + title: siteTitle, + description: siteDescription, + home_page_url: siteUrl, + feed_url: path.join(siteUrl, 'feed.json'), + user_comment: + 'This feed allows you to read the posts from this site in any feed reader that supports the JSON Feed format. To add this feed to your reader, copy the following URL — https://kremalicious.com/feed.json — and add it your reader.', + favicon: path.join(siteUrl, 'favicon.ico'), + icon: path.join(siteUrl, 'apple-touch-icon.png'), + author: { + name: author.name, + url: author.uri + }, + items: jsonItems + } + + await writeFile( + path.join('./public', 'feed.json'), + JSON.stringify(jsonFeed), + 'utf8' + ).catch(err => { + throw Error('\nFailed to write JSON Feed file: ', err) + }) + + // eslint-disable-next-line no-console + console.log('\nsuccess Generating JSON feed') +} + +module.exports = { generateJsonFeed, feedContent } diff --git a/package.json b/package.json index 4e46b083..d58b6758 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,7 @@ "markdownlint-cli": "^0.15.0", "npm-run-all": "^4.1.5", "ora": "^3.2.0", + "pify": "^4.0.1", "prettier": "^1.17.0", "prettier-stylelint": "^0.4.2", "stylelint": "^10.0.0", diff --git a/src/components/atoms/SEO.jsx b/src/components/atoms/SEO.jsx index 946a9b1d..4bc46364 100644 --- a/src/components/atoms/SEO.jsx +++ b/src/components/atoms/SEO.jsx @@ -120,6 +120,13 @@ const MetaTags = ({ + + ) diff --git a/static/apple-touch-icon.png b/static/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6b6b74f269799cbdc36f978da119caf436913922 GIT binary patch literal 10894 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 C>Ctxp literal 0 HcmV?d00001