diff --git a/old_src/components/Footer.js b/old_src/components/Footer.js deleted file mode 100644 index 634480d95..000000000 --- a/old_src/components/Footer.js +++ /dev/null @@ -1,33 +0,0 @@ -import Link from 'next/link'; - -const Footer = () => ( - -); - -export default Footer; diff --git a/old_src/components/Header.js b/old_src/components/Header.js deleted file mode 100644 index 14a2137f9..000000000 --- a/old_src/components/Header.js +++ /dev/null @@ -1,83 +0,0 @@ -import Link from 'next/link'; -import Subscribe from './Subscribe'; - -const Header = () => ( -
-
- - - Syntax - - -
-
-
-

A Tasty Treats Podcast for Web Developers.

- - Ask a Potluck Question → - -
-
-
- Wes Bos -

Wes Bos

- - @wesbos - -

- Full Stack JavaScript Developer. Creator of really good{' '} - - web development courses - - . BBQ enthusiast. -

-
- -
- Scott Tolinski -

Scott Tolinski

- - @stolinski - -

- Web Developer, Creator of Level Up Tuts, - Bboy, Robotops Crew and{' '} - - Youtuber - -

-
-
-
- -
-); - -export default Header; diff --git a/old_src/components/Page.js b/old_src/components/Page.js deleted file mode 100644 index 31c90ae9f..000000000 --- a/old_src/components/Page.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import Header from './Header'; -import Footer from './Footer'; - -function Page({ children }) { - return ( -
- - Skip to content - -
- {children} -
- ); -} - -Page.propTypes = { - children: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.node), - PropTypes.node, - ]).isRequired, -}; - -export default Page; diff --git a/old_src/components/Player.js b/old_src/components/Player.js deleted file mode 100644 index 8b9f51ca7..000000000 --- a/old_src/components/Player.js +++ /dev/null @@ -1,268 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { FaPlay, FaPause } from 'react-icons/fa'; -import formatTime from '../lib/formatTime'; -import VolumeBars from './VolumeBars'; - -export default class Player extends React.Component { - constructor(props) { - super(props); - - let lastPlayed = 0; - let lastVolumePref = 1; - let lastPlaybackRate = 1; - - // for Server Side Rendering - if (typeof window !== 'undefined') { - const { show } = this.props; - const lp = localStorage.getItem(`lastPlayed${show.number}`); - const lastVolume = localStorage.getItem(`lastVolumeSetting`); - const lastPlayback = localStorage.getItem(`lastPlaybackSetting`); - - if (lp) lastPlayed = JSON.parse(lp).lastPlayed; //eslint-disable-line - if (lastVolume) lastVolumePref = JSON.parse(lastVolume).lastVolumePref; //eslint-disable-line - if (lastPlayback) lastPlaybackRate = JSON.parse(lastPlayback).lastPlaybackRate; //eslint-disable-line - } - - 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) { - //eslint-disable-line - this.audio.playbackRate = nextState.playbackRate; - } - - componentDidUpdate(prevProps, prevState) { - //eslint-disable-line - const { show } = this.props; - const { currentTime, currentVolume, playbackRate } = this.state; - if (show.number !== prevProps.show.number) { - const lp = localStorage.getItem(`lastPlayed${show.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); - // eslint-disable-next-line - 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${show.number}`, JSON.stringify({ lastPlayed: currentTime })); - localStorage.setItem(`lastVolumeSetting`, JSON.stringify({ lastVolumePref: currentVolume })); - localStorage.setItem( - `lastPlaybackSetting`, - JSON.stringify({ lastPlaybackRate: playbackRate }) - ); - } - } - - timeUpdate = (e) => { - const { show } = this.props; - const { timeWasLoaded } = this.state; - // Check if the user already had a curent time - if (timeWasLoaded) { - const lp = localStorage.getItem(`lastPlayed${show.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 = () => { - const { onPlayPause } = this.props; - this.setState({ playing: !this.audio.paused }); - onPlayPause(this.audio); - }; - - 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; //eslint-disable-line - - if (playbackRate > playbackRateMax) { - playbackRate = playbackRateMin; - } - - if (playbackRate < playbackRateMin) { - playbackRate = playbackRateMax; - } - - this.setState({ playbackRate }); - }; - - render() { - const { show } = this.props; - const { - playing, - playbackRate, - progressTime, - currentTime, - duration, - showTooltip, - tooltipPosition, - tooltipTime - } = this.state; - - return ( -
-
- -
- -
- {/* eslint-disable */} -
{ - this.setState({ showTooltip: true }); - }} - onMouseLeave={() => { - this.setState({ showTooltip: false }); - }} - ref={(x) => (this.progress = x)} - > - {/* eslint-enable */} - -
-
-

- Playing: {show.displayNumber}: {show.title} -

-
- {tooltipTime} -
-
- -
- -
-

LOUDNESS

-
- -
-
-
- {/* eslint-disable */} - -
- ); - } -} - -Player.propTypes = { - show: PropTypes.object.isRequired, - onPlayPause: PropTypes.func -}; diff --git a/old_src/components/Show.js b/old_src/components/Show.js deleted file mode 100644 index 399153397..000000000 --- a/old_src/components/Show.js +++ /dev/null @@ -1,61 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import slug from 'speakingurl'; -import { FaPlay } from 'react-icons/fa'; -import Link from 'next/link'; -import Bars from './bars'; - -export default class Show extends React.Component { - render() { - const { show, currentPlaying, currentShow, setCurrentPlaying, isPlaying } = - this.props; - return ( -
- - -
-

- Episode {show.displayNumber} -

- | -

{show.displayDate}

-
-

{show.title}

-
- - -
- {currentPlaying === show.displayNumber ? ( - - ) : ( - - )} -
-
- ); - } -} - -Show.propTypes = { - show: PropTypes.object.isRequired, - currentPlaying: PropTypes.string.isRequired, - currentShow: PropTypes.string.isRequired, - setCurrentPlaying: PropTypes.func.isRequired, - isPlaying: PropTypes.bool, -}; diff --git a/old_src/components/ShowList.js b/old_src/components/ShowList.js deleted file mode 100644 index bc03b9e31..000000000 --- a/old_src/components/ShowList.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Show from './Show'; - -const ShowList = ({ - shows, - currentPlaying, - currentShow, - setCurrentPlaying, - isPlaying, -}) => ( -
- {shows.map((show) => ( - - ))} -
-
-); - -ShowList.propTypes = { - shows: PropTypes.array.isRequired, - currentPlaying: PropTypes.string.isRequired, - currentShow: PropTypes.string.isRequired, - setCurrentPlaying: PropTypes.func.isRequired, - isPlaying: PropTypes.bool.isRequired, -}; - -export default ShowList; diff --git a/old_src/components/ShowNotes.js b/old_src/components/ShowNotes.js deleted file mode 100644 index 8d8ddc953..000000000 --- a/old_src/components/ShowNotes.js +++ /dev/null @@ -1,72 +0,0 @@ -/* eslint-disable react/no-danger */ -import React, { useEffect } from 'react'; -import PropTypes from 'prop-types'; - -export default function ShowNotes({ show, setCurrentPlaying }) { - useEffect(() => { - document.querySelector('.showNotes').scrollTop = 0; - }); - - async function handleClick(e) { - const { target } = e; - if (target.matches(`a[href*='#t=']`)) { - e.preventDefault(); - const { href } = target; - const seconds = href - .split('#t=') - .at(-1) - .split(':') - .reverse() - .map(Number) - .map((num, i) => num * 60 ** i) - .reduce((acc, num) => acc + num, 0); - // TODO: This shouldn't use querySelector. It should use a ref. Meh its fine - setCurrentPlaying(show.displayNumber); - const audio = document.querySelector('audio'); - await audio.play(); - audio.currentTime = seconds; - } - } - - return ( -
-

{show.displayDate}

-

{show.title}

- - - 👇 Download Show - - - ✏ī¸ Edit Show Notes - - {/* eslint-disable */} -
- {/* eslint-enable */} -
- ); -} - -ShowNotes.propTypes = { - show: PropTypes.object.isRequired, - setCurrentPlaying: PropTypes.func.isRequired, -}; diff --git a/old_src/components/Subscribe.js b/old_src/components/Subscribe.js deleted file mode 100644 index cf8528f2e..000000000 --- a/old_src/components/Subscribe.js +++ /dev/null @@ -1,73 +0,0 @@ -function Subscribe() { - return ( -
- -
- ); -} - -export default Subscribe; diff --git a/old_src/components/VideoPlayer.js b/old_src/components/VideoPlayer.js deleted file mode 100644 index dd0032622..000000000 --- a/old_src/components/VideoPlayer.js +++ /dev/null @@ -1,21 +0,0 @@ -import ReactHlsPlayer from 'react-hls-player'; - -export default function VideoPlayer() { - return ( -
- -
- ); -} diff --git a/old_src/components/VolumeBars.js b/old_src/components/VolumeBars.js deleted file mode 100644 index 336891ab6..000000000 --- a/old_src/components/VolumeBars.js +++ /dev/null @@ -1,102 +0,0 @@ -import React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; - -// TODO Fix all eslint issues - -// data generator -> to create 11 volume bars -const getItems = (count) => - Array.from({ length: count }, (v, i) => (i + 1) * 10).map((k) => { - const decimal = k / 110; - return { - integer: `${k}`, - deci: `${decimal}`, - vol: `vol${k}`, - level: `Volume Level ${k}/110`, - checked: true, - }; - }); // END MAP // END ARROW -class VolumeBars extends Component { - constructor(props) { - super(props); - this.state = { - volumeBarList: getItems(11), - }; - } - - componentDidMount() { - const localKey = `lastVolumeBarsOn`; - const localStorageRef = localStorage.getItem(localKey); - if (localStorageRef) { - this.setState({ volumeBarList: JSON.parse(localStorageRef) }); - } - } - - componentDidUpdate() { - const localKey = `lastVolumeBarsOn`; - const { volumeBarList } = this.state; - const localValue = JSON.stringify(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; - const volumeBarListCopy = [...volumeBarList]; - // Get the index positions from 0 till index (index clicked) - for (let i = 0; i <= index; i += 1) { - volumeBarListCopy[i].checked = true; - } - // Get the index positions of the remaining non-checked - for (let i = index + 1; i < 11; i += 1) { - volumeBarListCopy[i].checked = null; - } - // Update State - this.setState({ - volumeBarList: volumeBarListCopy, - }); - }; - - render() { - const { volume } = this.props; - const { volumeBarList } = this.state; - return ( - <> - {volumeBarList.map((item, index) => ( - - { - this.handleOnClick(index); - }} - onChange={volume} - type="radio" - name="volume" - value={item.deci} - id={item.vol} - className="sr-only" - /> - - - ))} - - ); - } -} - -VolumeBars.propTypes = { - volume: PropTypes.func.isRequired, -}; - -export default VolumeBars; diff --git a/old_src/components/bars.js b/old_src/components/bars.js deleted file mode 100644 index 7e99a6331..000000000 --- a/old_src/components/bars.js +++ /dev/null @@ -1,19 +0,0 @@ -import PropTypes from 'prop-types'; - -const Bars = ({ isPlaying }) => ( -
-
-
-
-
-
-
-
-
-); - -Bars.propTypes = { - isPlaying: PropTypes.bool, -}; - -export default Bars; diff --git a/old_src/components/meta.js b/old_src/components/meta.js deleted file mode 100644 index 561a87059..000000000 --- a/old_src/components/meta.js +++ /dev/null @@ -1,64 +0,0 @@ -import Head from 'next/head'; -import PropTypes from 'prop-types'; -import slug from 'speakingurl'; - -const Meta = ({ show, staticPage }) => ( - - {show ? ( - <> - - {show.title} — Syntax Podcast {show.displayNumber} - - - - - - - - - ) : ( - - {staticPage && staticPage.title && `${staticPage.title} – `}Syntax - Podcast - - )} - -); - -const requiredPropsCheck = (props, propName, componentName) => { - if (!props.show && !props.staticPage) { - return new Error( - `One of 'show' or 'staticPage' is required by '${componentName}' component.` - ); - } - if (props.show && props.staticPage) { - return new Error( - `Only one of 'show' or 'staticPage' should be passed to '${componentName}' component, not both.` - ); - } - if (props[propName]) { - const myPropType = { - [propName]: PropTypes.shape({ - title: PropTypes.string.isRequired, - }), - }; - PropTypes.checkPropTypes(myPropType, props, propName, componentName); - } -}; - -Meta.propTypes = { - show: requiredPropsCheck, - staticPage: PropTypes.shape({ - title: PropTypes.string.isRequired, - }), -}; - -export default Meta; diff --git a/old_src/lib/formatTime.js b/old_src/lib/formatTime.js deleted file mode 100644 index 8d6bdc72c..000000000 --- a/old_src/lib/formatTime.js +++ /dev/null @@ -1,19 +0,0 @@ -// 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; -} diff --git a/old_src/lib/getShows.js b/old_src/lib/getShows.js deleted file mode 100644 index cd9127ac7..000000000 --- a/old_src/lib/getShows.js +++ /dev/null @@ -1,117 +0,0 @@ -const { promisify } = require('util'); -const path = require('path'); -const marked = require('meta-marked'); -const { readFile, readdir } = require('fs'); -const slug = require('speakingurl'); - -const readAFile = promisify(readFile); -const readDirContents = promisify(readdir); -const format = require('date-fns/format'); - -const pad = (num) => `000${num}`.substr(-3); - -let shows; - -const renderer = new marked.Renderer(); -renderer.link = function (href, title, text) { - return ` ${text}`; -}; - -const loadShows = async () => { - // Cached shows - if (shows) { - return shows; - } - - const showsDir = path.join(process.cwd(), 'shows'); - const files = (await readDirContents(showsDir)).filter((file) => - file.endsWith('.md') - ); - - const markdownPromises = files.map((file) => - readAFile(path.join(showsDir, file), 'utf-8') - ); - const showMarkdown = await Promise.all(markdownPromises); - - shows = showMarkdown - .map((md) => marked(md, { renderer })) // convert to markdown - .map((show, i) => { - const { number } = show.meta; - - return { - ...show.meta, - slug: `/show/${number}/${slug(show.meta.title)}`, - html: show.html, - notesFile: files[i], - displayDate: format(parseFloat(show.meta.date), 'MMM do, yyyy'), - displayNumber: pad(number), - }; - }) // flatten - .reverse(); - - return shows; -}; -async function getShows(filter) { - // eslint-disable-next-line no-shadow - const showsForGetShows = await loadShows(); - const now = Date.now(); - return filter === 'all' - ? showsForGetShows - : showsForGetShows.filter((show) => show.date < now); -} - -async function getShowsList() { - const showsForList = await getShows(); - return showsForList.map((show) => ({ - id: show.number, - title: show.title, - slug: show.slug, - date: show.date, - displayDate: show.displayDate, - displayNumber: show.displayNumber, - url: show.url, - number: show.number, - })); -} - -async function getShow(number) { - const showsForGetShow = await loadShows(); - const show = showsForGetShow.find( - (showItem) => showItem.displayNumber === number - ); - return show; -} - -async function getAllShowSickPicks() { - // Since the sick picks parsed markdown id is not consistent, - // this RegEx finds the first

tag with an id that contains - // the sequential characters "icks" from "picks" and selects - // characters from the string up until the next

tag - // i.e. the next section (usually Shameless Plugs) - const sickPickRegex = /(

*[\s\S]*?(?= - const showsForSickPicks = await getShows(); - return showsForSickPicks.reduce((sickPicksAcc, show) => { - const episode = `

Episode Number: ${show.number} - Sick Picks`; - const sickPickMatch = show.html.match(sickPickRegex); - - if (sickPickMatch) { - const html = sickPickMatch[0].replace(headerRegex, episode); - const sickPick = { - id: show.number, - html, - }; - - return sickPicksAcc.concat(sickPick); - } - - return sickPicksAcc; - }, []); -} - -module.exports = { - getShows, - getShow, - getAllShowSickPicks, - getShowsList, -}; diff --git a/old_src/lib/initMiddleware.js b/old_src/lib/initMiddleware.js deleted file mode 100644 index a70041d7d..000000000 --- a/old_src/lib/initMiddleware.js +++ /dev/null @@ -1,13 +0,0 @@ -// Helper method to wait for a middleware to execute before continuing -// And to throw an error when an error happens in a middleware -export default function initMiddleware(middleware) { - return (req, res) => - new Promise((resolve, reject) => { - middleware(req, res, (result) => { - if (result instanceof Error) { - return reject(result); - } - return resolve(result); - }); - }); -} diff --git a/old_src/next.config.js b/old_src/next.config.js deleted file mode 100644 index 857bd0ffe..000000000 --- a/old_src/next.config.js +++ /dev/null @@ -1,48 +0,0 @@ -const path = require('path'); -const glob = require('glob'); - -module.exports = { - rewrites() { - return [ - { - source: '/', - destination: '/show/latest/latest', - }, - ]; - }, - webpack: (config) => { - config.module.rules.push( - { - test: /\.(css|styl)/, - loader: 'emit-file-loader', - options: { - name: 'dist/[path][name].[ext]', - }, - }, - { - test: /\.css$/, - use: ['babel-loader', 'raw-loader', 'postcss-loader'], - }, - { - test: /\.styl$/, - use: [ - // 'babel-loader', - 'raw-loader', - 'postcss-loader', - { - loader: 'stylus-loader', - options: { - stylusOptions: { - includePaths: ['styles', 'node_modules'] - .map((d) => path.join(__dirname, d)) - .map((g) => glob.sync(g)) - .reduce((a, c) => a.concat(c), []), - }, - }, - }, - ], - } - ); - return config; - }, -}; diff --git a/old_src/package.json b/old_src/package.json deleted file mode 100755 index 84ba05c3c..000000000 --- a/old_src/package.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "name": "syntax", - "description": "Full Stack Developers Wes Bos and Scott Tolinski dive deep into web development topics, explaining how they work and talking about their own experiences. They cover from JavaScript frameworks like React, to the latest advancements in CSS to simplifying web tooling.", - "engines": { - "node": ">=14.0.0" - }, - "scripts": { - "dev": "next dev --port 6969", - "build": "next build", - "start": "next start", - "deploy": "now", - "alias": "now alias", - "lint": "eslint .", - "lint:fix": "eslint . --fix" - }, - "now": { - "alias": [ - "syntax", - "syntax.fm" - ] - }, - "dependencies": { - "@babel/eslint-parser": "^7.16.5", - "@babel/preset-react": "^7.16.7", - "@types/node": "^16.11.19", - "@typescript-eslint/eslint-plugin": "^5.9.1", - "@typescript-eslint/parser": "^5.9.1", - "autoprefixer": "10.4.1", - "babel-loader": "^7.1.5", - "cors": "^2.8.5", - "date-fns": "^2.28.0", - "emit-file-loader": "^0.0.2", - "eslint-config-airbnb-typescript": "^16.1.0", - "glob": "7.2.0", - "meta-marked": "^0.5.0", - "next": "^12.0.7", - "now": "^20.1.2", - "postcss-easy-import": "3.0.0", - "postcss-loader": "6.2.1", - "prop-types": "^15.8.0", - "raw-loader": "^4.0.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-hls-player": "^3.0.7", - "react-icons": "^4.3.1", - "speakingurl": "^14.0.1", - "typescript": "^4.5.4" - }, - "devDependencies": { - "@babel/core": "^7.16.7", - "eslint": "^8.6.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-config-prettier": "^8.3.0", - "eslint-config-wesbos": "^3.0.2", - "eslint-plugin-html": "^6.2.0", - "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0", - "prettier": "^2.5.1", - "stylus": "^0.56.0", - "stylus-loader": "^6.2.0" - } -} diff --git a/old_src/pages/200.js b/old_src/pages/200.js deleted file mode 100644 index a2710cdad..000000000 --- a/old_src/pages/200.js +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import Meta from '../components/meta'; -import Page from '../components/Page'; - -export default class TwoHundy extends React.Component { - render() { - return ( - - -
-

Episode 200!

-

- Ask us anything in the form below and tune in around 11:30ET for a - live stream! -

- -

- Huge thanks to{' '} - - Pigeon Hole - {' '} - for supplying the software for this Q+A. 👇đŸģ -

-