From 010a5e1924c20c871ef40d59747ec034dc76f0c2 Mon Sep 17 00:00:00 2001 From: Amberley Romo Date: Thu, 18 Jul 2019 14:01:20 -0500 Subject: [PATCH] wip from livestream --- .../content/episodes/01-pilot/pilot.mdx | 9 +- .../gatsby-theme-podcast/gatsby-config.js | 8 +- packages/gatsby-theme-podcast/gatsby-node.js | 141 ++---------------- packages/gatsby-theme-podcast/package.json | 1 + .../src/templates/episode-page.js | 10 +- .../wip-gatsby-source-rss-feed/gatsby-node.js | 92 ++++++++++++ packages/wip-gatsby-source-rss-feed/index.js | 1 + .../wip-gatsby-source-rss-feed/package.json | 10 ++ packages/wip-gatsby-source-rss-feed/yarn.lock | 34 +++++ podcast-site/content/episodes/0-intro.mdx | 22 +++ 10 files changed, 187 insertions(+), 141 deletions(-) create mode 100644 packages/wip-gatsby-source-rss-feed/gatsby-node.js create mode 100644 packages/wip-gatsby-source-rss-feed/index.js create mode 100644 packages/wip-gatsby-source-rss-feed/package.json create mode 100644 packages/wip-gatsby-source-rss-feed/yarn.lock create mode 100644 podcast-site/content/episodes/0-intro.mdx diff --git a/packages/gatsby-theme-podcast/content/episodes/01-pilot/pilot.mdx b/packages/gatsby-theme-podcast/content/episodes/01-pilot/pilot.mdx index 27ee366..c445630 100644 --- a/packages/gatsby-theme-podcast/content/episodes/01-pilot/pilot.mdx +++ b/packages/gatsby-theme-podcast/content/episodes/01-pilot/pilot.mdx @@ -1,10 +1,7 @@ --- -title: '01: Pilot episode' -date: '2019-03-20' -time: '33' -description: We talk about stuff. -episodeLink: abcde-12345 -embedUrl: https://hopeinsource.simplecast.com/episodes/1-faith-and-open-source-10d618f0 +title: Woof +boop: "https://anchor.fm/fullstack-health/episodes/0-Intro-e4egsi" +ygatsby: eh --- ## Links diff --git a/packages/gatsby-theme-podcast/gatsby-config.js b/packages/gatsby-theme-podcast/gatsby-config.js index f25e59e..4d63b9f 100644 --- a/packages/gatsby-theme-podcast/gatsby-config.js +++ b/packages/gatsby-theme-podcast/gatsby-config.js @@ -1,6 +1,6 @@ const pkg = require("./package.json"); -module.exports = () => ({ +module.exports = ({ rssSource = "" }) => ({ siteMetadata: { title: "The podcast title", author: "Jane Doe & John Doe", @@ -31,6 +31,12 @@ module.exports = () => ({ modules: [pkg.name] } }, + { + resolve: "@amber1ey/gatsby-source-rss-feed", + options: { + rssSource + } + }, { resolve: "gatsby-source-filesystem", options: { diff --git a/packages/gatsby-theme-podcast/gatsby-node.js b/packages/gatsby-theme-podcast/gatsby-node.js index 01595d0..b82172c 100644 --- a/packages/gatsby-theme-podcast/gatsby-node.js +++ b/packages/gatsby-theme-podcast/gatsby-node.js @@ -1,8 +1,5 @@ const fs = require("fs"); const path = require("path"); -const crypto = require("crypto"); -const Parser = require("rss-parser"); -const parser = new Parser(); exports.onPreBootstrap = ({ reporter }) => { const dirs = [ @@ -20,92 +17,6 @@ exports.onPreBootstrap = ({ reporter }) => { }); }; -const createContentDigest = obj => - crypto - .createHash("md5") - .update(JSON.stringify(obj)) - .digest("hex"); - -const generateRSSItemSlug = title => { - return ( - title - // remove non-alphanumeric characters, except spaces - .replace(/[^\w\s]/gi, "") - .toLowerCase() - .split(" ") - .join("-") - ); -}; - -const durationToMinutes = durationInSeconds => { - return Math.floor(durationInSeconds / 60); -}; - -// hackity hack. this extracts the first paragraph from the description -const extractFirstParagraph = html => { - return html.match(/

(.*?)<\/p>/)[0]; -}; - -async function sourceNodes({ actions }, { rssSource = "" }) { - if (!rssSource) { - console.log(`gatsby-theme-podcast requires an RSS feed`); - return; - } - const { createNode } = actions; - const data = await parser.parseURL(rssSource); - - if (!data) { - return; - } - - // Create nodes for top-level RSS feed info - const { title, description, link, image, items } = data; - - // Prepare RSS item nodes - const preparedRssItemNodes = items.map(rssItem => { - let slug = generateRSSItemSlug(rssItem.title); - let excerpt = extractFirstParagraph(rssItem.content); - let duration = durationToMinutes(rssItem.itunes.duration); - const node = Object.assign({}, rssItem, { - id: rssItem.link, - title: rssItem.title, - content: rssItem.content, - link: rssItem.link, - excerpt, - duration, - slug, - parent: null - }); - node.internal = { - type: "rssFeedItem", - contentDigest: createContentDigest(node) - }; - return node; - }); - - const feedInfo = { - id: link, - title, - description, - link, - imageUrl: image.url, - items___NODE: preparedRssItemNodes.map(node => node.id), - parent: null - }; - - feedInfo.internal = { - type: "rssFeedInfo", - contentDigest: createContentDigest(feedInfo) - }; - - createNode(feedInfo); - - // Actually create nodes for RSS items - preparedRssItemNodes.forEach(rssItemNode => createNode(rssItemNode)); -} - -exports.sourceNodes = sourceNodes; - exports.createPages = async function createPages({ graphql, actions }) { const { createPage } = actions; const rssItemPage = require.resolve("./src/templates/episode-page.js"); @@ -146,49 +57,21 @@ exports.createPages = async function createPages({ graphql, actions }) { }); }; -// * -// * @TODO this is all now outdated -// * These files should only exist in the site/theme starter -// * Need to be pulled in (if exists) to corresponding episode -// * -let userCreatedOwnEpisodes = false; - -exports.onCreateNode = ({ node, actions, getNode }) => { - const { createNodeField } = actions; - - if (node.internal.type === `Mdx`) { - // create source field - const fileNode = getNode(node.parent); - - const source = fileNode.sourceInstanceName; +// Connect mdx notes/transcripts to episode +exports.onCreateNode = async ({ node, actions, getNodesByType }) => { + const { createParentChildLink } = actions; - createNodeField({ - node, - name: `source`, - value: source - }); - - const eligibleEpisodeSources = [ - "podcast-demo-episodes", - "podcast-episodes" - ]; + if (node.internal.type !== `Mdx`) { + return; + } - if (eligibleEpisodeSources.includes(source)) { - if (source === "podcast-episodes") { - userCreatedOwnEpisodes = true; - } + const rssItemNodes = getNodesByType(`rssFeedItem`); - if (userCreatedOwnEpisodes && source === "podcast-demo-episodes") { - return; - } + const filtered = rssItemNodes.find(rssItemNode => { + return rssItemNode.link === node.frontmatter.boop; + }); - // create slug for episode pages - const value = path.parse(node.fileAbsolutePath).name; - createNodeField({ - name: `slug`, - node, - value - }); - } + if (filtered) { + createParentChildLink({ parent: filtered, child: node }); } }; diff --git a/packages/gatsby-theme-podcast/package.json b/packages/gatsby-theme-podcast/package.json index 2df72f8..a03a05e 100644 --- a/packages/gatsby-theme-podcast/package.json +++ b/packages/gatsby-theme-podcast/package.json @@ -5,6 +5,7 @@ "main": "index.js", "license": "MIT", "dependencies": { + "@amber1ey/gatsby-source-rss-feed": "*", "@mdx-js/mdx": "^1.0.4", "@mdx-js/react": "^1.0.2", "gatsby-image": "^2.0.34", diff --git a/packages/gatsby-theme-podcast/src/templates/episode-page.js b/packages/gatsby-theme-podcast/src/templates/episode-page.js index c595a36..3cb5a54 100644 --- a/packages/gatsby-theme-podcast/src/templates/episode-page.js +++ b/packages/gatsby-theme-podcast/src/templates/episode-page.js @@ -3,7 +3,7 @@ import { Link, graphql } from "gatsby"; import get from "lodash.get"; import PodcastPlayer from "syntax-podcast-player"; -// import { MDXRenderer } from "gatsby-plugin-mdx"; +import { MDXRenderer } from "gatsby-plugin-mdx"; import Layout from "../components/Layout"; import Support from "../components/Support"; import SEO from "../components/SEO"; @@ -66,10 +66,7 @@ class RssItemPageTemplate extends React.Component { }} /> -

- @TODO: Need to create a way to add additional episode/show content, - like transcripts and show notes -

+ {rssItem.childMdx.body}

@@ -144,6 +141,9 @@ export const query = graphql` } excerpt duration + childMdx { + body + } } } `; diff --git a/packages/wip-gatsby-source-rss-feed/gatsby-node.js b/packages/wip-gatsby-source-rss-feed/gatsby-node.js new file mode 100644 index 0000000..3d6de98 --- /dev/null +++ b/packages/wip-gatsby-source-rss-feed/gatsby-node.js @@ -0,0 +1,92 @@ +const crypto = require("crypto"); +const Parser = require("rss-parser"); +const parser = new Parser(); + +// Based on and extended from https://github.com/rheajt/gatsby-source-rss/blob/master/src/gatsby-node.js + +const createContentDigest = obj => + crypto + .createHash("md5") + .update(JSON.stringify(obj)) + .digest("hex"); + +const generateRSSItemSlug = title => { + return ( + title + // remove non-alphanumeric characters, except spaces + .replace(/[^\w\s]/gi, "") + .toLowerCase() + .split(" ") + .join("-") + ); +}; + +const durationToMinutes = durationInSeconds => { + return Math.floor(durationInSeconds / 60); +}; + +// hackity hack. this extracts the first paragraph from the description +const extractFirstParagraph = html => { + return html.match(/

(.*?)<\/p>/)[0]; +}; + +async function sourceNodes({ actions }, { rssSource = "" }) { + if (!rssSource) { + console.log(`gatsby-theme-podcast requires an RSS feed`); + return; + } + const { createNode } = actions; + const data = await parser.parseURL(rssSource); + + if (!data) { + return; + } + + // Create nodes for top-level RSS feed info + const { title, description, link, image, items } = data; + + // Prepare RSS item nodes + const preparedRssItemNodes = items.map(rssItem => { + let slug = generateRSSItemSlug(rssItem.title); + let excerpt = extractFirstParagraph(rssItem.content); + let duration = durationToMinutes(rssItem.itunes.duration); + const node = Object.assign({}, rssItem, { + id: rssItem.link, + title: rssItem.title, + content: rssItem.content, + link: rssItem.link, + excerpt, + duration, + slug, + parent: null, + children: [] + }); + node.internal = { + type: "rssFeedItem", + contentDigest: createContentDigest(node) + }; + return node; + }); + + const feedInfo = { + id: link, + title, + description, + link, + imageUrl: image.url, + items___NODE: preparedRssItemNodes.map(node => node.id), + parent: null + }; + + feedInfo.internal = { + type: "rssFeedInfo", + contentDigest: createContentDigest(feedInfo) + }; + + createNode(feedInfo); + + // Actually create nodes for RSS items + preparedRssItemNodes.forEach(rssItemNode => createNode(rssItemNode)); +} + +exports.sourceNodes = sourceNodes; diff --git a/packages/wip-gatsby-source-rss-feed/index.js b/packages/wip-gatsby-source-rss-feed/index.js new file mode 100644 index 0000000..6723592 --- /dev/null +++ b/packages/wip-gatsby-source-rss-feed/index.js @@ -0,0 +1 @@ +// boop diff --git a/packages/wip-gatsby-source-rss-feed/package.json b/packages/wip-gatsby-source-rss-feed/package.json new file mode 100644 index 0000000..9b0d239 --- /dev/null +++ b/packages/wip-gatsby-source-rss-feed/package.json @@ -0,0 +1,10 @@ +{ + "name": "@amber1ey/gatsby-source-rss-feed", + "private": true, + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "rss-parser": "^3.7.2" + } +} diff --git a/packages/wip-gatsby-source-rss-feed/yarn.lock b/packages/wip-gatsby-source-rss-feed/yarn.lock new file mode 100644 index 0000000..34a9928 --- /dev/null +++ b/packages/wip-gatsby-source-rss-feed/yarn.lock @@ -0,0 +1,34 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +entities@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +rss-parser@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/rss-parser/-/rss-parser-3.7.2.tgz#9f5b7d4944d4f7a190b469e31a8353aedb17c052" + integrity sha512-kx0VIFelgwBk5qA4n32U6cx40anAU7TwlRXjyxLDFgMlg8/UcJ64x+Hj5oRX1Kjos+OeFGOmnd5YXH5ES+bmzg== + dependencies: + entities "^1.1.1" + xml2js "^0.4.19" + +sax@>=0.6.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +xml2js@^0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + +xmlbuilder@~9.0.1: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= diff --git a/podcast-site/content/episodes/0-intro.mdx b/podcast-site/content/episodes/0-intro.mdx new file mode 100644 index 0000000..a663437 --- /dev/null +++ b/podcast-site/content/episodes/0-intro.mdx @@ -0,0 +1,22 @@ +--- +title: Meow +boop: "https://anchor.fm/fullstack-health/episodes/0-Intro-e4egsi" +ygatsby: meh +--- + +## Links + +- Example: https://www.example.com + +## Transcript + +Person 1: [00:00](#playFrom=0) So hi, yep, what's up everyone? + +Person 2: [00:29](#playFrom=29) Yep we're making a podcast. + +## Credits + +Hosted by [John Doe](#) and [Jane Doe](#)
+Edited by [John](https://twitter.com/left_pad).
+Cover art by Jessica Doe.
+Music by [James Doe](#).