1
0
mirror of https://github.com/kremalicious/blog.git synced 2024-12-22 09:13:35 +01:00

hooks refactoring

This commit is contained in:
Matthias Kretschmann 2019-10-02 15:32:01 +02:00
parent 0946b30b67
commit 3229db8143
Signed by: m
GPG Key ID: 606EEEF3C479A91F
13 changed files with 191 additions and 270 deletions

View File

@ -15,8 +15,8 @@ const feedContent = edge => {
: `${html}${footer}` : `${html}${footer}`
} }
const generateJsonFeed = async posts => { async function jsonItems(posts) {
const jsonItems = await posts.map(edge => { return await posts.map(edge => {
const { frontmatter, fields, excerpt } = edge.node const { frontmatter, fields, excerpt } = edge.node
const { slug, date } = fields const { slug, date } = fields
@ -33,27 +33,29 @@ const generateJsonFeed = async posts => {
content_html: feedContent(edge) content_html: feedContent(edge)
} }
}) })
}
const jsonFeed = { const createJsonFeed = posts => ({
version: 'https://jsonfeed.org/version/1', version: 'https://jsonfeed.org/version/1',
title: siteTitle, title: siteTitle,
description: siteDescription, description: siteDescription,
home_page_url: siteUrl, home_page_url: siteUrl,
feed_url: path.join(siteUrl, 'feed.json'), feed_url: path.join(siteUrl, 'feed.json'),
user_comment: user_comment:
'This feed allows you to read the posts from this site in any feed reader that supports the JSON Feed format. To add this feed to your reader, copy the following URL — https://kremalicious.com/feed.json — and add it your reader.', 'This feed allows you to read the posts from this site in any feed reader that supports the JSON Feed format. To add this feed to your reader, copy the following URL — https://kremalicious.com/feed.json — and add it your reader.',
favicon: path.join(siteUrl, 'favicon.ico'), favicon: path.join(siteUrl, 'favicon.ico'),
icon: path.join(siteUrl, 'apple-touch-icon.png'), icon: path.join(siteUrl, 'apple-touch-icon.png'),
author: { author: {
name: author.name, name: author.name,
url: author.uri url: author.uri
}, },
items: jsonItems items: jsonItems(posts)
} })
const generateJsonFeed = async posts => {
await writeFile( await writeFile(
path.join('./public', 'feed.json'), path.join('./public', 'feed.json'),
JSON.stringify(jsonFeed), JSON.stringify(createJsonFeed(posts)),
'utf8' 'utf8'
).catch(err => { ).catch(err => {
throw Error('\nFailed to write JSON Feed file: ', err) throw Error('\nFailed to write JSON Feed file: ', err)

View File

@ -5,6 +5,7 @@ import styles from './PostActions.module.scss'
import { ReactComponent as Twitter } from '../../images/twitter.svg' import { ReactComponent as Twitter } from '../../images/twitter.svg'
import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg' import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg'
import { ReactComponent as GitHub } from '../../images/github.svg' import { ReactComponent as GitHub } from '../../images/github.svg'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
const ActionContent = ({ const ActionContent = ({
title, title,
@ -23,19 +24,23 @@ const ActionContent = ({
</> </>
) )
const ActionTwitter = ({ url, slug }: { url: string; slug: string }) => ( const ActionTwitter = ({ slug }: { slug: string }) => {
<a const { siteUrl } = useSiteMetadata()
className={styles.action}
href={`https://twitter.com/intent/tweet?text=@kremalicious&url=${url}${slug}`} return (
> <a
<Twitter /> className={styles.action}
<ActionContent href={`https://twitter.com/intent/tweet?text=@kremalicious&url=${siteUrl}${slug}`}
title="Have a comment?" >
text="Hit me up" <Twitter />
textLink="@kremalicious" <ActionContent
/> title="Have a comment?"
</a> text="Hit me up"
) textLink="@kremalicious"
/>
</a>
)
}
const ActionCrypto = ({ toggleModal }: { toggleModal(): void }) => ( const ActionCrypto = ({ toggleModal }: { toggleModal(): void }) => (
<button className={styles.action} onClick={toggleModal}> <button className={styles.action} onClick={toggleModal}>
@ -61,11 +66,9 @@ const ActionGitHub = ({ githubLink }: { githubLink: string }) => (
export default function PostActions({ export default function PostActions({
slug, slug,
url,
githubLink githubLink
}: { }: {
slug: string slug: string
url: string
githubLink: string githubLink: string
}) { }) {
const [showModal, setShowModal] = useState(false) const [showModal, setShowModal] = useState(false)
@ -77,7 +80,7 @@ export default function PostActions({
return ( return (
<aside className={styles.actions}> <aside className={styles.actions}>
<div> <div>
<ActionTwitter url={url} slug={slug} /> <ActionTwitter slug={slug} />
</div> </div>
<div> <div>

View File

@ -3,17 +3,19 @@ import { Link } from 'gatsby'
import Time from 'react-time' import Time from 'react-time'
import slugify from 'slugify' import slugify from 'slugify'
import styles from './PostMeta.module.scss' import styles from './PostMeta.module.scss'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
const PostMeta = ({ post, meta }: { post: any; meta: any }) => { const PostMeta = ({ post }: { post: any }) => {
const { author, updated, tags, type } = post.frontmatter const { author, updated, tags, type } = post.frontmatter
const siteMeta = useSiteMetadata()
const { date } = post.fields const { date } = post.fields
return ( return (
<footer className={styles.entryMeta}> <footer className={styles.entryMeta}>
<div className={styles.byline}> <div className={styles.byline}>
<span className={styles.by}>by</span> <span className={styles.by}>by</span>
<a className="fn" rel="author" href={meta.author.uri}> <a className="fn" rel="author" href={siteMeta.author.uri}>
{author || meta.author.name} {author || siteMeta.author.name}
</a> </a>
</div> </div>

View File

@ -5,5 +5,5 @@ import testRender from '../../../jest/testRender'
import Hamburger from './Hamburger' import Hamburger from './Hamburger'
describe('Hamburger', () => { describe('Hamburger', () => {
testRender(<Hamburger />) testRender(<Hamburger onClick={() => null} />)
}) })

View File

@ -1,21 +1,10 @@
import React from 'react' import React from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import Helmet from 'react-helmet' import Helmet from 'react-helmet'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
const query = graphql` const query = graphql`
query { query {
site {
siteMetadata {
siteTitle
siteDescription
siteUrl
author {
name
twitter
}
}
}
logo: allFile(filter: { name: { eq: "apple-touch-icon" } }) { logo: allFile(filter: { name: { eq: "apple-touch-icon" } }) {
edges { edges {
node { node {
@ -29,7 +18,6 @@ const query = graphql`
const createSchemaOrg = ( const createSchemaOrg = (
blogURL: string, blogURL: string,
title: string, title: string,
siteMeta: any,
postSEO: boolean, postSEO: boolean,
postURL: string, postURL: string,
image: string, image: string,
@ -40,8 +28,7 @@ const createSchemaOrg = (
'@context': 'http://schema.org', '@context': 'http://schema.org',
'@type': 'WebSite', '@type': 'WebSite',
url: blogURL, url: blogURL,
name: title, name: title
alternateName: siteMeta.titleAlt ? siteMeta.titleAlt : ''
} }
] ]
@ -67,7 +54,6 @@ const createSchemaOrg = (
'@type': 'BlogPosting', '@type': 'BlogPosting',
url: blogURL, url: blogURL,
name: title, name: title,
alternateName: siteMeta.titleAlt ? siteMeta.titleAlt : '',
headline: title, headline: title,
image: { image: {
'@type': 'ImageObject', '@type': 'ImageObject',
@ -86,8 +72,7 @@ const MetaTags = ({
url, url,
schema, schema,
postSEO, postSEO,
title, title
siteMeta
}: { }: {
description: string description: string
image: string image: string
@ -95,47 +80,50 @@ const MetaTags = ({
schema: string schema: string
postSEO: boolean postSEO: boolean
title: string title: string
siteMeta: any }) => {
}) => ( const { siteTitle, siteDescription, siteUrl, author } = useSiteMetadata()
<Helmet
defaultTitle={`${siteMeta.siteTitle} ¦ ${siteMeta.siteDescription}`}
titleTemplate={`%s ¦ ${siteMeta.siteTitle}`}
>
<html lang="en" />
{/* General tags */} return (
<meta name="description" content={description} /> <Helmet
<meta name="image" content={image} /> defaultTitle={`${siteTitle} ¦ ${siteDescription}`}
<link rel="canonical" href={url} /> titleTemplate={`%s ¦ ${siteTitle}`}
>
<html lang="en" />
{/* Schema.org tags */} {/* General tags */}
<script type="application/ld+json">{schema}</script> <meta name="description" content={description} />
<meta name="image" content={image} />
<link rel="canonical" href={url} />
{/* OpenGraph tags */} {/* Schema.org tags */}
<meta property="og:url" content={url} /> <script type="application/ld+json">{schema}</script>
{postSEO && <meta property="og:type" content="article" />}
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
{/* Twitter Card tags */} {/* OpenGraph tags */}
<meta name="twitter:card" content="summary_large_image" /> <meta property="og:url" content={url} />
<meta {postSEO && <meta property="og:type" content="article" />}
name="twitter:creator" <meta property="og:title" content={title} />
content={siteMeta.author.twitter ? siteMeta.author.twitter : ''} <meta property="og:description" content={description} />
/> <meta property="og:image" content={image} />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={image} />
<link {/* Twitter Card tags */}
rel="alternate" <meta name="twitter:card" content="summary_large_image" />
title="JSON Feed" <meta
type="application/json" name="twitter:creator"
href={`${siteMeta.siteUrl}/feed.json`} content={author.twitter ? author.twitter : ''}
/> />
</Helmet> <meta name="twitter:title" content={title} />
) <meta name="twitter:description" content={description} />
<meta name="twitter:image" content={image} />
<link
rel="alternate"
title="JSON Feed"
type="application/json"
href={`${siteUrl}/feed.json`}
/>
</Helmet>
)
}
export default function SEO({ export default function SEO({
post, post,
@ -147,8 +135,8 @@ export default function SEO({
postSEO?: boolean postSEO?: boolean
}) { }) {
const data = useStaticQuery(query) const data = useStaticQuery(query)
const siteMeta = data.site.siteMetadata
const logo = data.logo.edges[0].node.relativePath const logo = data.logo.edges[0].node.relativePath
const { siteTitle, siteUrl, siteDescription } = useSiteMetadata()
let title let title
let description let description
@ -157,26 +145,25 @@ export default function SEO({
if (postSEO) { if (postSEO) {
const postMeta = post.frontmatter const postMeta = post.frontmatter
title = `${postMeta.title} ¦ ${siteMeta.siteTitle}` title = `${postMeta.title} ¦ ${siteTitle}`
description = postMeta.description ? postMeta.description : post.excerpt description = postMeta.description ? postMeta.description : post.excerpt
image = postMeta.image image = postMeta.image
? postMeta.image.childImageSharp.fluid.src ? postMeta.image.childImageSharp.fluid.src
: `/${logo}` : `/${logo}`
postURL = `${siteMeta.siteUrl}${slug}` postURL = `${siteUrl}${slug}`
} else { } else {
title = `${siteMeta.siteTitle} ¦ ${siteMeta.siteDescription}` title = `${siteTitle} ¦ ${siteDescription}`
description = siteMeta.siteDescription description = siteDescription
image = `/${logo}` image = `/${logo}`
} }
image = `${siteMeta.siteUrl}${image}` image = `${siteUrl}${image}`
const blogURL = siteMeta.siteUrl const blogURL = siteUrl
const url = postSEO ? postURL : blogURL const url = postSEO ? postURL : blogURL
let schema = createSchemaOrg( let schema = createSchemaOrg(
blogURL, blogURL,
title, title,
siteMeta,
postSEO, postSEO,
postURL, postURL,
image, image,
@ -193,7 +180,6 @@ export default function SEO({
schema={schema} schema={schema}
postSEO={postSEO} postSEO={postSEO}
title={title} title={title}
siteMeta={siteMeta}
/> />
) )
} }

View File

@ -1,6 +1,6 @@
import React from 'react' import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import Helmet from 'react-helmet' import Helmet from 'react-helmet'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
const TypekitScript = (typekitID: string) => ( const TypekitScript = (typekitID: string) => (
<script> <script>
@ -17,19 +17,8 @@ const TypekitScript = (typekitID: string) => (
</script> </script>
) )
const query = graphql`
query {
site {
siteMetadata {
typekitID
}
}
}
`
export default function Typekit() { export default function Typekit() {
const data = useStaticQuery(query) const { typekitID } = useSiteMetadata()
const { typekitID } = data.site.siteMetadata
return ( return (
typekitID && ( typekitID && (

View File

@ -1,32 +1,18 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import Helmet from 'react-helmet' import Helmet from 'react-helmet'
import { Link, graphql, useStaticQuery } from 'gatsby' import { Link } from 'gatsby'
import Hamburger from '../atoms/Hamburger' import Hamburger from '../atoms/Hamburger'
import styles from './Menu.module.scss' import styles from './Menu.module.scss'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
const query = graphql`
query {
site {
siteMetadata {
menu {
title
link
}
}
}
}
`
export default function Menu() { export default function Menu() {
const [menuOpen, setMenuOpen] = useState(false) const [menuOpen, setMenuOpen] = useState(false)
const data = useStaticQuery(query) const { menu } = useSiteMetadata()
const toggleMenu = () => { const toggleMenu = () => {
setMenuOpen(!menuOpen) setMenuOpen(!menuOpen)
} }
const { menu } = data.site.siteMetadata
const MenuItems = menu.map((item: any) => ( const MenuItems = menu.map((item: any) => (
<li key={item.title}> <li key={item.title}>
<Link onClick={toggleMenu} to={item.link}> <Link onClick={toggleMenu} to={item.link}>

View File

@ -1,27 +1,13 @@
import React from 'react' import React from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { useSiteMetadata } from '../../hooks/use-site-metadata'
import Web3Donation from '../Web3Donation' import Web3Donation from '../Web3Donation'
import Qr from '../atoms/Qr' import Qr from '../atoms/Qr'
import Modal from '../atoms/Modal' import Modal from '../atoms/Modal'
import styles from './ModalThanks.module.scss' import styles from './ModalThanks.module.scss'
const query = graphql`
query {
site {
siteMetadata {
author {
bitcoin
ether
}
}
}
}
`
export default function ModalThanks(props: any) { export default function ModalThanks(props: any) {
const data = useStaticQuery(query) const { author } = useSiteMetadata()
const { author } = data.site.siteMetadata
return ( return (
<Modal <Modal
@ -37,11 +23,13 @@ export default function ModalThanks(props: any) {
<p>Send Bitcoin or Ether from any wallet.</p> <p>Send Bitcoin or Ether from any wallet.</p>
</header> </header>
{Object.keys(author).map((address, i) => ( {Object.keys(author)
<div key={i} className={styles.coin}> .filter(key => key === 'bitcoin' || key === 'ether')
<Qr title={address} address={author[address]} /> .map((address, i) => (
</div> <div key={i} className={styles.coin}>
))} <Qr title={address} address={author[address]} />
</div>
))}
</div> </div>
</Modal> </Modal>
) )

View File

@ -1,22 +1,10 @@
import React from 'react' import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import IconLinks from './IconLinks' import IconLinks from './IconLinks'
import styles from './Subscribe.module.scss' import styles from './Subscribe.module.scss'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
const query = graphql`
query {
site {
siteMetadata {
rss
jsonfeed
}
}
}
`
export default function Subscribe() { export default function Subscribe() {
const data = useStaticQuery(query) const { rss, jsonfeed } = useSiteMetadata()
const { rss, jsonfeed } = data.site.siteMetadata
const links = [rss, jsonfeed] const links = [rss, jsonfeed]
return ( return (

View File

@ -3,21 +3,10 @@ import { graphql, useStaticQuery } from 'gatsby'
import Img from 'gatsby-image' import Img from 'gatsby-image'
import IconLinks from './IconLinks' import IconLinks from './IconLinks'
import styles from './Vcard.module.scss' import styles from './Vcard.module.scss'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
const query = graphql` const query = graphql`
query { query {
site {
siteMetadata {
author {
name
uri
twitter
github
facebook
}
}
}
avatar: allFile(filter: { name: { eq: "avatar" } }) { avatar: allFile(filter: { name: { eq: "avatar" } }) {
edges { edges {
node { node {
@ -34,7 +23,7 @@ const query = graphql`
export default function Vcard() { export default function Vcard() {
const data = useStaticQuery(query) const data = useStaticQuery(query)
const { twitter, github, facebook, name, uri } = data.site.siteMetadata.author const { twitter, github, facebook, name, uri } = useSiteMetadata().author
const avatar = data.avatar.edges[0].node.childImageSharp.fixed const avatar = data.avatar.edges[0].node.childImageSharp.fixed
const links = [twitter, github, facebook] const links = [twitter, github, facebook]

View File

@ -1,6 +1,4 @@
import React, { PureComponent } from 'react' import React, { useState } from 'react'
import { StaticQuery, graphql } from 'gatsby'
import Container from '../atoms/Container' import Container from '../atoms/Container'
import Vcard from '../molecules/Vcard' import Vcard from '../molecules/Vcard'
import Subscribe from '../molecules/Subscribe' import Subscribe from '../molecules/Subscribe'
@ -10,85 +8,48 @@ import { ReactComponent as Github } from '../../images/github.svg'
import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg' import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg'
import styles from './Footer.module.scss' import styles from './Footer.module.scss'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
const query = graphql` export default function Footer() {
query { const { name, uri, bitcoin, github } = useSiteMetadata()
site { const year = new Date().getFullYear()
siteMetadata { const [showModal, setShowModal] = useState(false)
author {
name
uri
bitcoin
github
}
}
}
}
`
export default class Footer extends PureComponent< const toggleModal = () => {
{}, setShowModal(!showModal)
{ year: number; showModal: boolean }
> {
state = {
year: null,
showModal: false
} }
toggleModal = () => { return (
this.setState({ showModal: !this.state.showModal }) <footer role="contentinfo" className={styles.footer}>
} <Container>
<Vcard />
<Subscribe />
componentDidMount() { <section className={styles.copyright}>
const year = new Date().getFullYear() <p>
this.setState({ year }) &copy; 2005&ndash;
} {year + ' '}
<a href={uri} rel="me">
{name}
</a>
</p>
render() { <p>
return ( <a href={`${github}/blog`}>
<StaticQuery <Github />
query={query} View source
render={data => { </a>
const { name, uri, bitcoin, github } = data.site.siteMetadata.author <button className={styles.btc} onClick={toggleModal}>
<Bitcoin />
<code>{bitcoin}</code>
</button>
</p>
return ( {showModal && (
<footer role="contentinfo" className={styles.footer}> <ModalThanks isOpen={showModal} handleCloseModal={toggleModal} />
<Container> )}
<Vcard /> </section>
<Subscribe /> </Container>
</footer>
<section className={styles.copyright}> )
<p>
&copy; 2005&ndash;
{this.state.year + ' '}
<a href={uri} rel="me">
{name}
</a>
</p>
<p>
<a href={`${github}/blog`}>
<Github />
View source
</a>
<button className={styles.btc} onClick={this.toggleModal}>
<Bitcoin />
<code>{bitcoin}</code>
</button>
</p>
{this.state.showModal && (
<ModalThanks
isOpen={this.state.showModal}
handleCloseModal={this.toggleModal}
/>
)}
</section>
</Container>
</footer>
)
}}
/>
)
}
} }

View File

@ -0,0 +1,38 @@
import { useStaticQuery, graphql } from 'gatsby'
const query = graphql`
query {
site {
siteMetadata {
siteTitle
siteTitleShort
siteDescription
siteUrl
author {
name
email
uri
twitter
github
facebook
bitcoin
ether
}
typekitID
menu {
title
link
}
rss
jsonfeed
itemsPerPage
repoContentPath
}
}
}
`
export const useSiteMetadata = () => {
const { site } = useStaticQuery(query)
return site.siteMetadata
}

View File

@ -22,7 +22,6 @@ export default function Post({
location: Location location: Location
}) { }) {
const { markdownRemark: post } = data const { markdownRemark: post } = data
const meta = data.site.siteMetadata
const { title, image, type, linkurl, style, tags } = post.frontmatter const { title, image, type, linkurl, style, tags } = post.frontmatter
const { slug, githubLink } = post.fields const { slug, githubLink } = post.fields
@ -47,8 +46,8 @@ export default function Post({
{type !== 'photo' && <PostContent post={post} />} {type !== 'photo' && <PostContent post={post} />}
{type === 'link' && <PostLinkActions slug={slug} linkurl={linkurl} />} {type === 'link' && <PostLinkActions slug={slug} linkurl={linkurl} />}
<PostActions slug={slug} url={meta.siteUrl} githubLink={githubLink} /> <PostActions slug={slug} githubLink={githubLink} />
<PostMeta post={post} meta={meta} /> <PostMeta post={post} />
</article> </article>
{type === 'post' && <RelatedPosts tags={tags} />} {type === 'post' && <RelatedPosts tags={tags} />}
@ -100,15 +99,5 @@ export const pageQuery = graphql`
} }
rawMarkdownBody rawMarkdownBody
} }
site {
siteMetadata {
siteUrl
author {
name
uri
}
}
}
} }
` `