Repository: vojtaholik/gatsby-theme-simplecast Branch: master Commit: 2a67a6834ccb Files: 48 Total size: 91.2 KB Directory structure: gitextract_3x8h2ftp/ ├── .gitignore ├── LICENSE ├── README.md ├── demo/ │ ├── content/ │ │ └── episodes/ │ │ ├── 1/ │ │ │ └── index.md │ │ ├── 2/ │ │ │ └── index.md │ │ ├── 3/ │ │ │ └── index.md │ │ ├── 4/ │ │ │ └── index.md │ │ ├── 5/ │ │ │ └── index.md │ │ ├── 6/ │ │ │ └── index.md │ │ ├── 7/ │ │ │ └── index.md │ │ └── 8/ │ │ └── index.md │ ├── gatsby-config.js │ ├── package.json │ └── src/ │ ├── @vojtaholik/ │ │ └── gatsby-theme-simplecast/ │ │ └── lib/ │ │ └── config/ │ │ └── index.js │ ├── gatsby-plugin-theme-ui/ │ │ └── index.js │ └── pages/ │ ├── 404.js │ ├── index.js │ └── page-2.js ├── gatsby-theme-simplecast/ │ ├── .gitignore │ ├── .prettierrc │ ├── LICENSE │ ├── README.md │ ├── data/ │ │ └── mockupEpisodes.json │ ├── gatsby-browser.js │ ├── gatsby-config.js │ ├── gatsby-node.js │ ├── gatsby-ssr.js │ ├── index.js │ ├── package.json │ └── src/ │ ├── components/ │ │ ├── aside.js │ │ ├── bars.js │ │ ├── context.js │ │ ├── header.js │ │ ├── image.js │ │ ├── layout.css │ │ ├── layout.js │ │ ├── link.js │ │ ├── navigation.js │ │ ├── player.js │ │ ├── seo.js │ │ └── volumeBars.js │ ├── gatsby-plugin-theme-ui/ │ │ └── index.js │ ├── lib/ │ │ ├── config/ │ │ │ └── index.js │ │ └── formatTime.js │ ├── pages/ │ │ ├── 404.js │ │ └── index.js │ └── templates/ │ └── episode.js └── package.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # Typescript v1 declaration files typings/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # dotenv environment variables file .env.* # gatsby files .cache/ public # Mac files .DS_Store # Yarn yarn-error.log .pnp/ .pnp.js # Yarn Integrity file .yarn-integrity ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 Vojta Holik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Gatsby Theme Simplecast ### [→ Preview](https://gatsby-theme-simplecast.netlify.com) ## Running demo - `yarn` - `yarn workspace demo develop` ## Using theme - [Read me →](https://github.com/vojtaholik/gatsby-theme-simplecast/blob/master/gatsby-theme-simplecast/README.md) ================================================ FILE: demo/content/episodes/1/index.md ================================================ --- id: a summary: 'Summary. Lorem ipsum dolor sit amet.' resources: ['[Link](/)','[Link](/)','[Link](/)'] guestName: 'Anna Doe' guestSummary: '[Twitter](/)' image: null guestPhoto: ./guest.png --- Ground round pork shoulder buffalo, short ribs chuck bresaola doner pig burgdoggen andouille turducken shankle strip steak fatback. Beef alcatra swine boudin corned beef drumstick hamburger tri-tip shankle. Meatball leberkas strip steak, burgdoggen biltong swine boudin. T-bone short ribs sausage tri-tip, rump pancetta bacon filet mignon jowl turducken ham. Tri-tip bacon cow rump. Andouille pig fatback kielbasa, venison bacon burgdoggen sirloin sausage tri-tip ground round frankfurter pork chop. Kielbasa shoulder hamburger salami drumstick pork tail landjaeger meatball burgdoggen ribeye pork belly cupim beef ribs. Biltong bacon bresaola, ribeye shank turducken pancetta beef ribs turkey t-bone. Biltong jerky buffalo venison ground round boudin. Picanha fatback t-bone, boudin capicola sirloin biltong. ================================================ FILE: demo/content/episodes/2/index.md ================================================ --- id: b summary: 'Summary. Lorem ipsum dolor sit amet.' image: './banner.png' guestName: 'Charlie Doe' guestSummary: 'Lorem ipsum dolor sit amet. [Twitter](/)' guestPhoto: './guest.png' --- Maecenas a augue vitae mauris interdum accumsan. Morbi auctor velit sed justo tempor, nec blandit purus iaculis. In hac habitasse platea dictumst. Ut in rutrum justo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam ullamcorper libero id sapien eleifend, et ornare lectus rhoncus. Donec tempor dapibus metus, quis ornare diam rhoncus eget. Ut molestie cursus ornare. Aenean iaculis eget enim congue vestibulum. Curabitur imperdiet nisi quis interdum auctor. Vivamus semper consectetur purus, at blandit nibh congue vel. Phasellus rhoncus, leo et commodo tempus, quam metus commodo tellus, sit amet interdum sem leo id nisl. Cras a pretium mauris. Sed nec justo ultricies, tincidunt lorem eu, accumsan dolor. Pellentesque eu auctor nisi, non tincidunt ante. Quisque lacinia dictum risus, a dignissim ipsum malesuada in. Morbi tristique risus metus, at porta mauris fermentum id. Quisque sit amet tincidunt enim, a auctor est. Morbi condimentum vestibulum ex non varius. ================================================ FILE: demo/content/episodes/3/index.md ================================================ --- id: c summary: 'Summary. Lorem ipsum dolor sit amet.' resources: ['[Badass: Making Users Awesome](https://www.goodreads.com/book/show/24737268-badass)', '[Shambhala: The Sacred Path of the Warrior](https://www.goodreads.com/book/show/336248.Shambhala)'] guestName: 'Robert Doe' guestSummary: '[Twitter](https://twitter.com/janelleallen?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor)' guestPhoto: './guest.png' image: './banner.png' --- Flank pork belly leberkas pig jowl corned beef. Hamburger ham salami, venison pastrami strip steak spare ribs pork belly brisket. Bacon chicken tenderloin shankle tongue doner, corned beef shoulder burgdoggen cupim chuck pig turkey. Biltong brisket doner sirloin kielbasa short ribs porchetta prosciutto turkey leberkas ground round landjaeger spare ribs. Kevin strip steak tongue, bacon cupim chicken drumstick rump. Short ribs jowl biltong corned beef chuck, shoulder landjaeger burgdoggen frankfurter sausage hamburger meatball pork loin. Sausage doner beef ribs salami beef shankle. Jerky ground round rump, cow strip steak short loin doner ham hock meatloaf porchetta andouille beef ribs. Tri-tip ribeye doner sirloin, frankfurter meatball tail beef drumstick shankle. Kielbasa pancetta ham, flank fatback jowl turkey boudin leberkas. Tongue drumstick shankle, strip steak picanha pork filet mignon leberkas andouille flank landjaeger short loin corned beef meatball. ================================================ FILE: demo/content/episodes/4/index.md ================================================ --- id: d summary: 'Summary. Lorem ipsum dolor sit amet.' image: './banner.png' resources: ['[Link](/)', '[Link](/)', '[Link](/)'] --- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vel volutpat nulla, vitae egestas dui. Donec sodales eros id purus gravida, quis egestas lorem mollis. Morbi sapien velit, finibus eget dapibus eget, auctor a justo. Etiam cursus congue luctus. Nam dui dolor, convallis vel hendrerit fringilla, interdum vitae odio. Vivamus at interdum nunc, sed cursus magna. Praesent malesuada hendrerit magna nec euismod. Curabitur placerat pellentesque tincidunt. Donec odio justo, ornare ac massa vel, ullamcorper aliquam leo. Fusce facilisis diam vitae mi consequat suscipit. Nunc pharetra magna sit amet dui rhoncus malesuada. Integer hendrerit pellentesque lorem a pulvinar. Aenean at nunc tempus, semper nisi vitae, imperdiet nibh. Donec accumsan lacus ac sapien egestas aliquet. Sed lectus ex, auctor et varius quis, accumsan sed felis. Duis sit amet mattis nisi, sed tempor libero. Curabitur in tristique justo. Cras eu ipsum at nibh tristique iaculis. Suspendisse rhoncus laoreet fringilla. Cras tincidunt odio non facilisis fermentum. Quisque vel odio vel purus molestie pellentesque nec sit amet augue. Duis a neque sodales est pretium porttitor. Praesent at lacus rutrum, elementum dui ac, consequat mi. ================================================ FILE: demo/content/episodes/5/index.md ================================================ --- id: e summary: 'Summary. Lorem ipsum dolor sit amet.' image: './banner.png' --- Pancetta ham hock tongue t-bone pork loin. Boudin burgdoggen alcatra, buffalo beef meatball ham corned beef short loin flank pancetta. Pastrami short loin spare ribs, alcatra shoulder rump pork kielbasa fatback meatball doner swine ribeye. Leberkas tongue shank ball tip prosciutto flank turkey frankfurter pig hamburger. Corned beef swine short ribs boudin. Drumstick rump salami shank jerky flank meatloaf strip steak bresaola bacon brisket tail meatball t-bone pig. Capicola boudin salami porchetta beef turkey brisket. Boudin buffalo chuck capicola. Short ribs meatloaf pork chop drumstick short loin pig frankfurter ground round meatball buffalo shoulder swine prosciutto tail ham. Venison meatball drumstick capicola, pig ribeye biltong fatback porchetta picanha sirloin. Ground round jowl porchetta shankle chuck pancetta. Kevin hamburger corned beef filet mignon tongue prosciutto beef ribs pancetta drumstick short loin chuck capicola. Shankle sausage porchetta shank. Sirloin short loin pork, ground round turkey ribeye chuck tail tri-tip t-bone buffalo bresaola. ================================================ FILE: demo/content/episodes/6/index.md ================================================ --- id: f summary: 'Summary. Lorem ipsum dolor sit amet.' image: './banner.png' --- Ham salami biltong pastrami turkey frankfurter. Ham hock prosciutto pork, tenderloin beef ribs kielbasa swine biltong pancetta boudin turkey hamburger tongue strip steak jowl. Bresaola pork loin venison boudin. Shank pig porchetta boudin. Swine prosciutto short ribs kielbasa shankle ball tip flank ribeye biltong meatloaf salami bacon. Brisket burgdoggen shank corned beef, chicken frankfurter boudin pork loin shankle porchetta jowl ground round sirloin alcatra biltong. Turkey drumstick porchetta alcatra pork jerky, turducken biltong fatback cupim tail. Jerky filet mignon capicola, leberkas jowl brisket venison. Rump jerky boudin prosciutto, sausage short loin chicken pastrami buffalo. ================================================ FILE: demo/content/episodes/7/index.md ================================================ --- id: g summary: 'Summary. Lorem ipsum dolor sit amet.' image: './banner.png' --- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vel volutpat nulla, vitae egestas dui. Donec sodales eros id purus gravida, quis egestas lorem mollis. Morbi sapien velit, finibus eget dapibus eget, auctor a justo. Etiam cursus congue luctus. Nam dui dolor, convallis vel hendrerit fringilla, interdum vitae odio. Vivamus at interdum nunc, sed cursus magna. Praesent malesuada hendrerit magna nec euismod. Curabitur placerat pellentesque tincidunt. Donec odio justo, ornare ac massa vel, ullamcorper aliquam leo. Fusce facilisis diam vitae mi consequat suscipit. Nunc pharetra magna sit amet dui rhoncus malesuada. Integer hendrerit pellentesque lorem a pulvinar. Aenean at nunc tempus, semper nisi vitae, imperdiet nibh. Donec accumsan lacus ac sapien egestas aliquet. Sed lectus ex, auctor et varius quis, accumsan sed felis. Duis sit amet mattis nisi, sed tempor libero. Curabitur in tristique justo. Cras eu ipsum at nibh tristique iaculis. Suspendisse rhoncus laoreet fringilla. Cras tincidunt odio non facilisis fermentum. Quisque vel odio vel purus molestie pellentesque nec sit amet augue. Duis a neque sodales est pretium porttitor. Praesent at lacus rutrum, elementum dui ac, consequat mi. ================================================ FILE: demo/content/episodes/8/index.md ================================================ --- id: h summary: 'Summary. Lorem ipsum dolor sit amet.' image: './banner.png' --- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vel volutpat nulla, vitae egestas dui. Donec sodales eros id purus gravida, quis egestas lorem mollis. Morbi sapien velit, finibus eget dapibus eget, auctor a justo. Etiam cursus congue luctus. Nam dui dolor, convallis vel hendrerit fringilla, interdum vitae odio. Vivamus at interdum nunc, sed cursus magna. Praesent malesuada hendrerit magna nec euismod. Curabitur placerat pellentesque tincidunt. Donec odio justo, ornare ac massa vel, ullamcorper aliquam leo. Fusce facilisis diam vitae mi consequat suscipit. Nunc pharetra magna sit amet dui rhoncus malesuada. Integer hendrerit pellentesque lorem a pulvinar. Aenean at nunc tempus, semper nisi vitae, imperdiet nibh. Donec accumsan lacus ac sapien egestas aliquet. Sed lectus ex, auctor et varius quis, accumsan sed felis. Duis sit amet mattis nisi, sed tempor libero. Curabitur in tristique justo. Cras eu ipsum at nibh tristique iaculis. Suspendisse rhoncus laoreet fringilla. Cras tincidunt odio non facilisis fermentum. Quisque vel odio vel purus molestie pellentesque nec sit amet augue. Duis a neque sodales est pretium porttitor. Praesent at lacus rutrum, elementum dui ac, consequat mi. ================================================ FILE: demo/gatsby-config.js ================================================ require('dotenv').config({ path: `.env.${process.env.NODE_ENV}`, }) module.exports = { plugins: [ { resolve: '@vojtaholik/gatsby-theme-simplecast', options: { simplecastApiSecret: process.env.SIMPLECAST_API_SECRET, //podcastId: process.env.PODCAST_ID, markdownPath: 'content/episodes', episodeSlug: 'show', }, }, `gatsby-plugin-theme-ui`, ], } ================================================ FILE: demo/package.json ================================================ { "private": true, "name": "demo", "version": "1.0.0", "license": "MIT", "scripts": { "build": "gatsby build", "develop": "gatsby develop", "clean": "gatsby clean" }, "dependencies": { "@vojtaholik/gatsby-theme-simplecast": "^1.0.8", "gatsby": "^2.13.41", "gatsby-plugin-theme-ui": "^0.2.18", "gatsby-theme-ui": "^0.2.0", "react": "^16.8.6", "react-dom": "^16.8.6", "theme-ui": "^0.2.21" } } ================================================ FILE: demo/src/@vojtaholik/gatsby-theme-simplecast/lib/config/index.js ================================================ export default { podcastSeason: '1', headerImageHeight: [300, 400], spotifyUrl: '/', applePodcastsUrl: '/', googlePodcastsUrl: '/', } ================================================ FILE: demo/src/gatsby-plugin-theme-ui/index.js ================================================ export default { useCustomProperties: true, initialColorMode: 'dark', colors: { text: 'rgba(255, 255, 255, 0.9)', background: '#1A2232', backgroundLighten10: '#232B3B', backgroundLighten20: '#2C3648', primaryDarken: '#7A5EFF', primary: '#A085FF', primaryLighten10: '#9D82FF', primaryLighten50: '#B298FF', primaryLighten70: '#D2C8FF', secondary: '#85FFD0', }, } ================================================ FILE: demo/src/pages/404.js ================================================ import React from 'react' export default function NotFound() { return (

404 - page not found.

) } ================================================ FILE: demo/src/pages/index.js ================================================ import React from 'react' import {graphql} from 'gatsby' import IndexPage from '@vojtaholik/gatsby-theme-simplecast/src/pages/index' export default function Index({data: {allEpisode, allMarkdownRemark}}) { return } export const indexQuery = graphql` query { allEpisode { totalCount nodes { id title description number enclosure_url fields { slug } } } allMarkdownRemark { edges { node { html frontmatter { id title resources guestSummary guestName guestPhoto { childImageSharp { fluid(maxWidth: 200) { ...GatsbyImageSharpFluid_noBase64 } } } image { childImageSharp { original { src } fluid(maxWidth: 700) { ...GatsbyImageSharpFluid_noBase64 } } } } } } } } ` ================================================ FILE: demo/src/pages/page-2.js ================================================ import React from 'react' export default function Page() { return (

hello!

) } ================================================ FILE: gatsby-theme-simplecast/.gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # Typescript v1 declaration files typings/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # dotenv environment variables file .env.development # gatsby files .cache/ public # Mac files .DS_Store # Yarn yarn-error.log .pnp/ .pnp.js # Yarn Integrity file .yarn-integrity ================================================ FILE: gatsby-theme-simplecast/.prettierrc ================================================ { "endOfLine": "lf", "semi": false, "singleQuote": false, "tabWidth": 2, "trailingComma": "es5" } ================================================ FILE: gatsby-theme-simplecast/LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 gatsbyjs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: gatsby-theme-simplecast/README.md ================================================ # Gatsby Theme Simplecast Gatsby theme that sources data from Simplecast API which can be combined with Markdown files to associate more information to each episode. Inspired by [syntax.fm](http://syntax.fm). [→ Preview Theme](https://gatsby-theme-simplecast.netlify.com) ## Installation To use this theme in your Gatsby sites, follow these instructions: 1. Install the theme ``` yarn add @vojtaholik/gatsby-theme-simplecast ``` 2. Add the theme to your `gatsby-config.js`: ``` module.exports = { plugins: [ { resolve: '@vojtaholik/gatsby-theme-simplecast', options: { podcastId: PODCAST_ID, // theme uses mockup data if no podcastId provided simplecastApiSecret: SIMPLECAST_API_SECRET, markdownPath: 'content/episodes', }, }, ], } ``` Plugin options - `simplecastApiSecret`: Grab [your Simplecast API token here](https://dashboard.simplecast.com/account/private-apps). - `podcastId`: Podcast ID can be found in your Simplecast account under embeds settings. - `markdownPath`: Path to your markdown files. For markdown file to show up, it's `frontmatter.id` must match `episode.id`. - `episodeSlug`: default "show". (`/show/05/episode-title`) 3. Create index page in `src/pages/index.js` - You can use [this example](https://github.com/vojtaholik/gatsby-theme-simplecast/blob/master/demo/src/pages/index.js) which displays latest episode by default. 4. Start your site ``` gatsby develop ``` ================================================ FILE: gatsby-theme-simplecast/data/mockupEpisodes.json ================================================ { "href": "https://api.simplecast.com/podcasts/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/episodes?limit=10", "pages": { "total": 5, "previous": null, "next": { "href": "https://api.simplecast.com/podcasts/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/episodes?limit=10&offset=10&private=true&status=importing%2Caudio_imported%2Ctranscoding%2Ctranscoding_error%2Cdraft%2Cscheduled%2Cpublished%2Cdirty%2Cprivate" }, "limit": 10, "current": 1 }, "dashboard_link": "https://dashboard.simplecast.com/shows/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/episodes", "create": null, "count": 47, "collection": [ { "updated_at": "2019-07-07T21:18:37.988516-07:00", "type": "full", "token": "GRGoBLV0", "title": "Podcast Episode Title", "status": "published", "slug": "podcast-episode-1", "season": { "href": "https://api.simplecast.com/seasons/37157954-19df-4d38-9087-6fe015020f77", "number": 1 }, "scheduled_for": null, "published_at": "2019-07-07T21:18:37.988429-07:00", "number": 8, "is_hidden": false, "image_url": "https://cdn.simplecast.com/images/55d7f360-05c1-43af-9c2d-eb89e156734a/2965154a-b5d2-4479-ab85-6a8b06242014/j_c_hiatt.jpg", "image_path": "/prod/images/55d7f360-05c1-43af-9c2d-eb89e156734a/2965154a-b5d2-4479-ab85-6a8b06242014/j_c_hiatt.jpg", "id": "a", "href": "https://api.simplecast.com/episodes/39917452-ddc9-4b42-8471-a07fc4487277?preview=true", "guid": "a985054e-dc9b-45dd-93c9-3691c3690bec", "enclosure_url": "https://cl.ly/3ba8c8b8d9fe/Helping_Hands_ID_1202.mp3", "description": "Spicy jalapeno biltong kielbasa swine buffalo, prosciutto meatball shank. Tenderloin sirloin ground round, short ribs biltong cow tri-tip sausage buffalo andouille chicken turkey beef ribs shoulder. Tongue bresaola kielbasa picanha salami doner rump. Picanha corned beef tri-tip strip steak drumstick leberkas rump brisket pork loin sausage short ribs frankfurter. Hamburger jerky corned beef biltong kielbasa. Sirloin filet mignon shankle ribeye jerky pig. Spare ribs pork kielbasa tri-tip corned beef capicola.", "analytics": { "href": "https://api.simplecast.com/analytics/downloads?episode=39917452-ddc9-4b42-8471-a07fc4487277&preview=true" } }, { "updated_at": "2019-06-12T12:44:03.792833-07:00", "type": "full", "token": "cMNsoKRl", "title": "Podcast Episode Title", "status": "published", "slug": "podcast-episode-2", "season": { "href": "https://api.simplecast.com/seasons/37157954-19df-4d38-9087-6fe015020f77", "number": 1 }, "scheduled_for": null, "published_at": "2019-05-31T17:22:47.299272-07:00", "number": 7, "is_hidden": false, "image_url": "https://cdn.simplecast.com/images/55d7f360-05c1-43af-9c2d-eb89e156734a/3d52cc0a-c791-4b98-95d1-1b2e45b005b1/Jason_Avatar.jpg", "image_path": "/prod/images/55d7f360-05c1-43af-9c2d-eb89e156734a/3d52cc0a-c791-4b98-95d1-1b2e45b005b1/Jason_Avatar.jpg", "id": "b", "href": "https://api.simplecast.com/episodes/7979994f-c577-4728-aa5e-4f2c1e9314ae?preview=true", "guid": "39623c8c-1401-45e9-a803-382f9136eb26", "enclosure_url": "https://cl.ly/195b9e8b7c60/Lobo_Loco_-_10_-_Pianoman_Play_Sofa_Again_ID_1159.mp3", "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla at sagittis felis. Quisque lacus sapien, consectetur quis nibh nec, dapibus euismod mi. Mauris vel luctus libero. Donec semper suscipit nibh eu mattis. Donec aliquet lacinia laoreet. Ut gravida hendrerit orci eu hendrerit. Nam vel tristique ex.", "analytics": { "href": "https://api.simplecast.com/analytics/downloads?episode=7979994f-c577-4728-aa5e-4f2c1e9314ae&preview=true" } }, { "updated_at": "2019-06-12T12:45:07.197070-07:00", "type": "full", "token": "edf78b39", "title": "Podcast Episode Title", "status": "published", "slug": "edf78b39", "season": { "href": "https://api.simplecast.com/seasons/37157954-19df-4d38-9087-6fe015020f77", "number": 1 }, "scheduled_for": null, "published_at": "2019-05-17T08:00:00.000000-07:00", "number": 6, "is_hidden": false, "image_url": "https://cdn.simplecast.com/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/815fd97a-c688-43a0-89ec-adb51771d245/1558126643artwork.jpg", "image_path": "/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/815fd97a-c688-43a0-89ec-adb51771d245/1558126643artwork.jpg", "id": "c", "href": "https://api.simplecast.com/episodes/815fd97a-c688-43a0-89ec-adb51771d245?preview=true", "guid": "471b8cf9-bd58-425a-9809-823c37e24389", "enclosure_url": "https://cl.ly/4a27ffd65e7c/Lobo_Loco_-_05_-_Overchill_ID_1140.mp3", "description": "Corned beef pork belly prosciutto tenderloin shank capicola. Swine spare ribs pork chop shank ham hock leberkas meatball. Prosciutto venison flank drumstick, bacon sausage pancetta leberkas meatloaf doner shoulder. Sausage ball tip pork chop alcatra, fatback brisket short loin.", "analytics": { "href": "https://api.simplecast.com/analytics/downloads?episode=815fd97a-c688-43a0-89ec-adb51771d245&preview=true" } }, { "updated_at": "2019-06-12T13:00:33.648782-07:00", "type": "full", "token": "b14002cc", "title": "Podcast Episode Title", "status": "published", "slug": "b14002cc", "season": { "href": "https://api.simplecast.com/seasons/37157954-19df-4d38-9087-6fe015020f77", "number": 1 }, "scheduled_for": null, "published_at": "2019-05-13T18:59:00.000000-07:00", "number": 5, "is_hidden": false, "image_url": "https://cdn.simplecast.com/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/831dd452-0017-431f-a6aa-e67f656bcbb5/1557799504artwork.jpg", "image_path": "/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/831dd452-0017-431f-a6aa-e67f656bcbb5/1557799504artwork.jpg", "id": "d", "href": "https://api.simplecast.com/episodes/831dd452-0017-431f-a6aa-e67f656bcbb5?preview=true", "guid": "38e0bb24-2c80-4448-8435-585ef9b87e97", "enclosure_url": "https://cl.ly/b0adbc9c58d4/Art_Of_Escapism_-_Dont_Feel_So_Low.mp3", "description": "Filet mignon leberkas meatball burgdoggen. Pastrami doner chuck, shank tenderloin ground round shankle ham hock burgdoggen cupim swine shoulder. Tenderloin burgdoggen turkey sausage, leberkas tail short ribs strip steak bacon filet mignon. Pork loin leberkas picanha swine.", "analytics": { "href": "https://api.simplecast.com/analytics/downloads?episode=831dd452-0017-431f-a6aa-e67f656bcbb5&preview=true" } }, { "updated_at": "2019-06-12T13:01:22.454517-07:00", "type": "full", "token": "e855d7bc", "title": "Podcast Episode Title", "status": "published", "slug": "e855d7bc", "season": { "href": "https://api.simplecast.com/seasons/37157954-19df-4d38-9087-6fe015020f77", "number": 1 }, "scheduled_for": null, "published_at": "2019-05-03T08:00:00.000000-07:00", "number": 4, "is_hidden": false, "image_url": "https://cdn.simplecast.com/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/27992848-007f-4c0e-b0b6-74518b758f7e/1556842744artwork.jpg", "image_path": "/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/27992848-007f-4c0e-b0b6-74518b758f7e/1556842744artwork.jpg", "id": "e", "href": "https://api.simplecast.com/episodes/27992848-007f-4c0e-b0b6-74518b758f7e?preview=true", "guid": "b61428c6-2974-4deb-a74f-6c22a9c2991f", "enclosure_url": "https://cl.ly/100c0e77180c/Ainst_Char_-_03_-_Your_Cellar_My_Shrine.mp3", "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla at sagittis felis. Quisque lacus sapien, consectetur quis nibh nec, dapibus euismod mi. Mauris vel luctus libero. Donec semper suscipit nibh eu mattis. Donec aliquet lacinia laoreet. Ut gravida hendrerit orci eu hendrerit. Nam vel tristique ex.", "analytics": { "href": "https://api.simplecast.com/analytics/downloads?episode=27992848-007f-4c0e-b0b6-74518b758f7e&preview=true" } }, { "updated_at": "2019-06-12T13:01:58.802141-07:00", "type": "full", "token": "49266475", "title": "Podcast Episode Title", "status": "published", "slug": "49266475", "season": { "href": "https://api.simplecast.com/seasons/37157954-19df-4d38-9087-6fe015020f77", "number": 1 }, "scheduled_for": null, "published_at": "2019-04-29T16:19:00.000000-07:00", "number": 3, "is_hidden": false, "image_url": "https://cdn.simplecast.com/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4/1556580270artwork.jpg", "image_path": "/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4/1556580270artwork.jpg", "id": "f", "href": "https://api.simplecast.com/episodes/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4?preview=true", "guid": "5943566f-d1d5-48e1-9498-6972121ff6fd", "enclosure_url": "https://cl.ly/196987184667/Andrew_Walton_-_02_-_The_Curse_Of_The_Albatross.mp3", "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla at sagittis felis. Quisque lacus sapien, consectetur quis nibh nec, dapibus euismod mi. Mauris vel luctus libero. Donec semper suscipit nibh eu mattis. Donec aliquet lacinia laoreet. Ut gravida hendrerit orci eu hendrerit. Nam vel tristique ex.", "analytics": { "href": "https://api.simplecast.com/analytics/downloads?episode=a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4&preview=true" } }, { "updated_at": "2019-06-12T13:01:58.802141-07:00", "type": "full", "token": "49266475", "title": "Podcast Episode Title", "status": "published", "slug": "49266475", "season": { "href": "https://api.simplecast.com/seasons/37157954-19df-4d38-9087-6fe015020f77", "number": 1 }, "scheduled_for": null, "published_at": "2019-04-29T16:19:00.000000-07:00", "number": 2, "is_hidden": false, "image_url": "https://cdn.simplecast.com/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4/1556580270artwork.jpg", "image_path": "/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4/1556580270artwork.jpg", "id": "g", "href": "https://api.simplecast.com/episodes/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4?preview=true", "guid": "5943566f-d1d5-48e1-9498-6972121ff6fd", "enclosure_url": "https://cl.ly/196987184667/Andrew_Walton_-_02_-_The_Curse_Of_The_Albatross.mp3", "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla at sagittis felis. Quisque lacus sapien, consectetur quis nibh nec, dapibus euismod mi. Mauris vel luctus libero. Donec semper suscipit nibh eu mattis. Donec aliquet lacinia laoreet. Ut gravida hendrerit orci eu hendrerit. Nam vel tristique ex.", "analytics": { "href": "https://api.simplecast.com/analytics/downloads?episode=a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4&preview=true" } }, { "updated_at": "2019-06-12T13:01:58.802141-07:00", "type": "full", "token": "49266475", "title": "Podcast Episode Title", "status": "published", "slug": "49266475", "season": { "href": "https://api.simplecast.com/seasons/37157954-19df-4d38-9087-6fe015020f77", "number": 1 }, "scheduled_for": null, "published_at": "2019-04-29T16:19:00.000000-07:00", "number": 1, "is_hidden": false, "image_url": "https://cdn.simplecast.com/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4/1556580270artwork.jpg", "image_path": "/images/2ac34c/2ac34cab-4949-40aa-bac7-d7e3a70f0a39/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4/1556580270artwork.jpg", "id": "h", "href": "https://api.simplecast.com/episodes/a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4?preview=true", "guid": "5943566f-d1d5-48e1-9498-6972121ff6fd", "enclosure_url": "https://cl.ly/196987184667/Andrew_Walton_-_02_-_The_Curse_Of_The_Albatross.mp3", "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla at sagittis felis. Quisque lacus sapien, consectetur quis nibh nec, dapibus euismod mi. Mauris vel luctus libero. Donec semper suscipit nibh eu mattis. Donec aliquet lacinia laoreet. Ut gravida hendrerit orci eu hendrerit. Nam vel tristique ex.", "analytics": { "href": "https://api.simplecast.com/analytics/downloads?episode=a593adfa-6bc5-4774-9fe9-cc5e34e6f2c4&preview=true" } } ], "average_duration": 1994.26 } ================================================ FILE: gatsby-theme-simplecast/gatsby-browser.js ================================================ import React from "react" import Layout from "./src/components/layout" import Player from "./src/components/player" import { EpisodeProvider, EpisodeConsumer } from "./src/components/context" import { ThemeProvider, Styled } from "theme-ui" import theme from "./src/gatsby-plugin-theme-ui/index" import { SkipNavLink } from "@reach/skip-nav" export const wrapPageElement = ({ element, props }, options) => { const episodeSlug = options.episodeSlug ? options.episodeSlug : "show" return ( {props.location.pathname.includes(episodeSlug) || props.location.pathname === "/" ? ( {context => } ) : null} {element} ) } ================================================ FILE: gatsby-theme-simplecast/gatsby-config.js ================================================ module.exports = ({ markdownPath = `${__dirname}/content/episodes` }) => ({ siteMetadata: { title: `Podcast Name`, description: `Podcast description.`, author: `@vojtaholik`, }, plugins: [ `gatsby-plugin-react-helmet`, `gatsby-plugin-sharp`, `gatsby-transformer-remark`, `gatsby-transformer-sharp`, `gatsby-plugin-theme-ui`, { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/src/images`, }, }, { resolve: `gatsby-source-filesystem`, options: { path: markdownPath, name: `episodes`, }, }, { resolve: `gatsby-plugin-manifest`, options: { name: `gatsby-theme-simplecast`, short_name: `simplecast`, start_url: `/`, background_color: `#A085FF`, theme_color: `#A085FF`, display: `minimal-ui`, icon: `src/images/icon.png`, // This path is relative to the root of the site. }, }, // this (optional) plugin enables Progressive Web App + Offline functionality // To learn more, visit: https://gatsby.dev/offline // `gatsby-plugin-offline`, ], }) ================================================ FILE: gatsby-theme-simplecast/gatsby-node.js ================================================ require("dotenv").config({ path: `.env.${process.env.NODE_ENV}`, }) const axios = require("axios") const crypto = require("crypto") const path = require("path") const slugify = require("@sindresorhus/slugify") exports.sourceNodes = async ( { actions: { createNode, createNodeField }, plugins }, options ) => { axios.defaults.headers.common.Authorization = `Bearer ${options.simplecastApiSecret}` axios.defaults.headers.common.Accept = "application/json" const mockupEpisodes = require("./data/mockupEpisodes.json") const { data } = options.podcastId ? await axios( `https://api.simplecast.com/podcasts/${options.podcastId}/episodes` ) : mockupEpisodes const packagePodcast = p => { const nodeContent = JSON.stringify(p) const nodeContentDigest = crypto .createHash("md5") .update(nodeContent) .digest("hex") const node = { ...p, content: nodeContent, internal: { type: "Episode", contentDigest: nodeContentDigest, }, } createNode(node) } // fallback to mockup data if no podcast id provided options.podcastId ? data.collection.map(packagePodcast) : mockupEpisodes.collection.map(packagePodcast) } exports.createPages = async ({ actions, graphql }, options) => { const { data } = await graphql(` { site { siteMetadata { title } } allEpisode { edges { node { id title number } } } allMarkdownRemark { edges { node { id html frontmatter { title } } } } } `) data.allEpisode.edges.forEach(({ node }, options) => { actions.createPage({ path: `${options.episodeSlug ? options.episodeSlug : "show"}/${ node.number }/${slugify(node.title)}`, component: require.resolve(`./src/templates/episode.js`), context: { slug: slugify(node.title), id: node.id, title: node.title, }, }) }) } exports.onCreateNode = ({ node, getNode, actions }, options) => { const { createNodeField } = actions const showsSlug = options.episodeSlug ? options.episodeSlug : "show" createNodeField({ name: "slug", node, value: "/" + showsSlug + "/" + node.number + "/" + slugify(`${node.title}`), }) } ================================================ FILE: gatsby-theme-simplecast/gatsby-ssr.js ================================================ import React from "react" import Layout from "./src/components/layout" import Player from "./src/components/player" import { EpisodeProvider, EpisodeConsumer } from "./src/components/context" import { ThemeProvider, Styled } from "theme-ui" import theme from "./src/gatsby-plugin-theme-ui/index" import { SkipNavLink } from "@reach/skip-nav" export const wrapPageElement = ({ element, props }, options) => { const episodeSlug = options.episodeSlug ? options.episodeSlug : "show" return ( {props.location.pathname.includes(episodeSlug) || props.location.pathname === "/" ? ( {context => } ) : null} {element} ) } ================================================ FILE: gatsby-theme-simplecast/index.js ================================================ /** @jsx jsx */ import { jsx } from "theme-ui" import { graphql } from "gatsby" import Episode from "gatsby-theme-simplecast/src/templates/episode" export default function Index({ data: { allEpisode, allMarkdownRemark } }) { const MarkdownForLatestEpisode = allMarkdownRemark.edges.filter( Markdown => Markdown.node.frontmatter.id === allEpisode.nodes[0].id ) const data = useStaticQuery(graphql` { allEpisode { totalCount nodes { id title description number enclosure_url fields { slug } } } allMarkdownRemark { edges { node { html frontmatter { id title resources guestSummary guestName guestPhoto { childImageSharp { fluid(maxWidth: 200) { ...GatsbyImageSharpFluid_noBase64 } } } image { childImageSharp { original { src } fluid(maxWidth: 700) { ...GatsbyImageSharpFluid_noBase64 } } } } } } } } `) return ( ) } ================================================ FILE: gatsby-theme-simplecast/package.json ================================================ { "name": "@vojtaholik/gatsby-theme-simplecast", "main": "index.js", "description": "Simplecast gatsby theme.", "version": "1.0.8", "author": "Vojta Holik ", "dependencies": { "@emotion/core": "^10.0.14", "@emotion/styled": "^10.0.14", "@mdx-js/react": "^1.0.27", "@reach/skip-nav": "^0.1.3", "@reach/visually-hidden": "^0.1.4", "@sindresorhus/slugify": "^0.9.1", "axios": "^0.19.0", "crypto": "^1.0.1", "dotenv": "^8.0.0", "fs": "^0.0.1-security", "gatsby": "^2.13.41", "gatsby-image": "^2.2.7", "gatsby-plugin-manifest": "^2.2.4", "gatsby-plugin-offline": "^2.2.4", "gatsby-plugin-react-helmet": "^3.1.2", "gatsby-plugin-sharp": "^2.2.9", "gatsby-plugin-theme-ui": "^0.2.18", "gatsby-source-filesystem": "^2.1.6", "gatsby-theme-ui": "^0.2.0", "gatsby-transformer-json": "^2.2.2", "gatsby-transformer-remark": "^2.6.9", "gatsby-transformer-sharp": "^2.2.4", "lodash": "^4.17.15", "prop-types": "^15.7.2", "react": "^16.8.6", "react-dom": "^16.8.6", "react-helmet": "^5.2.1", "react-icons": "^3.7.0", "react-markdown": "^4.1.0", "react-onclickoutside": "^6.8.0", "theme-ui": "^0.2.21" }, "devDependencies": { "gatsby": "^2.13.41", "prettier": "^1.18.2", "react": "^16.8.6", "react-dom": "^16.8.6", "theme-ui": "^0.2.21" }, "keywords": [ "gatsby", "gatsby-theme", "gatsby-plugin", "simplecast" ], "license": "MIT", "scripts": { "build": "gatsby build", "develop": "gatsby develop", "clean": "gatsby clean", "format": "prettier --write src/**/*.{js,jsx}", "start": "npm run develop", "serve": "gatsby serve", "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"" }, "repository": { "type": "git", "url": "https://github.com/vojtaholik/gatsby-theme-simplecast" }, "bugs": { "url": "https://github.com/vojtaholik/gatsby-theme-simplecast/issues" }, "peerDependencies": { "gatsby": "^2.13.41", "react": "^16.8.6", "react-dom": "^16.8.6", "theme-ui": "^0.2.21" } } ================================================ FILE: gatsby-theme-simplecast/src/components/aside.js ================================================ /** @jsx jsx */ import { jsx } from "theme-ui" import Img from "gatsby-image" import { FaExternalLinkAlt as ExternalLinkIcon } from "react-icons/fa" import config from "../lib/config" import { css } from "@emotion/core" import styled from "@emotion/styled" import Link from "./link" import Markdown from "react-markdown" import itunesIcon from "../images/apple.svg" import spotifyImage from "../images/spotify.png" import googleImage from "../images/google.svg" const PodcastProvider = styled(Link)( css({ mb: 5, display: "flex", alignItems: "center", img: { m: 0, mr: 3 }, }) ) function Aside({ markdown }) { return ( ) } export default Aside ================================================ FILE: gatsby-theme-simplecast/src/components/bars.js ================================================ import React from "react" const Bars = () => (
) export default Bars ================================================ FILE: gatsby-theme-simplecast/src/components/context.js ================================================ import React, { Component } from "react" import { graphql, useStaticQuery } from "gatsby" const EpisodeContext = React.createContext() export function EpisodeProvider(props) { const data = useStaticQuery(graphql` { allEpisode { totalCount nodes { id title description number enclosure_url fields { slug } } } } `) const [currentPlaying, setCurrentPlaying] = React.useState( data.allEpisode.nodes[0] ) return ( ) } export class EpisodeConsumer extends Component { render() { return ( {this.props.children} ) } } ================================================ FILE: gatsby-theme-simplecast/src/components/header.js ================================================ /** @jsx jsx */ import { jsx, useThemeUI, Header as ThemedHeader, Box, Flex } from "theme-ui" import Img from "gatsby-image" import { FaPlay as PlayIcon } from "react-icons/fa" import VisuallyHidden from "@reach/visually-hidden" import config from "../lib/config" function Header({ context, episode, image }) { const themeContext = useThemeUI() const { theme } = themeContext return ( {image && ( {episode.title} )}

{episode.title}

EP{episode.number}
) } export default Header ================================================ FILE: gatsby-theme-simplecast/src/components/image.js ================================================ import React from "react" import { useStaticQuery, graphql } from "gatsby" import Img from "gatsby-image" /* * This component is built using `gatsby-image` to automatically serve optimized * images with lazy loading and reduced file sizes. The image is loaded using a * `useStaticQuery`, which allows us to load the image from directly within this * component, rather than having to pass the image data down from pages. * * For more information, see the docs: * - `gatsby-image`: https://gatsby.dev/gatsby-image * - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/ */ const Image = () => { const data = useStaticQuery(graphql` query { placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) { childImageSharp { fluid(maxWidth: 300) { ...GatsbyImageSharpFluid } } } } `) return } export default Image ================================================ FILE: gatsby-theme-simplecast/src/components/layout.css ================================================ html { font-family: sans-serif; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; } body { margin: 0; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .progress { background: gray; /* height: 2rem; */ cursor: crosshair; overflow: hidden; } .progress__time { background: green; border-right: 1px solid rgba(0, 0, 0, 0.1); min-width: 5px; height: 100%; transition: width 0.1s; background: yellow; } article, aside, details, figcaption, figure, footer, header, main, menu, nav, section, summary { display: block; } audio, canvas, progress, video { display: inline-block; } audio:not([controls]) { display: none; height: 0; } progress { vertical-align: baseline; } [hidden], template { display: none; } a { background-color: transparent; -webkit-text-decoration-skip: objects; } a:active, a:hover { outline-width: 0; } abbr[title] { border-bottom: none; text-decoration: underline; text-decoration: underline dotted; } b, strong { font-weight: inherit; font-weight: bolder; } dfn { font-style: italic; } h1 { font-size: 2em; margin: 0.67em 0; } mark { background-color: #ff0; color: #000; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } img { border-style: none; } svg:not(:root) { overflow: hidden; } code, kbd, pre, samp { font-family: monospace, monospace; font-size: 1em; } figure { margin: 1em 40px; } hr { box-sizing: content-box; height: 0; overflow: visible; } button, input, optgroup, select, textarea { font: inherit; margin: 0; } optgroup { font-weight: 700; } button, input { overflow: visible; } button, select { text-transform: none; } [type="reset"], [type="submit"], button, html [type="button"] { -webkit-appearance: button; } [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner, button::-moz-focus-inner { border-style: none; padding: 0; } [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring, button:-moz-focusring { outline: 1px dotted ButtonText; } fieldset { border: 1px solid silver; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } legend { box-sizing: border-box; color: inherit; display: table; max-width: 100%; padding: 0; white-space: normal; } textarea { overflow: auto; } [type="checkbox"], [type="radio"] { box-sizing: border-box; padding: 0; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { -webkit-appearance: textfield; outline-offset: -2px; } [type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-input-placeholder { color: inherit; opacity: 0.54; } ::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; } html { font: 112.5%/1.45em georgia, serif; box-sizing: border-box; overflow-y: scroll; } * { box-sizing: inherit; } *:before { box-sizing: inherit; } *:after { box-sizing: inherit; } body { color: hsla(0, 0%, 0%, 0.8); font-family: georgia, serif; font-weight: normal; word-wrap: break-word; font-kerning: normal; -moz-font-feature-settings: "kern", "liga", "clig", "calt"; -ms-font-feature-settings: "kern", "liga", "clig", "calt"; -webkit-font-feature-settings: "kern", "liga", "clig", "calt"; font-feature-settings: "kern", "liga", "clig", "calt"; } img { max-width: 100%; margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } h1 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 2.25rem; line-height: 1.1; } h2 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 1.62671rem; line-height: 1.1; } h3 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 1.38316rem; line-height: 1.1; } h4 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 1rem; line-height: 1.1; } h5 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 0.85028rem; line-height: 1.1; } h6 { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; color: inherit; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-weight: bold; text-rendering: optimizeLegibility; font-size: 0.78405rem; line-height: 1.1; } hgroup { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } ul { list-style: none; margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; list-style-position: outside; list-style-image: none; } ol { margin-left: 1.45rem; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; list-style-position: outside; list-style-image: none; } dl { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } dd { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } p { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } figure { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } pre { margin-left: 0; margin-right: 0; margin-top: 0; margin-bottom: 1.45rem; font-size: 0.85rem; line-height: 1.42; background: hsla(0, 0%, 0%, 0.04); border-radius: 3px; overflow: auto; word-wrap: normal; padding: 1.45rem; } table { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; font-size: 1rem; line-height: 1.45rem; border-collapse: collapse; width: 100%; } fieldset { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } blockquote { margin-left: 1.45rem; margin-right: 1.45rem; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } form { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } noscript { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } iframe { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } hr { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: calc(1.45rem - 1px); background: hsla(0, 0%, 0%, 0.2); border: none; height: 1px; } address { margin-left: 0; margin-right: 0; margin-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0; padding-top: 0; margin-bottom: 1.45rem; } b { font-weight: bold; } strong { font-weight: bold; } dt { font-weight: bold; } th { font-weight: bold; } li { margin-bottom: calc(1.45rem / 2); } ol li { padding-left: 0; } ul li { padding-left: 0; } li > ol { margin-left: 1.45rem; margin-bottom: calc(1.45rem / 2); margin-top: calc(1.45rem / 2); } li > ul { margin-left: 1.45rem; margin-bottom: calc(1.45rem / 2); margin-top: calc(1.45rem / 2); } blockquote *:last-child { margin-bottom: 0; } li *:last-child { margin-bottom: 0; } p *:last-child { margin-bottom: 0; } li > p { margin-bottom: calc(1.45rem / 2); } code { font-size: 0.85rem; line-height: 1.45rem; } kbd { font-size: 0.85rem; line-height: 1.45rem; } samp { font-size: 0.85rem; line-height: 1.45rem; } abbr { border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); cursor: help; } acronym { border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); cursor: help; } abbr[title] { border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); cursor: help; text-decoration: none; } thead { text-align: left; } td, th { text-align: left; border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); font-feature-settings: "tnum"; -moz-font-feature-settings: "tnum"; -ms-font-feature-settings: "tnum"; -webkit-font-feature-settings: "tnum"; padding-left: 0.96667rem; padding-right: 0.96667rem; padding-top: 0.725rem; padding-bottom: calc(0.725rem - 1px); } th:first-child, td:first-child { padding-left: 0; } th:last-child, td:last-child { padding-right: 0; } tt, code { background-color: hsla(0, 0%, 0%, 0.04); border-radius: 3px; font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono", "Liberation Mono", Menlo, Courier, monospace; padding: 0; padding-top: 0.2em; padding-bottom: 0.2em; } pre code { background: none; line-height: 1.42; } code:before, code:after, tt:before, tt:after { letter-spacing: -0.2em; content: " "; } pre code:before, pre code:after, pre tt:before, pre tt:after { content: ""; } @media only screen and (max-width: 480px) { html { font-size: 100%; } } .bars { height: 45px; width: 0; position: relative; top: -9px; left: -1px; display: flex; flex-direction: column; align-items: flex-end; } .bar { background: #a085ff; bottom: 1px; height: 3px; position: absolute; width: 3px; animation: sound 0ms -800ms linear infinite alternate; } .bars--paused > * { animation-play-state: paused; } @keyframes sound { 0% { opacity: 0.35; background: #a085ff; width: 3px; } 100% { opacity: 1; background: #a085ff; width: 10px; } } .bar:nth-child(1) { top: 1px; animation-duration: 474ms; } .bar:nth-child(2) { top: 5px; animation-duration: 433ms; } .bar:nth-child(3) { top: 9px; animation-duration: 407ms; } .bar:nth-child(4) { top: 13px; animation-duration: 458ms; } .bar:nth-child(5) { top: 17px; animation-duration: 400ms; } .bar:nth-child(6) { top: 21px; animation-duration: 427ms; } .bar:nth-child(7) { top: 25px; animation-duration: 441ms; } .bar:nth-child(8) { top: 29px; animation-duration: 419ms; } .bar:nth-child(9) { top: 33px; animation-duration: 487ms; } .bar:nth-child(10) { top: 37px; animation-duration: 442ms; } .bar:nth-child(11) { top: 41px; animation-duration: 435ms; } .bar:nth-child(12) { top: 45px; animation-duration: 510ms; } .bar:nth-child(13) { top: 49px; animation-duration: 485ms; } .bar:nth-child(14) { top: 53px; animation-duration: 455ms; } .bar:nth-child(15) { top: 57px; animation-duration: 425ms; } ================================================ FILE: gatsby-theme-simplecast/src/components/layout.js ================================================ /** @jsx jsx */ import PropTypes from "prop-types" import Navigation from "./navigation" import "./layout.css" import { jsx, Layout as Wrapper, Container } from "theme-ui" function Layout({ children }) { return (
{children}
) } Layout.propTypes = { children: PropTypes.node.isRequired, } export default Layout ================================================ FILE: gatsby-theme-simplecast/src/components/link.js ================================================ import React from "react" import GatsbyLink from "gatsby-link" const Link = ({ children, to, ...other }) => { const internal = /^\/(?!\/)/.test(to) if (internal) { return ( {children} ) } return ( {children} ) } export default Link ================================================ FILE: gatsby-theme-simplecast/src/components/navigation.js ================================================ /** @jsx jsx */ import React from "react" import { useStaticQuery, graphql } from "gatsby" import { jsx, Flex } from "theme-ui" import { EpisodeConsumer } from "./context" import { FaPlay as PlayIcon } from "react-icons/fa" import { MdMenu as MenuIcon, MdClose as CloseMenuIcon } from "react-icons/md" import onClickOutside from "react-onclickoutside" import config from "../lib/config" import Link from "./link" import Bars from "./bars" function Navigation() { const [isOpen, setIsOpen] = React.useState(false) const toggleMenu = () => setIsOpen(!isOpen) Navigation.handleClickOutside = () => setIsOpen(false) const twoDigits = n => (n.toString().length < 2 ? `0${n}` : n) const Logo = () => ( <>

{data.site.siteMetadata.title ? data.site.siteMetadata.title : "Podcast Name"}

{config.podcastSeason && (
season {twoDigits(config.podcastSeason)}
)} ) const data = useStaticQuery(graphql` query navQuery { site { siteMetadata { title } } allEpisode { totalCount nodes { id title description number enclosure_url fields { slug } } } allMarkdownRemark { edges { node { id frontmatter { id summary } } } } } `) return ( {context => ( <> )} ) } const clickOutsideConfig = { handleClickOutside: () => Navigation.handleClickOutside, } export default onClickOutside(Navigation, clickOutsideConfig) ================================================ FILE: gatsby-theme-simplecast/src/components/player.js ================================================ // by Wes Bos, syntax.fm // https://github.com/wesbos/Syntax/blob/master/components/Player.js /** @jsx jsx */ import React from "react" import PropTypes from "prop-types" import { FaPlay, FaPause } from "react-icons/fa" import { jsx, Container } from "theme-ui" import { keyframes } from "@emotion/core" import formatTime from "../lib/formatTime" import VisuallyHidden from "@reach/visually-hidden" // import VolumeBars from "./volumeBars" export default class Player extends React.Component { static propTypes = { episode: PropTypes.object.isRequired, } constructor(props) { super(props) let lastPlayed = 0 let lastVolumePref = 1 // let lastPlaybackRate = 1 // for Server Side Rendering if (typeof window !== "undefined") { const { episode } = this.props const lp = localStorage.getItem(`lastPlayed${episode.number}`) const lastVolume = localStorage.getItem(`lastVolumeSetting`) // const lastPlayback = localStorage.getItem(`lastPlaybackSetting`) if (lp) lastPlayed = JSON.parse(lp).lastPlayed if (lastVolume) lastVolumePref = JSON.parse(lastVolume).lastVolumePref // if (lastPlayback) // lastPlaybackRate = JSON.parse(lastPlayback).lastPlaybackRate } this.state = { progressTime: 50, playing: false, duration: 0, currentTime: lastPlayed, currentVolume: lastVolumePref, // playbackRate: lastPlaybackRate, timeWasLoaded: lastPlayed !== 0, showTooltip: false, tooltipPosition: 0, tooltipTime: "0:00", } } // END Constructor componentWillUpdate(nextProps, nextState) { // this.audio.playbackRate = nextState.playbackRate } componentDidUpdate(prevProps, prevState) { const { episode } = this.props const { currentTime, currentVolume, // playbackRate } = this.state if (episode.number !== prevProps.episode.number) { const lp = localStorage.getItem(`lastPlayed${episode.number}`) if (lp) { const lastVolume = localStorage.getItem(`lastVolumeSetting`) // const lastPlayback = localStorage.getItem(`lastPlaybackSetting`) const data = JSON.parse(lp) const data2 = JSON.parse(lastVolume) // const data3 = JSON.parse(lastPlayback) this.setState({ currentTime: data.lastPlayed, currentVolume: data2.lastVolumePref, // playbackRate: data3.lastPlaybackRate, }) this.audio.currentTime = data.lastPlayed this.audio.volume = data2.lastVolumePref // this.audio.playbackRate = data3.lastPlaybackRate } this.audio.play() } else { localStorage.setItem( `lastPlayed${episode.number}`, JSON.stringify({ lastPlayed: currentTime }) ) localStorage.setItem( `lastVolumeSetting`, JSON.stringify({ lastVolumePref: currentVolume }) ) // localStorage.setItem( // `lastPlaybackSetting`, // JSON.stringify({ lastPlaybackRate: playbackRate }) // ) } } timeUpdate = e => { // console.log('Updating Time'); const { episode } = this.props const { timeWasLoaded } = this.state // Check if the user already had a curent time if (timeWasLoaded) { const lp = localStorage.getItem(`lastPlayed${episode.number}`) if (lp) { e.currentTarget.currentTime = JSON.parse(lp).lastPlayed } this.setState({ timeWasLoaded: false }) } else { const { currentTime = 0, duration = 0 } = e.currentTarget const progressTime = (currentTime / duration) * 100 if (Number.isNaN(progressTime)) return this.setState({ progressTime, currentTime, duration }) } } volumeUpdate = e => { const { timeWasLoaded } = this.state // Check if the user already had a curent volume if (timeWasLoaded) { const lastVolume = localStorage.getItem(`lastVolumeSetting`) if (lastVolume) { e.currentTarget.volume = JSON.parse(lastVolume).lastVolumePref } this.setState({ timeWasLoaded: false }) } } groupUpdates = e => { this.timeUpdate(e) this.volumeUpdate(e) } togglePlay = () => { const { playing } = this.state const method = playing ? "pause" : "play" this.audio[method]() } scrubTime = eventData => (eventData.nativeEvent.offsetX / this.progress.offsetWidth) * this.audio.duration scrub = e => { this.audio.currentTime = this.scrubTime(e) } seekTime = e => { this.setState({ tooltipPosition: e.nativeEvent.offsetX, tooltipTime: formatTime(this.scrubTime(e)), }) } playPause = () => { this.setState({ playing: !this.audio.paused }) const method = this.audio.paused ? "add" : "remove" document.querySelector(".bars").classList[method]("bars--paused") // 💩 } volume = e => { this.audio.volume = e.currentTarget.value this.setState({ currentVolume: `${e.currentTarget.value}`, }) } speedUp = () => { this.speed(0.25) } speedDown = e => { e.preventDefault() this.speed(-0.25) } // speed = change => { // const playbackRateMax = 2.5 // const playbackRateMin = 0.75 // let playbackRate = this.state.playbackRate + change // if (playbackRate > playbackRateMax) { // playbackRate = playbackRateMin // } // if (playbackRate < playbackRateMin) { // playbackRate = playbackRateMax // } // this.setState({ playbackRate }) // } render() { const { episode } = this.props const { playing, // playbackRate, progressTime, currentTime, duration, showTooltip, tooltipPosition, tooltipTime, } = this.state const bounce = keyframes` from { transform: translateX(0) } to { transform: translateX(-200px) } ` return (

{episode.title} - EP{episode.number}

{formatTime(currentTime)}
{ this.setState({ showTooltip: true }) }} onMouseLeave={() => { this.setState({ showTooltip: false }) }} ref={x => (this.progress = x)} > {/* eslint-enable */}
{formatTime(duration)}
{tooltipTime}
{/*
*/} {/*

LOUDNESS

*/}
) } } ================================================ FILE: gatsby-theme-simplecast/src/components/seo.js ================================================ /** * SEO component that queries for data with * Gatsby's useStaticQuery React hook * * See: https://www.gatsbyjs.org/docs/use-static-query/ */ import React from "react" import PropTypes from "prop-types" import Helmet from "react-helmet" import { useStaticQuery, graphql } from "gatsby" function SEO({ description, lang, meta, title, image }) { const { site } = useStaticQuery( graphql` query { site { siteMetadata { title description author } } } ` ) const metaDescription = description || site.siteMetadata.description return ( ) } SEO.defaultProps = { lang: `en`, meta: [], description: ``, } SEO.propTypes = { description: PropTypes.string, lang: PropTypes.string, meta: PropTypes.arrayOf(PropTypes.object), title: PropTypes.string.isRequired, } export default SEO ================================================ FILE: gatsby-theme-simplecast/src/components/volumeBars.js ================================================ import React, { Component, Fragment } from "react" // TODO Fix all eslint issues // data generator -> to create 10 volume bars const getItems = count => { return Array.from({ length: count }, (v, i) => (i + 1) * 10).map(k => { let decimal = k / 100 return { integer: `${k}`, deci: `${decimal}`, vol: `vol${k}`, level: `${k}/100`, checked: true, } }) // END MAP } // END ARROW class VolumeBars extends Component { state = { volumeBarList: getItems(10), } componentDidMount() { const localKey = `lastVolumeBarsOn` const localStorageRef = localStorage.getItem(localKey) if (localStorageRef) { this.setState({ volumeBarList: JSON.parse(localStorageRef) }) } } componentDidUpdate(prevProps, prevState) { const localKey = `lastVolumeBarsOn` const localValue = JSON.stringify(this.state.volumeBarList) localStorage.setItem(localKey, localValue) } //We are going to track which volume bars are "checked" handleOnClick = index => { // make a copy of state const volumeBarList = [...this.state.volumeBarList] // Get the index positions from 0 till index (index clicked) for (let i = 0; i <= index; i++) { volumeBarList[i].checked = true } // Get the index positions of the remaining non-checked for (let i = index + 1; i < 10; i++) { volumeBarList[i].checked = null } // Update State this.setState({ volumeBarList, }) } render() { return ( {this.state.volumeBarList.map((item, index) => ( { this.handleOnClick(index) }} onChange={this.props.volume} type="radio" name="volume" value={item.deci} id={item.vol} className="sr-only" /> ))} ) } } export default VolumeBars ================================================ FILE: gatsby-theme-simplecast/src/gatsby-plugin-theme-ui/index.js ================================================ import config from "../lib/config" export default { useCustomProperties: true, initialColorMode: "dark", breakpoints: ["992px", "1200px", "1920px"], space: [0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 56, 64, 72, 80, 128, 256, 512], sizes: [0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 56, 64, 72, 80, 128, 256, 512], fontSizes: [12, 14, 16, 18, 20, 22, 24, 32, 40, 48, 64], colors: { modes: { dark: { text: "rgba(255, 255, 255, 0.9)", background: "#1A2232", backgroundLighten10: "#232B3B", backgroundLighten20: "#2C3648", primaryDarken: "#7A5EFF", primary: "#A085FF", primaryLighten10: "#9D82FF", primaryLighten50: "#B298FF", primaryLighten70: "#D2C8FF", secondary: "#85FFD0", }, }, }, radii: [5, "50%"], fontWeights: { body: 300, heading: 500, }, lineHeights: { body: 1.675, heading: 1.125, }, letterSpacings: { heading: "1.5", }, fonts: { body: "system-ui, sans-serif", heading: "inherit", }, header: { logo: { flexDirection: "column", justifyContent: "center", a: { textDecoration: "none" }, container: { p: 3, display: ["flex", "none"], visibility: ["visible", "hidden"], width: "100%", justifyContent: "space-between", alignItems: "center", }, }, }, styles: { color: "primary", Header: { position: "relative", display: "flex", flexDirection: "column", width: "100%", height: config.headerImageHeight, color: "text", h1: { fontSize: [6, 8], textShadow: "0 2px 5px rgba(0,0,0,0.2)" }, "h1, h5": { m: 0 }, h5: { mt: 1, fontSize: 1, opacity: 0.6 }, ".header_content": { width: "100%", height: "100%", position: "absolute", //pb: [5, 8], px: [5, 8], zIndex: 1, display: "flex", alignItems: "flex-start", justifyContent: "flex-end", button: { width: "100%", maxWidth: 7, height: 7, background: "transparent", border: "1px solid", borderColor: "text", color: "text", fontSize: "10px", borderRadius: 1, display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", mr: 3, mt: 2, svg: { mt: "1px", ml: "2px", }, }, }, }, root: { ".episodes_list": { backgroundColor: "background", position: ["absolute", "static"], zIndex: 2, width: "100%", maxWidth: [375, 300], px: 5, pt: 40, a: { textDecoration: "none", color: "text", fontSize: 3, fontWeight: "heading", }, li: { py: 0, display: "flex", justifyContent: "flex-start", alignItems: "center", ".summary": { fontSize: 2, lineHeight: 1.4, fontWeight: 300, opacity: 0.7, mt: 3, }, ".active": { borderLeft: "3px solid", borderColor: "primary", backgroundColor: "backgroundLighten10", }, a: { px: 5, py: 4, borderLeft: "3px solid", borderColor: "background", fontSize: 4, width: "100%", }, ":hover": { a: { borderColor: "backgroundLighten10" }, ".active": { borderColor: "primary", }, button: { opacity: 1, ":hover": { opacity: 1, }, }, }, h4: { mb: 0, }, button: { position: "absolute", opacity: 0, ml: -3, backgroundColor: "background", border: "1px solid", borderColor: "text", color: "text", display: "flex", width: "100%", maxWidth: "24px", height: "24px", flexGrow: "1", borderRadius: "50%", alignItems: "center", justifyContent: "center", svg: { mt: "1px", ml: "1px" }, cursor: "pointer", }, }, }, "[data-reach-skip-link]": { border: "0", clip: "rect(0 0 0 0)", height: "1px", width: "1px", margin: "-1px", padding: "0", overflow: "hidden", position: "absolute", zIndex: "999", }, "[data-reach-skip-link]:focus": { padding: "1rem", position: "fixed", top: "10px", left: "10px", backgroundColor: "background", width: "auto", height: "auto", clip: "auto", }, backgroundColor: "background", lineHeight: "body", fontFamily: "body", fontSize: [2, 3], color: "text", bg: "background", a: { color: "primaryLighten50", }, "a:hover": { color: "primaryLighten70", }, article: { p: [5, 8], pb: [2, 14], borderLeft: "2px solid", borderRight: "2px solid", borderColor: "backgroundLighten10", }, ".sidebar": { display: "flex", flexDirection: "column", p: [5, 8], pb: [13, 8], width: "100%", maxWidth: ["100%", 250], fontSize: "15px", h5: { my: 4, fontSize: 3 }, "h5:not(:first-of-type)": { mb: 10, mt: 0 }, ".guest": { fontSize: 1, textTransform: "uppercase", opacity: 0.8, fontWeight: "body", }, li: { mb: 2, display: "flex", a: { color: "text" }, svg: { mt: 1, mr: 1, width: "100%", maxWidth: 3, color: "text", opacity: 0.5, }, }, }, hr: { backgroundColor: "backgroundLighten10", height: "2px", }, }, Container: { maxWidth: 1200, }, a: { color: "primary", textDecoration: "none", ":hover": { color: "secondary", textDecoration: "underline", }, }, }, } ================================================ FILE: gatsby-theme-simplecast/src/lib/config/index.js ================================================ export default { podcastSeason: "1", headerImageHeight: [300, 400], spotifyUrl: "/", applePodcastsUrl: "/", googlePodcastsUrl: "/", } ================================================ FILE: gatsby-theme-simplecast/src/lib/formatTime.js ================================================ // TODO figure out the ~~ thing export default function formatTime(time) { // Hours, minutes and seconds const hrs = Math.floor(~~(time / 3600)) // eslint-disable-line const mins = Math.floor(~~((time % 3600) / 60)) // eslint-disable-line const secs = Math.floor(time % 60) // Output like "1:01" or "4:03:59" or "123:03:59" let ret = "" if (hrs > 0) { ret += `${hrs}:${mins < 10 ? "0" : ""}` } ret += `${mins}:${secs < 10 ? "0" : ""}` ret += `${secs}` return ret } ================================================ FILE: gatsby-theme-simplecast/src/pages/404.js ================================================ import React from "react" import Layout from "../components/layout" import SEO from "../components/seo" const NotFoundPage = () => (

NOT FOUND

You just hit a route that doesn't exist... the sadness.

) export default NotFoundPage ================================================ FILE: gatsby-theme-simplecast/src/pages/index.js ================================================ /** @jsx jsx */ import { jsx } from "theme-ui" import { graphql, useStaticQuery } from "gatsby" import Episode from "../templates/episode" export default function Index({ data: { allEpisode, allMarkdownRemark } }) { const MarkdownForLatestEpisode = allMarkdownRemark.edges.filter( Markdown => Markdown.node.frontmatter.id === allEpisode.nodes[0].id ) const data = useStaticQuery(graphql` { allEpisode { totalCount nodes { id title description number enclosure_url fields { slug } } } allMarkdownRemark { edges { node { html frontmatter { id title resources guestSummary guestName guestPhoto { childImageSharp { fluid(maxWidth: 200) { ...GatsbyImageSharpFluid_noBase64 } } } image { childImageSharp { original { src } fluid(maxWidth: 700) { ...GatsbyImageSharpFluid_noBase64 } } } } } } } } `) return ( ) } ================================================ FILE: gatsby-theme-simplecast/src/templates/episode.js ================================================ /** @jsx jsx */ import { jsx } from "theme-ui" import { graphql } from "gatsby" import { EpisodeConsumer } from "../components/context" import SEO from "../components/seo" import Header from "../components/header" import Aside from "../components/aside" import { SkipNavContent } from "@reach/skip-nav" function EpisodeTemplate({ data: { episode, markdownRemark } }) { const image = markdownRemark && markdownRemark.frontmatter.image const markdown = markdownRemark && markdownRemark return ( {context => (

{episode.description && episode.description}

{markdown && (
)}
)}
) } export default EpisodeTemplate export const episodeQuery = graphql` query($id: String!) { episode(id: { eq: $id }) { id title description number enclosure_url fields { slug } } markdownRemark(frontmatter: { id: { eq: $id } }) { html frontmatter { id title resources guestName guestSummary guestPhoto { childImageSharp { fluid(maxWidth: 200) { ...GatsbyImageSharpFluid } } } image { childImageSharp { original { src } fluid(maxWidth: 700) { ...GatsbyImageSharpFluid } } } } } } ` ================================================ FILE: package.json ================================================ { "private": true, "workspaces": [ "gatsby-theme-simplecast", "demo" ] }