1
0
mirror of https://github.com/kremalicious/blog.git synced 2025-02-14 21:10:25 +01:00
This commit is contained in:
Matthias Kretschmann 2021-03-14 01:34:04 +01:00
parent c35e26ea14
commit 273adeecb4
Signed by: m
GPG Key ID: 606EEEF3C479A91F
44 changed files with 32751 additions and 248 deletions

32669
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,8 @@
"gatsby-plugin-sharp": "^3.0.1", "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-webpack-size": "^1.0.0", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.21",
"gatsby-plugin-webpack-size": "^2.0.1",
"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",
"gatsby-remark-breaks": "^1.0.0", "gatsby-remark-breaks": "^1.0.0",
@ -99,7 +100,7 @@
"@types/shortid": "^0.0.29", "@types/shortid": "^0.0.29",
"@typescript-eslint/eslint-plugin": "^4.17.0", "@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.17.0", "@typescript-eslint/parser": "^4.17.0",
"@welldone-software/why-did-you-render": "^6.1.0", "@welldone-software/why-did-you-render": "^6.1.1",
"eslint": "^7.22.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",
@ -108,10 +109,9 @@
"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.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.27.1",
"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",
@ -121,10 +121,11 @@
"stylelint": "^13.12.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": "^21.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.3" "typescript": "^4.2.3",
"typescript-plugin-css-modules": "^3.2.0"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
import Typekit from './atoms/Typekit' import Typekit from './atoms/Typekit'
import Header from './organisms/Header' import Header from './organisms/Header'
import Footer from './organisms/Footer' import Footer from './organisms/Footer'
import * as styles from './Layout.module.css' import { document, content } from './Layout.module.css'
// if (process.env.NODE_ENV !== 'production') { // if (process.env.NODE_ENV !== 'production') {
// // eslint-disable-next-line // // eslint-disable-next-line
@ -16,8 +16,8 @@ export default function Layout({ children }: { children: any }): ReactElement {
<Typekit /> <Typekit />
<Header /> <Header />
<main className={styles.document} id="document"> <main className={document} id="document">
<div className={styles.content}>{children}</div> <div className={content}>{children}</div>
</main> </main>
<Footer /> <Footer />

View File

@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import remark from 'remark' import remark from 'remark'
import remarkReact from 'remark-react' import remarkReact from 'remark-react'
import * as styles from './Changelog.module.css' import { title, content, source } from './Changelog.module.css'
import { GitHub, GitHubRepo } from '../../@types/GitHub' import { GitHub, GitHubRepo } from '../../@types/GitHub'
export function PureChangelog({ export function PureChangelog({
@ -30,20 +30,20 @@ export function PureChangelog({
const filePathDisplay = `${owner.login}/${repo}:CHANGELOG.md` const filePathDisplay = `${owner.login}/${repo}:CHANGELOG.md`
return ( return (
<div className={styles.changelog}> <>
<h2 className={styles.title} id="changelog"> <h2 className={title} id="changelog">
Changelog Changelog
</h2> </h2>
<div className={styles.content}> <div className={content}>
{changelogHtml} {changelogHtml}
<p className={styles.source}> <p className={source}>
sourced from{' '} sourced from{' '}
<a href={filePathUrl}> <a href={filePathUrl}>
<code>{filePathDisplay}</code> <code>{filePathDisplay}</code>
</a> </a>
</p> </p>
</div> </div>
</div> </>
) )
} }

View File

@ -6,5 +6,6 @@
} }
.wide { .wide {
composes: container;
max-width: none; max-width: none;
} }

View File

@ -1,12 +1,12 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import loadable from '@loadable/component' import loadable from '@loadable/component'
import * as styles from './Copy.module.css' import { copied, button } from './Copy.module.css'
import Icon from './Icon' import Icon from './Icon'
const Clipboard = loadable(() => import('react-clipboard.js')) const Clipboard = loadable(() => import('react-clipboard.js'))
const onCopySuccess = (e: any) => { const onCopySuccess = (e: any) => {
e.trigger.classList.add(styles.copied) e.trigger.classList.add(copied)
} }
export default function Copy({ text }: { text: string }): ReactElement { export default function Copy({ text }: { text: string }): ReactElement {
@ -15,7 +15,7 @@ export default function Copy({ text }: { text: string }): ReactElement {
data-clipboard-text={text} data-clipboard-text={text}
button-title="Copy to clipboard" button-title="Copy to clipboard"
onSuccess={(e: ClipboardJS.Event) => onCopySuccess(e)} onSuccess={(e: ClipboardJS.Event) => onCopySuccess(e)}
className={styles.button} className={button}
> >
<Icon name="Copy" /> <Icon name="Copy" />
</Clipboard> </Clipboard>

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import ExifMap from './ExifMap' import ExifMap from './ExifMap'
import * as styles from './Exif.module.css' import { exif as styleExif, data, map } from './Exif.module.css'
import { Exif as ExifMeta } from '../../@types/Image' import { Exif as ExifMeta } from '../../@types/Image'
import Icon from './Icon' import Icon from './Icon'
@ -31,8 +31,8 @@ export default function Exif({ exif }: { exif: ExifMeta }): ReactElement {
} = exif.formatted } = exif.formatted
return ( return (
<aside className={styles.exif}> <aside className={styleExif}>
<div className={styles.data}> <div className={data}>
{model && <ExifData title="Camera model" value={model} icon="Camera" />} {model && <ExifData title="Camera model" value={model} icon="Camera" />}
{focalLength && ( {focalLength && (
<ExifData title="Focal length" value={focalLength} icon="Crosshair" /> <ExifData title="Focal length" value={focalLength} icon="Crosshair" />
@ -49,7 +49,7 @@ export default function Exif({ exif }: { exif: ExifMeta }): ReactElement {
{iso && <ExifData title="ISO" value={iso} icon="Maximize" />} {iso && <ExifData title="ISO" value={iso} icon="Maximize" />}
</div> </div>
{gps && gps.latitude && ( {gps && gps.latitude && (
<div className={styles.map}> <div className={map}>
<ExifMap gps={gps} /> <ExifMap gps={gps} />
</div> </div>
)} )}

View File

@ -1,5 +1,5 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import * as styles from './Hamburger.module.css' import { button, hamburger, line } from './Hamburger.module.css'
export default function Hamburger({ export default function Hamburger({
onClick onClick
@ -7,16 +7,11 @@ export default function Hamburger({
onClick(): void onClick(): void
}): ReactElement { }): ReactElement {
return ( return (
<button <button type="button" title="Menu" className={button} onClick={onClick}>
type="button" <span className={hamburger}>
title="Menu" <span className={line} />
className={styles.button} <span className={line} />
onClick={onClick} <span className={line} />
>
<span className={styles.hamburger}>
<span className={styles.line} />
<span className={styles.line} />
<span className={styles.line} />
</span> </span>
</button> </button>
) )

View File

@ -27,7 +27,7 @@ import {
import { ReactComponent as Jsonfeed } from '../../images/jsonfeed.svg' import { ReactComponent as Jsonfeed } from '../../images/jsonfeed.svg'
import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg' import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg'
import { ReactComponent as Stopwatch } from '../../images/stopwatch.svg' import { ReactComponent as Stopwatch } from '../../images/stopwatch.svg'
import * as styles from './Icon.module.css' import { icon } from './Icon.module.css'
const components: any = { const components: any = {
Download: ArrowDownCircle, Download: ArrowDownCircle,
@ -55,12 +55,12 @@ const components: any = {
Crosshair Crosshair
} }
const Icon = ({ name }: { name: string }): ReactElement => { const Icon = ({ name, ...props }: { name: string }): ReactElement => {
const IconMapped = components[name] const IconMapped = components[name]
// const IconFeather = (Feather as any)[name] // const IconFeather = (Feather as any)[name]
if (!IconMapped) return null if (!IconMapped) return null
return <IconMapped className={styles.icon} /> return <IconMapped className={icon} {...props} />
} }
export default Icon export default Icon

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import * as styles from './Input.module.css' import { input } from './Input.module.css'
export default function Input({ className, ...props }: any): ReactElement { export default function Input({ className, ...props }: any): ReactElement {
return <input className={`${styles.input} ${className || ''}`} {...props} /> return <input className={`${input} ${className || ''}`} {...props} />
} }

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { QRCode } from 'react-qr-svg' import { QRCode } from 'react-qr-svg'
import * as styles from './Qr.module.css' import { qr, code } from './Qr.module.css'
import Copy from './Copy' import Copy from './Copy'
export default function Qr({ export default function Qr({
@ -19,10 +19,10 @@ export default function Qr({
level="Q" level="Q"
style={{ width: 120 }} style={{ width: 120 }}
value={address} value={address}
className={styles.qr} className={qr}
/> />
<pre className={styles.code}> <pre className={code}>
<code>{address}</code> <code>{address}</code>
<Copy text={address} /> <Copy text={address} />
</pre> </pre>

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import * as styles from './Tag.module.css' import { tag, count as styleCount } from './Tag.module.css'
export default function Tag({ export default function Tag({
name, name,
@ -14,9 +14,9 @@ export default function Tag({
style?: any style?: any
}): ReactElement { }): ReactElement {
return ( return (
<Link className={styles.tag} to={url} style={style}> <Link className={tag} to={url} style={style}>
{name} {name}
{count && <span className={styles.count}>{count}</span>} {count && <span className={styleCount}>{count}</span>}
</Link> </Link>
) )
} }

View File

@ -2,7 +2,7 @@ import React, { ReactElement, useState } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import Hamburger from '../atoms/Hamburger' import Hamburger from '../atoms/Hamburger'
import * as styles from './Menu.module.css' import { menu as styleMenu } from './Menu.module.css'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import { useSiteMetadata } from '../../hooks/use-site-metadata'
import { MenuItem } from '../../@types/Site' import { MenuItem } from '../../@types/Site'
@ -28,7 +28,7 @@ export default function Menu(): ReactElement {
<html className={menuOpen ? 'has-menu-open' : undefined} lang="en" /> <html className={menuOpen ? 'has-menu-open' : undefined} lang="en" />
</Helmet> </Helmet>
<Hamburger onClick={toggleMenu} /> <Hamburger onClick={toggleMenu} />
<nav className={styles.menu}> <nav className={styleMenu}>
<ul>{MenuItems}</ul> <ul>{MenuItems}</ul>
</nav> </nav>
</> </>

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Icon from '../atoms/Icon' import Icon from '../atoms/Icon'
import * as styles from './Networks.module.css' import { link as styleLink } from './Networks.module.css'
function NetworkIcon({ link }: { link: string }) { function NetworkIcon({ link }: { link: string }) {
let IconComp let IconComp
@ -28,7 +28,7 @@ export default function IconLinks({
return ( return (
<p> <p>
{links.map((link: string) => ( {links.map((link: string) => (
<a key={link} className={styles.link} href={link} title={link}> <a key={link} className={styleLink} href={link} title={link}>
<NetworkIcon link={link} /> <NetworkIcon link={link} />
</a> </a>
))} ))}

View File

@ -1,9 +1,13 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import * as styles from './Pagination.module.css'
import shortid from 'shortid' import shortid from 'shortid'
import { PageContext } from '../../@types/Post' import { PageContext } from '../../@types/Post'
import Icon from '../atoms/Icon' import Icon from '../atoms/Icon'
import {
current as styleCurrent,
number,
pagination
} from './Pagination.module.css'
const PageNumber = ({ const PageNumber = ({
i, i,
@ -14,7 +18,7 @@ const PageNumber = ({
slug: string slug: string
current?: boolean current?: boolean
}) => { }) => {
const classes = current ? styles.current : styles.number const classes = current ? styleCurrent : number
const link = i === 0 ? slug : `${slug}page/${i + 1}` const link = i === 0 ? slug : `${slug}page/${i + 1}`
return ( return (
@ -62,7 +66,7 @@ export default function Pagination({
const isLast = currentPageNumber === numPages const isLast = currentPageNumber === numPages
return ( return (
<div className={styles.pagination}> <div className={pagination}>
{!isFirst && <PrevNext prevPagePath={prevPagePath} />} {!isFirst && <PrevNext prevPagePath={prevPagePath} />}
{Array.from({ length: numPages }, (_, i) => ( {Array.from({ length: numPages }, (_, i) => (
<PageNumber <PageNumber

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Time from '../atoms/Time' import Time from '../atoms/Time'
import * as styles from './PostDate.module.css' import { time } from './PostDate.module.css'
export default function PostDate({ export default function PostDate({
date, date,
@ -10,7 +10,7 @@ export default function PostDate({
updated?: string updated?: string
}): ReactElement { }): ReactElement {
return ( return (
<div className={styles.time}> <div className={time}>
<Time date={date} /> <Time date={date} />
{updated && ' • updated '} {updated && ' • updated '}
{updated && <Time date={updated} />} {updated && <Time date={updated} />}

View File

@ -1,7 +1,7 @@
import React, { ReactElement, useState } from 'react' import React, { ReactElement, useState } from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import PostTeaser from './PostTeaser' import PostTeaser from './PostTeaser'
import * as styles from './RelatedPosts.module.css' import { relatedPosts, title, button } from './RelatedPosts.module.css'
import { Post, Frontmatter } from '../../@types/Post' import { Post, Frontmatter } from '../../@types/Post'
import { PhotoThumb } from '../templates/Photos' import { PhotoThumb } from '../templates/Photos'
@ -78,10 +78,10 @@ export default function RelatedPosts({
} }
return ( return (
<aside className={styles.relatedPosts}> <aside className={relatedPosts}>
<h1 className={styles.title}> <h1 className={title}>
Related {isPhotos ? 'Photos' : 'Posts'}{' '} Related {isPhotos ? 'Photos' : 'Posts'}{' '}
<button className={styles.button} onClick={() => refreshPosts()}> <button className={button} onClick={() => refreshPosts()}>
Refresh Refresh
</button> </button>
</h1> </h1>

View File

@ -1,14 +1,9 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import * as styles from './SearchButton.module.css' import { searchButton } from './SearchButton.module.css'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
const SearchButton = (props: any): ReactElement => ( const SearchButton = (props: any): ReactElement => (
<button <button type="button" title="Search" className={searchButton} {...props}>
type="button"
title="Search"
className={styles.searchButton}
{...props}
>
<Icon name="Search" /> <Icon name="Search" />
</button> </button>
) )

View File

@ -1,7 +1,7 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Input from '../../atoms/Input' import Input from '../../atoms/Input'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
import * as styles from './SearchInput.module.css' import { searchInput, searchInputClose } from './SearchInput.module.css'
export default function SearchInput({ export default function SearchInput({
value, value,
@ -15,7 +15,7 @@ export default function SearchInput({
return ( return (
<> <>
<Input <Input
className={styles.searchInput} className={searchInput}
type="search" type="search"
placeholder="Search everything" placeholder="Search everything"
autoFocus // eslint-disable-line autoFocus // eslint-disable-line
@ -23,7 +23,7 @@ export default function SearchInput({
onChange={onChange} onChange={onChange}
/> />
<button <button
className={styles.searchInputClose} className={searchInputClose}
onClick={onToggle} onClick={onToggle}
title="Close search" title="Close search"
> >

View File

@ -1,5 +1,9 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import * as styles from './SearchResultsEmpty.module.css' import {
empty,
emptyMessage,
emptyMessageText
} from './SearchResultsEmpty.module.css'
import { Results } from './SearchResults' import { Results } from './SearchResults'
const SearchResultsEmpty = ({ const SearchResultsEmpty = ({
@ -9,9 +13,9 @@ const SearchResultsEmpty = ({
searchQuery: string searchQuery: string
results: Results[] results: Results[]
}): ReactElement => ( }): ReactElement => (
<div className={styles.empty}> <div className={empty}>
<header className={styles.emptyMessage}> <header className={emptyMessage}>
<p className={styles.emptyMessageText}> <p className={emptyMessageText}>
{searchQuery.length > 0 && results.length === 0 {searchQuery.length > 0 && results.length === 0
? 'No results found' ? 'No results found'
: 'Awaiting your input'} : 'Awaiting your input'}

View File

@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import { getSrc } from 'gatsby-plugin-image' import { getSrc } from 'gatsby-plugin-image'
import IconLinks from './Networks' import IconLinks from './Networks'
import * as styles from './Vcard.module.css' import { avatar as styleAvatar, description } from './Vcard.module.css'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import { useSiteMetadata } from '../../hooks/use-site-metadata'
const query = graphql` const query = graphql`
@ -34,13 +34,13 @@ export default function Vcard(): ReactElement {
return ( return (
<> <>
<img <img
className={styles.avatar} className={styleAvatar}
src={avatar} src={avatar}
width="80" width="80"
height="80" height="80"
alt="avatar" alt="avatar"
/> />
<p className={styles.description}> <p className={description}>
Blog of designer &amp; developer{' '} Blog of designer &amp; developer{' '}
<a className="fn" rel="author" href={uri}> <a className="fn" rel="author" href={uri}>
{name} {name}

View File

@ -2,7 +2,11 @@ import React, { ReactElement, useState, useEffect } from 'react'
import { toDataUrl } from 'ethereum-blockies' import { toDataUrl } from 'ethereum-blockies'
import { formatEther } from '@ethersproject/units' import { formatEther } from '@ethersproject/units'
import useWeb3 from '../../../hooks/use-web3' import useWeb3 from '../../../hooks/use-web3'
import * as styles from './Account.module.css' import {
accountWrap,
blockies as styleBlockies,
balance
} from './Account.module.css'
export default function Account(): ReactElement { export default function Account(): ReactElement {
const { library, account } = useWeb3() const { library, account } = useWeb3()
@ -26,12 +30,12 @@ export default function Account(): ReactElement {
ethBalance && `Ξ${parseFloat(formatEther(ethBalance)).toPrecision(4)}` ethBalance && `Ξ${parseFloat(formatEther(ethBalance)).toPrecision(4)}`
return ( return (
<div className={styles.accountWrap} title={account}> <div className={accountWrap} title={account}>
<span className={styles.account}> <span>
<img className={styles.blockies} src={blockies} alt="Blockies" /> <img className={styleBlockies} src={blockies} alt="Blockies" />
{accountDisplay} {accountDisplay}
</span> </span>
<span className={styles.balance}>{balanceDisplay}</span> <span className={balance}>{balanceDisplay}</span>
</div> </div>
) )
} }

View File

@ -1,5 +1,5 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import * as styles from './Alert.module.css' import { success, error, alert } from './Alert.module.css'
export function getTransactionMessage( export function getTransactionMessage(
transactionHash?: string transactionHash?: string
@ -24,11 +24,7 @@ const constructMessage = (
: message && message.text : message && message.text
const classes = (status: string) => const classes = (status: string) =>
status === 'success' status === 'success' ? success : status === 'error' ? error : alert
? styles.success
: status === 'error'
? styles.error
: styles.alert
export default function Alert({ export default function Alert({
transactionHash, transactionHash,

View File

@ -1,6 +1,6 @@
import React, { useState, useEffect, ReactElement } from 'react' import React, { useState, useEffect, ReactElement } from 'react'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import * as styles from './Conversion.module.css' import { conversion as styleConversion } from './Conversion.module.css'
export async function getFiat( export async function getFiat(
amount: number amount: number
@ -43,7 +43,7 @@ export default function Conversion({
}, [amount]) }, [amount])
return ( return (
<div className={styles.conversion}> <div className={styleConversion}>
<span>{dollar !== '0.00' && `= $ ${dollar}`}</span> <span>{dollar !== '0.00' && `= $ ${dollar}`}</span>
<span>{euro !== '0.00' && `= € ${euro}`}</span> <span>{euro !== '0.00' && `= € ${euro}`}</span>
</div> </div>

View File

@ -2,7 +2,7 @@ import React, { ReactElement, useState } from 'react'
import Input from '../../atoms/Input' import Input from '../../atoms/Input'
import Account from './Account' import Account from './Account'
import Conversion from './Conversion' import Conversion from './Conversion'
import * as styles from './InputGroup.module.css' import { inputGroup, input, currency } from './InputGroup.module.css'
export default function InputGroup({ export default function InputGroup({
sendTransaction sendTransaction
@ -18,8 +18,8 @@ export default function InputGroup({
return ( return (
<div> <div>
<Account /> <Account />
<div className={styles.inputGroup}> <div className={inputGroup}>
<div className={styles.input}> <div className={input}>
<Input <Input
type="number" type="number"
value={amount} value={amount}
@ -27,7 +27,7 @@ export default function InputGroup({
min="0" min="0"
step="0.01" step="0.01"
/> />
<div className={styles.currency}> <div className={currency}>
<span>ETH</span> <span>ETH</span>
</div> </div>
</div> </div>

View File

@ -3,7 +3,7 @@ import { parseEther } from '@ethersproject/units'
import useWeb3, { connectors, getErrorMessage } from '../../../hooks/use-web3' import useWeb3, { connectors, getErrorMessage } from '../../../hooks/use-web3'
import InputGroup from './InputGroup' import InputGroup from './InputGroup'
import Alert, { getTransactionMessage } from './Alert' import Alert, { getTransactionMessage } from './Alert'
import * as styles from './index.module.css' import { web3 } from './index.module.css'
export default function Web3Donation({ export default function Web3Donation({
address address
@ -67,7 +67,7 @@ export default function Web3Donation({
} }
return ( return (
<div className={styles.web3}> <div className={web3}>
{!active && !message ? ( {!active && !message ? (
<button className="link" onClick={() => activate(connectors.MetaMask)}> <button className="link" onClick={() => activate(connectors.MetaMask)}>
Activate Web3 Activate Web3

View File

@ -3,14 +3,14 @@ import { Link } from 'gatsby'
import Icon from '../atoms/Icon' import Icon from '../atoms/Icon'
import Vcard from '../molecules/Vcard' import Vcard from '../molecules/Vcard'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import { useSiteMetadata } from '../../hooks/use-site-metadata'
import * as styles from './Footer.module.css' import { copyright, btc, footer } from './Footer.module.css'
function Copyright() { function Copyright() {
const { name, uri, github } = useSiteMetadata().author const { name, uri, github } = useSiteMetadata().author
const year = new Date().getFullYear() const year = new Date().getFullYear()
return ( return (
<section className={styles.copyright}> <section className={copyright}>
<p> <p>
&copy; 2005&ndash; &copy; 2005&ndash;
{year + ' '} {year + ' '}
@ -21,7 +21,7 @@ function Copyright() {
<Icon name="GitHub" /> <Icon name="GitHub" />
View source View source
</a> </a>
<Link to="/thanks" className={styles.btc}> <Link to="/thanks" className={btc}>
<Icon name="Bitcoin" /> <Icon name="Bitcoin" />
Say Thanks Say Thanks
</Link> </Link>
@ -33,7 +33,7 @@ function Copyright() {
export default class Footer extends PureComponent { export default class Footer extends PureComponent {
render(): ReactElement { render(): ReactElement {
return ( return (
<footer role="contentinfo" className={styles.footer}> <footer role="contentinfo" className={footer}>
<Vcard /> <Vcard />
<Copyright /> <Copyright />
</footer> </footer>

View File

@ -4,20 +4,20 @@ import Search from '../molecules/Search'
import Menu from '../molecules/Menu' import Menu from '../molecules/Menu'
import ThemeSwitch from '../molecules/ThemeSwitch' import ThemeSwitch from '../molecules/ThemeSwitch'
import { ReactComponent as Logo } from '../../images/logo.svg' import { ReactComponent as Logo } from '../../images/logo.svg'
import * as styles from './Header.module.css' import { header, headerContent, title, logo, nav } from './Header.module.css'
export default class Header extends PureComponent { export default class Header extends PureComponent {
render(): ReactElement { render(): ReactElement {
return ( return (
<header role="banner" className={styles.header}> <header role="banner" className={header}>
<div className={styles.headerContent}> <div className={headerContent}>
<h1 className={styles.title}> <h1 className={title}>
<Link to="/"> <Link to="/">
<Logo className={styles.logo} /> kremalicious <Logo className={logo} /> kremalicious
</Link> </Link>
</h1> </h1>
<nav role="navigation" className={styles.nav}> <nav role="navigation" className={nav}>
<ThemeSwitch /> <ThemeSwitch />
<Search /> <Search />
<Menu /> <Menu />

View File

@ -2,9 +2,9 @@ import React, { ReactElement } from 'react'
import { graphql } from 'gatsby' import { graphql } from 'gatsby'
import { Post, PageContext } from '../../@types/Post' import { Post, PageContext } from '../../@types/Post'
import Pagination from '../molecules/Pagination' import Pagination from '../molecules/Pagination'
import * as styles from './Archive.module.css'
import PostTeaser from '../molecules/PostTeaser' import PostTeaser from '../molecules/PostTeaser'
import Page from './Page' import Page from './Page'
import { posts } from './Archive.module.css'
export default function Archive({ export default function Archive({
data, data,
@ -40,7 +40,7 @@ export default function Archive({
post={page} post={page}
pathname={pageContext.slug} pathname={pageContext.slug}
> >
<div className={styles.posts}>{PostsList}</div> <div className={posts}>{PostsList}</div>
{numPages > 1 && <Pagination pageContext={pageContext} />} {numPages > 1 && <Pagination pageContext={pageContext} />}
</Page> </Page>
) )

View File

@ -2,7 +2,7 @@ import React, { ReactElement, ReactNode } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { Post } from '../../@types/Post' import { Post } from '../../@types/Post'
import SEO from '../atoms/SEO' import SEO from '../atoms/SEO'
import * as styles from './Page.module.css' import { pagetitle } from './Page.module.css'
export default function Page({ export default function Page({
title, title,
@ -22,7 +22,7 @@ export default function Page({
<Helmet title={title} /> <Helmet title={title} />
<SEO slug={pathname} postSEO post={post} /> <SEO slug={pathname} postSEO post={post} />
<h1 className={styles.pagetitle}>{title}</h1> <h1 className={pagetitle}>{title}</h1>
{section ? <section className={section}>{children}</section> : children} {section ? <section className={section}>{children}</section> : children}
</> </>
) )

View File

@ -1,10 +1,10 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { graphql, Link, PageProps } from 'gatsby' import { graphql, Link, PageProps } from 'gatsby'
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 { photo as stylePhoto, photos as stylePhotos } from './Photos.module.css'
import Pagination from '../molecules/Pagination' import Pagination from '../molecules/Pagination'
import Page from './Page'
import { photo as stylePhoto, photos as stylePhotos } from './Photos.module.css'
export const PhotoThumb = ({ photo }: { photo: Post }): ReactElement => { export const PhotoThumb = ({ photo }: { photo: Post }): ReactElement => {
const { title, image } = photo.frontmatter const { title, image } = photo.frontmatter

View File

@ -1,30 +1,22 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { useSiteMetadata } from '../../../hooks/use-site-metadata' import { useSiteMetadata } from '../../../hooks/use-site-metadata'
import * as styles from './Actions.module.css' import { action, actionTitle, actionText, actions } from './Actions.module.css'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
interface ActionProps { interface ActionProps {
title: string title: string
text: string text: string
icon: string
url?: string url?: string
onClick?(): void onClick?(): void
} }
const IconComp = ({ text }: { text: string }) => const Action = ({ title, text, url, icon, onClick }: ActionProps) => {
text.includes('GitHub') ? (
<Icon name="GitHub" />
) : text.includes('Bitcoin') ? (
<Icon name="Bitcoin" />
) : (
<Icon name="Twitter" />
)
const Action = ({ title, text, url, onClick }: ActionProps) => {
return ( return (
<a className={styles.action} href={url} onClick={onClick}> <a className={action} href={url} onClick={onClick}>
<IconComp text={text} /> <Icon name={icon} />
<h1 className={styles.actionTitle}>{title}</h1> <h1 className={actionTitle}>{title}</h1>
<p className={styles.actionText}>{text}</p> <p className={actionText}>{text}</p>
</a> </a>
) )
} }
@ -40,21 +32,24 @@ export default function PostActions({
const urlTwitter = `https://twitter.com/intent/tweet?text=@kremalicious&url=${siteUrl}${slug}` const urlTwitter = `https://twitter.com/intent/tweet?text=@kremalicious&url=${siteUrl}${slug}`
return ( return (
<aside className={styles.actions}> <aside className={actions}>
<Action <Action
title="Have a comment?" title="Have a comment?"
text="Hit me up @kremalicious" text="Hit me up @kremalicious"
url={urlTwitter} url={urlTwitter}
icon="Twitter"
/> />
<Action <Action
title="Found something useful?" title="Found something useful?"
text="Say thanks with BTC or ETH" text="Say thanks with BTC or ETH"
url="/thanks" url="/thanks"
icon="Bitcoin"
/> />
<Action <Action
title="Edit on GitHub" title="Edit on GitHub"
text="Contribute to this post" text="Contribute to this post"
url={githubLink} url={githubLink}
icon="GitHub"
/> />
</aside> </aside>
) )

View File

@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
import Changelog from '../../atoms/Changelog' import Changelog from '../../atoms/Changelog'
import { Post } from '../../../@types/Post' import { Post } from '../../../@types/Post'
import PostToc from './Toc' import PostToc from './Toc'
import * as styles from './Content.module.css' import { content as styleContent } from './Content.module.css'
export default function PostContent({ post }: { post: Post }): ReactElement { export default function PostContent({ post }: { post: Post }): ReactElement {
const separator = '<!-- more -->' const separator = '<!-- more -->'
@ -27,7 +27,7 @@ export default function PostContent({ post }: { post: Post }): ReactElement {
)} )}
<div <div
dangerouslySetInnerHTML={{ __html: content }} dangerouslySetInnerHTML={{ __html: content }}
className={styles.content} className={styleContent}
/> />
{changelog && <Changelog repo={changelog} />} {changelog && <Changelog repo={changelog} />}
</> </>

View File

@ -1,5 +1,5 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import * as styles from './Lead.module.css' import { lead as styleLead } from './Lead.module.css'
import { Post } from '../../../@types/Post' import { Post } from '../../../@types/Post'
// Extract lead paragraph from content // Extract lead paragraph from content
@ -23,7 +23,7 @@ const PostLead = ({
return ( return (
<div <div
className={`${styles.lead} ${className && className}`} className={`${styleLead} ${className && className}`}
dangerouslySetInnerHTML={{ __html: lead }} dangerouslySetInnerHTML={{ __html: lead }}
/> />
) )

View File

@ -1,7 +1,7 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import stylesPostMore from './More.module.css' import { postMore } from './More.module.css'
import * as styles from './LinkActions.module.css' import { postLinkActions } from './LinkActions.module.css'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
const PostLinkActions = ({ const PostLinkActions = ({
@ -11,8 +11,8 @@ const PostLinkActions = ({
linkurl?: string linkurl?: string
slug: string slug: string
}): ReactElement => ( }): ReactElement => (
<aside className={styles.postLinkActions}> <aside className={postLinkActions}>
<a className={stylesPostMore.postMore} href={linkurl}> <a className={postMore} href={linkurl}>
Go to source <Icon name="ExternalLink" /> Go to source <Icon name="ExternalLink" />
</a> </a>
<Link to={slug} rel="tooltip" title="Permalink"> <Link to={slug} rel="tooltip" title="Permalink">

View File

@ -3,7 +3,13 @@ import { Link } from 'gatsby'
import slugify from 'slugify' import slugify from 'slugify'
import Tag from '../../atoms/Tag' import Tag from '../../atoms/Tag'
import { useSiteMetadata } from '../../../hooks/use-site-metadata' import { useSiteMetadata } from '../../../hooks/use-site-metadata'
import * as styles from './Meta.module.css' import {
entryMeta,
byline,
by,
type as styleType,
tags as styleTags
} from './Meta.module.css'
import { Post } from '../../../@types/Post' import { Post } from '../../../@types/Post'
import shortid from 'shortid' import shortid from 'shortid'
import PostDate from '../../molecules/PostDate' import PostDate from '../../molecules/PostDate'
@ -14,9 +20,9 @@ export default function PostMeta({ post }: { post: Post }): ReactElement {
const { date, type } = post.fields const { date, type } = post.fields
return ( return (
<footer className={styles.entryMeta}> <footer className={entryMeta}>
<div className={styles.byline}> <div className={byline}>
<span className={styles.by}>by</span> <span className={by}>by</span>
<a className="fn" rel="author" href={siteMeta.author.uri}> <a className="fn" rel="author" href={siteMeta.author.uri}>
{author || siteMeta.author.name} {author || siteMeta.author.name}
</a> </a>
@ -25,13 +31,13 @@ export default function PostMeta({ post }: { post: Post }): ReactElement {
<PostDate date={date} updated={updated} /> <PostDate date={date} updated={updated} />
{type && type === 'photo' && ( {type && type === 'photo' && (
<div className={styles.type}> <div className={styleType}>
<Link to={`/${slugify(type)}s/`}>{type}s</Link> <Link to={`/${slugify(type)}s/`}>{type}s</Link>
</div> </div>
)} )}
{tags && ( {tags && (
<div className={styles.tags}> <div className={styleTags}>
{tags.map((tag: string) => { {tags.map((tag: string) => {
const url = `/archive/${slugify(tag)}/` const url = `/archive/${slugify(tag)}/`
return <Tag key={shortid.generate()} name={tag} url={url} /> return <Tag key={shortid.generate()} name={tag} url={url} />

View File

@ -1,7 +1,7 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
import * as styles from './More.module.css' import { postMore } from './More.module.css'
const PostMore = ({ const PostMore = ({
to, to,
@ -10,7 +10,7 @@ const PostMore = ({
to: string to: string
children: string children: string
}): ReactElement => ( }): ReactElement => (
<Link className={styles.postMore} to={to}> <Link className={postMore} to={to}>
{children} {children}
<Icon name="ChevronRight" /> <Icon name="ChevronRight" />
</Link> </Link>

View File

@ -1,7 +1,7 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
import * as styles from './PrevNext.module.css' import { prevnext, label, title } from './PrevNext.module.css'
interface Node { interface Node {
title: string title: string
@ -14,21 +14,21 @@ interface PrevNextProps {
} }
const PrevNext = ({ prev, next }: PrevNextProps): ReactElement => ( const PrevNext = ({ prev, next }: PrevNextProps): ReactElement => (
<nav className={styles.prevnext}> <nav className={prevnext}>
<div> <div>
{prev && ( {prev && (
<Link to={prev.slug}> <Link to={prev.slug}>
<Icon name="ChevronLeft" /> <Icon name="ChevronLeft" />
<p className={styles.label}>Newer</p> <p className={label}>Newer</p>
<h3 className={styles.title}>{prev.title}</h3> <h3 className={title}>{prev.title}</h3>
</Link> </Link>
)} )}
</div> </div>
<div> <div>
{next && ( {next && (
<Link to={next.slug}> <Link to={next.slug}>
<p className={styles.label}>Older</p> <p className={label}>Older</p>
<h3 className={styles.title}>{next.title}</h3> <h3 className={title}>{next.title}</h3>
<Icon name="ChevronRight" /> <Icon name="ChevronRight" />
</Link> </Link>
)} )}

View File

@ -3,11 +3,11 @@
margin-bottom: calc(var(--spacer) / 8); margin-bottom: calc(var(--spacer) / 8);
} }
.title__link { .titleLink {
font-size: var(--font-size-h3); font-size: var(--font-size-h3);
} }
.title__link svg { .titleLink svg {
width: var(--font-size-base); width: var(--font-size-base);
height: var(--font-size-base); height: var(--font-size-base);
display: inline-block; display: inline-block;

View File

@ -1,5 +1,9 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import * as styles from './Title.module.css' import {
title as styleTitle,
titleLink,
linkurl as styleLinkurl
} from './Title.module.css'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
import PostDate from '../../molecules/PostDate' import PostDate from '../../molecules/PostDate'
@ -20,20 +24,16 @@ export default function PostTitle({
return linkurl ? ( return linkurl ? (
<> <>
<h1 <h1 className={`${styleTitle} ${titleLink} ${className && className}`}>
className={`${styles.title} ${styles.title__link} ${
className && className
}`}
>
<a href={linkurl} title={`Go to source: ${linkurl}`}> <a href={linkurl} title={`Go to source: ${linkurl}`}>
{title} <Icon name="ExternalLink" /> {title} <Icon name="ExternalLink" />
</a> </a>
</h1> </h1>
<div className={styles.linkurl}>{linkHostname}</div> <div className={styleLinkurl}>{linkHostname}</div>
</> </>
) : ( ) : (
<> <>
<h1 className={`${styles.title} ${className && className}`}>{title}</h1> <h1 className={`${styleTitle} ${className && className}`}>{title}</h1>
{date && <PostDate date={date} updated={updated} />} {date && <PostDate date={date} updated={updated} />}
</> </>
) )

View File

@ -1,5 +1,5 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import * as styles from './Toc.module.css' import { toc } from './Toc.module.css'
const PostToc = ({ const PostToc = ({
tableOfContents tableOfContents
@ -8,7 +8,7 @@ const PostToc = ({
}): ReactElement => { }): ReactElement => {
return ( return (
<nav <nav
className={styles.toc} className={toc}
dangerouslySetInnerHTML={{ __html: tableOfContents }} dangerouslySetInnerHTML={{ __html: tableOfContents }}
/> />
) )

View File

@ -12,7 +12,7 @@ import PostActions from './Actions'
import PostLinkActions from './LinkActions' import PostLinkActions from './LinkActions'
import PostMeta from './Meta' import PostMeta from './Meta'
import PrevNext from './PrevNext' import PrevNext from './PrevNext'
import * as styles from './index.module.css' import { hentry, image as styleImage } from './index.module.css'
import { Image } from '../../atoms/Image' import { Image } from '../../atoms/Image'
export default function Post({ export default function Post({
@ -37,7 +37,7 @@ export default function Post({
<SEO slug={slug} post={post} postSEO /> <SEO slug={slug} post={post} postSEO />
<article className={styles.hentry}> <article className={hentry}>
<header> <header>
<PostTitle <PostTitle
linkurl={linkurl} linkurl={linkurl}
@ -52,7 +52,7 @@ export default function Post({
{image && ( {image && (
<Image <Image
className={styles.image} className={styleImage}
image={(image as any).childImageSharp.gatsbyImageData} image={(image as any).childImageSharp.gatsbyImageData}
alt={title} alt={title}
/> />

View File

@ -1,5 +1,5 @@
.section { .section {
composes: container.wide from '../components/atoms/Container.module.css'; composes: wide from '../components/atoms/Container.module.css';
} }
.section:not(:first-child) { .section:not(:first-child) {

View File

@ -10,7 +10,8 @@
"esModuleInterop": true, "esModuleInterop": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"sourceMap": true, "sourceMap": true,
"noImplicitAny": true "noImplicitAny": true,
"plugins": [{ "name": "typescript-plugin-css-modules" }]
}, },
"exclude": ["node_modules", "public", ".cache", "*.js"], "exclude": ["node_modules", "public", ".cache", "*.js"],
"include": ["./src/**/*", "./scripts/*.ts", "./jest/**/*"] "include": ["./src/**/*", "./scripts/*.ts", "./jest/**/*"]