mirror of
https://github.com/kremalicious/blog.git
synced 2025-02-14 21:10:25 +01:00
refactor
This commit is contained in:
parent
c35e26ea14
commit
273adeecb4
32669
package-lock.json
generated
32669
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -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",
|
||||||
|
@ -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 />
|
||||||
|
@ -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>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.wide {
|
.wide {
|
||||||
|
composes: container;
|
||||||
max-width: none;
|
max-width: none;
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
|
@ -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} />
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
</>
|
</>
|
||||||
|
@ -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>
|
||||||
))}
|
))}
|
||||||
|
@ -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
|
||||||
|
@ -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} />}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
|
@ -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"
|
||||||
>
|
>
|
||||||
|
@ -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'}
|
||||||
|
@ -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 & developer{' '}
|
Blog of designer & developer{' '}
|
||||||
<a className="fn" rel="author" href={uri}>
|
<a className="fn" rel="author" href={uri}>
|
||||||
{name}
|
{name}
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
© 2005–
|
© 2005–
|
||||||
{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>
|
||||||
|
@ -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 />
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
|
@ -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}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
|
@ -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} />}
|
||||||
</>
|
</>
|
||||||
|
@ -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 }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -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">
|
||||||
|
@ -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} />
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
@ -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;
|
||||||
|
@ -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} />}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -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 }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
@ -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) {
|
||||||
|
@ -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/**/*"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user