1
0
mirror of https://github.com/kremalicious/blog.git synced 2024-12-22 17:23:50 +01:00

gatsby v3 updates

This commit is contained in:
Matthias Kretschmann 2021-03-13 04:11:44 +01:00
parent 3aa87e0e82
commit 2c171a5ee7
Signed by: m
GPG Key ID: 606EEEF3C479A91F
14 changed files with 1119 additions and 36014 deletions

View File

@ -42,9 +42,5 @@ module.exports = {
title: '/Uses', title: '/Uses',
link: '/uses' link: '/uses'
} }
], ]
darkModeConfig: {
classNameDark: 'dark',
classNameLight: 'light'
}
} }

View File

@ -220,13 +220,6 @@ module.exports = {
exclude: ['/archive', '/archive/**/*', '/thanks', '/tags'] exclude: ['/archive', '/archive/**/*', '/thanks', '/tags']
} }
}, },
{
resolve: 'gatsby-plugin-use-dark-mode',
options: {
...siteConfig.darkModeConfig,
minify: true
}
},
'gatsby-plugin-react-helmet', 'gatsby-plugin-react-helmet',
'gatsby-plugin-catch-links', 'gatsby-plugin-catch-links',
'gatsby-redirect-from', 'gatsby-redirect-from',

36905
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -29,32 +29,31 @@
"not op_mini all" "not op_mini all"
], ],
"dependencies": { "dependencies": {
"@ethersproject/providers": "^5.0.23", "@ethersproject/providers": "^5.0.24",
"@ethersproject/units": "^5.0.10", "@ethersproject/units": "^5.0.11",
"@loadable/component": "^5.14.1", "@loadable/component": "^5.14.1",
"@web3-react/core": "^6.1.9", "@web3-react/core": "^6.1.9",
"@web3-react/injected-connector": "^6.0.7", "@web3-react/injected-connector": "^6.0.7",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"date-fns": "^2.17.0", "date-fns": "^2.19.0",
"dms2dec": "^1.1.0", "dms2dec": "^1.1.0",
"ethereum-blockies": "github:MyEtherWallet/blockies", "ethereum-blockies": "github:MyEtherWallet/blockies",
"fast-exif": "^1.0.1", "fast-exif": "^1.0.1",
"feather-icons": "^4.28.0", "feather-icons": "^4.28.0",
"fraction.js": "^4.0.13", "fraction.js": "^4.0.13",
"gatsby": "^3.0.3", "gatsby": "^3.0.4",
"gatsby-plugin-catch-links": "^3.0.0", "gatsby-plugin-catch-links": "^3.0.0",
"gatsby-plugin-feed": "^3.0.0", "gatsby-plugin-feed": "^3.0.0",
"gatsby-plugin-image": "^1.0.0", "gatsby-plugin-image": "^1.0.1",
"gatsby-plugin-lunr": "^1.5.2", "gatsby-plugin-lunr": "^1.5.2",
"gatsby-plugin-manifest": "^3.0.0", "gatsby-plugin-manifest": "^3.0.0",
"gatsby-plugin-matomo": "^0.9.0", "gatsby-plugin-matomo": "^0.9.0",
"gatsby-plugin-meta-redirect": "^1.1.1", "gatsby-plugin-meta-redirect": "^1.1.1",
"gatsby-plugin-offline": "^4.0.0", "gatsby-plugin-offline": "^4.0.0",
"gatsby-plugin-react-helmet": "^4.0.0", "gatsby-plugin-react-helmet": "^4.0.0",
"gatsby-plugin-sharp": "^3.0.0", "gatsby-plugin-sharp": "^3.0.1",
"gatsby-plugin-sitemap": "^3.0.0", "gatsby-plugin-sitemap": "^3.0.0",
"gatsby-plugin-svgr": "^3.0.0-beta.0", "gatsby-plugin-svgr": "^3.0.0-beta.0",
"gatsby-plugin-use-dark-mode": "^1.3.0",
"gatsby-plugin-webpack-size": "^1.0.0", "gatsby-plugin-webpack-size": "^1.0.0",
"gatsby-redirect-from": "^0.3.0", "gatsby-redirect-from": "^0.3.0",
"gatsby-remark-autolink-headers": "^3.0.0", "gatsby-remark-autolink-headers": "^3.0.0",
@ -80,29 +79,28 @@
"react-transition-group": "^4.4.1", "react-transition-group": "^4.4.1",
"remark": "^13.0.0", "remark": "^13.0.0",
"remark-react": "^8.0.0", "remark-react": "^8.0.0",
"slugify": "^1.4.7", "slugify": "^1.4.7"
"use-dark-mode": "^2.3.1"
}, },
"devDependencies": { "devDependencies": {
"@svgr/webpack": "^5.5.0", "@svgr/webpack": "^5.5.0",
"@testing-library/jest-dom": "^5.11.9", "@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.5", "@testing-library/react": "^11.2.5",
"@types/classnames": "^2.2.11", "@types/classnames": "^2.2.11",
"@types/fs-extra": "^9.0.7", "@types/fs-extra": "^9.0.8",
"@types/jest": "^26.0.20", "@types/jest": "^26.0.20",
"@types/loadable__component": "^5.13.3", "@types/loadable__component": "^5.13.3",
"@types/lunr": "^2.3.3", "@types/lunr": "^2.3.3",
"@types/node": "^14.14.28", "@types/node": "^14.14.34",
"@types/node-fetch": "^2.5.8", "@types/node-fetch": "^2.5.8",
"@types/react": "^17.0.2", "@types/react": "^17.0.3",
"@types/react-dom": "^17.0.1", "@types/react-dom": "^17.0.2",
"@types/react-helmet": "^6.1.0", "@types/react-helmet": "^6.1.0",
"@types/react-transition-group": "^4.4.0", "@types/react-transition-group": "^4.4.0",
"@types/shortid": "^0.0.29", "@types/shortid": "^0.0.29",
"@typescript-eslint/eslint-plugin": "^4.15.2", "@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.15.2", "@typescript-eslint/parser": "^4.17.0",
"@welldone-software/why-did-you-render": "^6.0.5", "@welldone-software/why-did-you-render": "^6.1.0",
"eslint": "^7.21.0", "eslint": "^7.22.0",
"eslint-config-prettier": "^8.1.0", "eslint-config-prettier": "^8.1.0",
"eslint-plugin-graphql": "^4.0.0", "eslint-plugin-graphql": "^4.0.0",
"eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-jsx-a11y": "^6.4.1",
@ -110,23 +108,23 @@
"eslint-plugin-react": "^7.22.0", "eslint-plugin-react": "^7.22.0",
"eslint-plugin-testing-library": "^3.10.1", "eslint-plugin-testing-library": "^3.10.1",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.20", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.21",
"identity-obj-proxy": "^3.0.0", "identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3", "jest": "^26.6.3",
"markdownlint-cli": "^0.26.0", "markdownlint-cli": "^0.26.0",
"node-iptc": "^1.0.5", "node-iptc": "^1.0.5",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"ora": "^5.3.0", "ora": "^5.3.0",
"postcss": "^8.2.7", "postcss": "^8.2.8",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"shortid": "^2.2.16", "shortid": "^2.2.16",
"stylelint": "^13.11.0", "stylelint": "^13.12.0",
"stylelint-config-css-modules": "^2.2.0", "stylelint-config-css-modules": "^2.2.0",
"stylelint-config-prettier": "^8.0.2", "stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^20.0.0", "stylelint-config-standard": "^20.0.0",
"stylelint-prettier": "^1.2.0", "stylelint-prettier": "^1.2.0",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.2.2" "typescript": "^4.2.3"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -1,7 +1,7 @@
import React, { ReactElement, useState } from 'react' import React, { ReactElement, useState } from 'react'
import Map from 'pigeon-maps' import Map from 'pigeon-maps'
import Marker from 'pigeon-marker' import Marker from 'pigeon-marker'
import useDarkMode from 'use-dark-mode' import useDarkMode from '../../hooks/useDarkMode'
const mapbox = (mapboxId: string) => ( const mapbox = (mapboxId: string) => (
x: string, x: string,
@ -23,10 +23,7 @@ export default function ExifMap({
}: { }: {
gps: { latitude: string; longitude: string } gps: { latitude: string; longitude: string }
}): ReactElement { }): ReactElement {
const { value } = useDarkMode(false, { const { value } = useDarkMode()
classNameDark: 'dark',
classNameLight: 'light'
})
const isDarkMode = value const isDarkMode = value
const [zoom, setZoom] = useState(12) const [zoom, setZoom] = useState(12)

View File

@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
import { graphql } from 'gatsby' import { graphql } from 'gatsby'
import { GatsbyImage } from 'gatsby-plugin-image' import { GatsbyImage } from 'gatsby-plugin-image'
import { ImageProps } from '../../@types/Image' import { ImageProps } from '../../@types/Image'
import * as styles from './Image.module.css' import { image as styleImage, imageTitle } from './Image.module.css'
export const Image = ({ export const Image = ({
title, title,
@ -12,11 +12,11 @@ export const Image = ({
className className
}: ImageProps): ReactElement => ( }: ImageProps): ReactElement => (
<figure <figure
className={`${styles.image} ${className ? className : ''}`} className={`${styleImage} ${className ? className : ''}`}
data-original={original && original.src} data-original={original?.src}
> >
<GatsbyImage backgroundColor="transparent" image={image} alt={alt} /> <GatsbyImage backgroundColor="transparent" image={image} alt={alt} />
{title && <figcaption className={styles.imageTitle}>{title}</figcaption>} {title && <figcaption className={imageTitle}>{title}</figcaption>}
</figure> </figure>
) )

View File

@ -3,7 +3,11 @@ import { Link, graphql } from 'gatsby'
import { Image } from '../atoms/Image' import { Image } from '../atoms/Image'
import { Post } from '../../@types/Post' import { Post } from '../../@types/Post'
import PostTitle from '../templates/Post/Title' import PostTitle from '../templates/Post/Title'
import * as styles from './PostTeaser.module.css' import {
post as stylePost,
empty,
title as styleTitle
} from './PostTeaser.module.css'
export const postTeaserQuery = graphql` export const postTeaserQuery = graphql`
fragment PostTeaser on MarkdownRemark { fragment PostTeaser on MarkdownRemark {
@ -42,21 +46,24 @@ export default function PostTeaser({
return ( return (
<Link <Link
className={styles.post} className={stylePost}
to={slug} to={slug}
onClick={toggleSearch && toggleSearch} onClick={toggleSearch && toggleSearch}
> >
{image ? ( {image ? (
<Image image={image} alt={title} /> <Image
image={(image as any).childImageSharp.gatsbyImageData}
alt={title}
/>
) : ( ) : (
<span className={styles.empty} /> <span className={empty} />
)} )}
<PostTitle <PostTitle
title={title} title={title}
date={hideDate ? null : date} date={hideDate ? null : date}
updated={updated} updated={updated}
className={styles.title} className={styleTitle}
/> />
</Link> </Link>
) )

View File

@ -1,19 +1,18 @@
import React, { ReactElement } from 'react' import React, { ReactElement, useEffect, useState } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import useDarkMode from 'use-dark-mode' import { themeSwitch, checkbox, label } from './ThemeSwitch.module.css'
import * as styles from './ThemeSwitch.module.css'
import Icon from '../atoms/Icon' import Icon from '../atoms/Icon'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import useDarkMode from '../../hooks/useDarkMode'
const ThemeToggleInput = ({ const ThemeToggleInput = ({
isDark, isDark,
toggleDark toggleDark
}: { }: {
isDark: boolean isDark: boolean
toggleDark(): void toggleDark: () => void
}) => ( }) => (
<input <input
onChange={toggleDark} onChange={() => toggleDark()}
type="checkbox" type="checkbox"
name="toggle" name="toggle"
value="toggle" value="toggle"
@ -22,8 +21,15 @@ const ThemeToggleInput = ({
/> />
) )
const HeadMarkup = ({ themeColor }: { themeColor: string }) => ( const HeadMarkup = ({
bodyClass,
themeColor
}: {
bodyClass: string
themeColor: string
}) => (
<Helmet> <Helmet>
<body className={bodyClass} />
<meta name="theme-color" content={themeColor} /> <meta name="theme-color" content={themeColor} />
<meta <meta
name="apple-mobile-web-app-status-bar-style" name="apple-mobile-web-app-status-bar-style"
@ -33,28 +39,30 @@ const HeadMarkup = ({ themeColor }: { themeColor: string }) => (
) )
export default function ThemeSwitch(): ReactElement { export default function ThemeSwitch(): ReactElement {
const { darkModeConfig } = useSiteMetadata() const { value, toggle } = useDarkMode()
const darkMode = useDarkMode(false, darkModeConfig) const [themeColor, setThemeColor] = useState('')
const themeColor = darkMode.value ? '#1d2224' : '#e7eef4' const [bodyClass, setBodyClass] = useState('')
useEffect(() => {
setBodyClass(value ? 'dark' : null)
setThemeColor(value ? '#1d2224' : '#e7eef4')
}, [value])
return ( return (
<> <>
<HeadMarkup themeColor={themeColor} /> <HeadMarkup themeColor={themeColor} bodyClass={bodyClass} />
<aside className={styles.themeSwitch} title="Toggle Dark Mode"> <aside className={themeSwitch} title="Toggle Dark Mode">
<label <label
htmlFor="toggle" htmlFor="toggle"
className={styles.checkbox} className={checkbox}
onClick={darkMode.toggle} onClick={toggle}
onKeyPress={darkMode.toggle} onKeyPress={toggle}
role="presentation" role="presentation"
> >
<span className={styles.label}>Toggle Dark Mode</span> <span className={label}>Toggle Dark Mode</span>
<ThemeToggleInput <ThemeToggleInput isDark={value} toggleDark={toggle} />
isDark={darkMode.value}
toggleDark={darkMode.toggle}
/>
<div aria-live="assertive"> <div aria-live="assertive">
{darkMode.value ? <Icon name="Sun" /> : <Icon name="Moon" />} {value ? <Icon name="Sun" /> : <Icon name="Moon" />}
</div> </div>
</label> </label>
</aside> </aside>

View File

@ -3,19 +3,19 @@ import { graphql, Link, PageProps } from 'gatsby'
import Page from './Page' import Page from './Page'
import { Post, PageContext } from '../../@types/Post' import { Post, PageContext } from '../../@types/Post'
import { Image } from '../atoms/Image' import { Image } from '../atoms/Image'
import * as styles from './Photos.module.css' import { photo as stylePhoto, photos as stylePhotos } from './Photos.module.css'
import Pagination from '../molecules/Pagination' import Pagination from '../molecules/Pagination'
export const PhotoThumb = ({ photo }: { photo: Post }): ReactElement => { export const PhotoThumb = ({ photo }: { photo: Post }): ReactElement => {
const { title, image } = photo.frontmatter const { title, image } = photo.frontmatter
const { slug } = photo.fields const { slug } = photo.fields
const { fluid } = image.childImageSharp const { gatsbyImageData } = (image as any).childImageSharp
return ( return (
<article className={styles.photo}> <article className={stylePhoto}>
{image && ( {image && (
<Link to={slug}> <Link to={slug}>
<Image title={title} fluid={fluid} alt={title} /> <Image title={title} image={gatsbyImageData} alt={title} />
</Link> </Link>
)} )}
</article> </article>
@ -55,7 +55,7 @@ export default function Photos(props: PhotosPageProps): ReactElement {
post={page} post={page}
pathname={props.location.pathname} pathname={props.location.pathname}
> >
<section className={styles.photos}> <section className={stylePhotos}>
{photos.map(({ node }: { node: Post }) => ( {photos.map(({ node }: { node: Post }) => (
<PhotoThumb key={node.id} photo={node} /> <PhotoThumb key={node.id} photo={node} />
))} ))}

View File

@ -53,7 +53,7 @@ export default function Post({
{image && ( {image && (
<Image <Image
className={styles.image} className={styles.image}
fluid={image.childImageSharp.fluid} image={(image as any).childImageSharp.gatsbyImageData}
alt={title} alt={title}
/> />
)} )}

View File

@ -361,4 +361,5 @@ td {
.gatsby-image-wrapper { .gatsby-image-wrapper {
max-height: 100vh; max-height: 100vh;
display: block;
} }

View File

@ -28,10 +28,6 @@ const query = graphql`
jsonfeed jsonfeed
itemsPerPage itemsPerPage
repoContentPath repoContentPath
darkModeConfig {
classNameDark
classNameLight
}
} }
} }
} }

62
src/hooks/useDarkMode.ts Normal file
View File

@ -0,0 +1,62 @@
//
// adapted from
// https://github.com/daveschumaker/react-dark-mode-hook/blob/master/useDarkMode.js
//
import { useState, useEffect, useCallback } from 'react'
const isClient = typeof window === 'object'
function getDarkMode() {
// if (localStorage.getItem('theme') === 'dark') {
// return true
// } else if (localStorage.getItem('theme') === 'light') {
// return false
// }
if (
isClient &&
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches
) {
return true
} else {
return false
}
}
export default function useDarkMode(): {
value: boolean
toggle?: () => void
} {
const [darkMode, setDarkMode] = useState(getDarkMode)
function toggleDarkMode() {
setDarkMode(!darkMode)
}
//
// Handle system theme change events
//
const handleChange = useCallback(() => {
setDarkMode(getDarkMode())
}, [])
useEffect(() => {
if (!isClient) return
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)')
try {
darkModeQuery.addEventListener('change', handleChange)
} catch (addEventListenerError) {
console.error(addEventListenerError)
}
return () =>
window
.matchMedia('(prefers-color-scheme: dark)')
.removeEventListener('change', handleChange)
}, [handleChange])
return { value: darkMode, toggle: toggleDarkMode }
}

View File

@ -5,21 +5,21 @@ import SEO from '../components/atoms/SEO'
import PostTeaser from '../components/molecules/PostTeaser' import PostTeaser from '../components/molecules/PostTeaser'
import { PhotoThumb } from '../components/templates/Photos' import { PhotoThumb } from '../components/templates/Photos'
import PostMore from '../components/templates/Post/More' import PostMore from '../components/templates/Post/More'
import * as styles from './index.module.css' import { section, articles, articlesLast, photos } from './index.module.css'
export default function Home({ data }: PageProps): ReactElement { export default function Home({ data }: PageProps): ReactElement {
return ( return (
<> <>
<SEO /> <SEO />
<section className={styles.section}> <section className={section}>
<div className={styles.articles}> <div className={articles}>
{(data as any).latestArticles.edges {(data as any).latestArticles.edges
.slice(0, 2) .slice(0, 2)
.map(({ node }: { node: Post }) => ( .map(({ node }: { node: Post }) => (
<PostTeaser key={node.id} post={node} hideDate /> <PostTeaser key={node.id} post={node} hideDate />
))} ))}
</div> </div>
<div className={`${styles.articles} ${styles.articlesLast}`}> <div className={`${articles} ${articlesLast}`}>
{(data as any).latestArticles.edges {(data as any).latestArticles.edges
.slice(2, 8) .slice(2, 8)
.map(({ node }: { node: Post }) => ( .map(({ node }: { node: Post }) => (
@ -30,8 +30,8 @@ export default function Home({ data }: PageProps): ReactElement {
<PostMore to="/archive">All Articles</PostMore> <PostMore to="/archive">All Articles</PostMore>
</section> </section>
<section className={styles.section}> <section className={section}>
<div className={styles.photos}> <div className={photos}>
{(data as any).latestPhotos.edges.map(({ node }: { node: Post }) => ( {(data as any).latestPhotos.edges.map(({ node }: { node: Post }) => (
<PhotoThumb key={node.id} photo={node} /> <PhotoThumb key={node.id} photo={node} />
))} ))}