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

more typings

This commit is contained in:
Matthias Kretschmann 2019-10-16 01:45:30 +02:00
parent 74af0c2dc9
commit 9197962a77
Signed by: m
GPG Key ID: 606EEEF3C479A91F
26 changed files with 276 additions and 177 deletions

View File

@ -6,7 +6,9 @@
"sourceType": "module"
},
"env": { "browser": true, "node": true, "es6": true, "jest": true },
"settings": { "react": { "version": "detect" } },
"settings": {
"react": { "version": "detect" }
},
"overrides": [
{
"files": ["**/*.ts", "**/*.tsx"],

25
src/@types/GitHub.d.ts vendored Normal file
View File

@ -0,0 +1,25 @@
export interface GitHubRepo {
name: string
url: string
owner: {
login: string
}
object: {
id: string
text: string
}
}
export interface GitHub {
github: {
viewer: {
repositories: {
edges: [
{
node: GitHubRepo
}
]
}
}
}
}

53
src/@types/PostMetadata.d.ts vendored Normal file
View File

@ -0,0 +1,53 @@
import { FluidObject } from 'gatsby-image'
export interface PostMetadataFields {
slug: string
date: string
githubLink: string
}
export interface PostMetadataImageExif {
iso: string
model: string
fstop: string
shutterspeed: string
focalLength: string
lensModel: string
exposure: string
gps: {
latitude: string
longitude: string
}
}
export interface PostMetadataImage {
childImageSharp: { fluid: FluidObject }
fields: {
exif: PostMetadataImageExif
}
}
export interface PostMetadataFrontmatter {
type?: string
title: string
description?: string
image?: PostMetadataImage
author?: string
updated?: string
tags?: string[]
linkurl?: string
style?: {
publicURL?: string
}
changelog?: string
}
export interface PostMetadata {
id?: string
html?: string
excerpt?: string
frontmatter: PostMetadataFrontmatter
fields?: PostMetadataFields
rawMarkdownBody?: string
fileAbsolutePath?: string
}

29
src/@types/SiteMetadata.d.ts vendored Normal file
View File

@ -0,0 +1,29 @@
export interface MenuItem {
title: string
link: string
}
export interface Author {
name: string
email: string
uri: string
twitter: string
github: string
facebook: string
bitcoin: string
ether: string
}
export interface SiteMetadata {
siteTitle: string
siteTitleShort: string
siteDescription: string
siteUrl: string
author: Author
typekitID: string
menu: MenuItem[]
rss: string
jsonfeed: string
itemsPerPage: number
repoContentPath: string
}

View File

@ -16,3 +16,14 @@ declare module '*.svg' {
const src: string
export default src
}
interface Window {
__LUNR__: {
readonly [language: string]: {
readonly index: lunr.Index
readonly store: {
readonly [key: string]: any
}
}
}
}

View File

@ -1,8 +1,9 @@
import React from 'react'
import Changelog from '../atoms/Changelog'
import { PostMetadata } from '../../@types/PostMetadata'
// Remove lead paragraph from content
const PostContent = ({ post }: { post: any }) => {
const PostContent = ({ post }: { post: PostMetadata }) => {
const separator = '<!-- more -->'
const changelog = post.frontmatter.changelog

View File

@ -1,15 +1,10 @@
import React from 'react'
import styles from './PostLead.module.scss'
import { PostMetadata } from '../../@types/PostMetadata'
// Extract lead paragraph from content
// Grab everything before more tag, or just first paragraph
const PostLead = ({
post,
index
}: {
post: { html: string }
index?: boolean
}) => {
const PostLead = ({ post, index }: { post: PostMetadata; index?: boolean }) => {
let lead
const content = post.html
const separator = '<!-- more -->'

View File

@ -4,8 +4,9 @@ import slugify from 'slugify'
import Time from '../atoms/Time'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
import styles from './PostMeta.module.scss'
import { PostMetadata } from '../../@types/PostMetadata'
export default function PostMeta({ post }: { post: any }) {
export default function PostMeta({ post }: { post: PostMetadata }) {
const siteMeta = useSiteMetadata()
const { author, updated, tags, type } = post.frontmatter
const { date } = post.fields

View File

@ -2,12 +2,13 @@ import React from 'react'
import { Link } from 'gatsby'
import Image from '../atoms/Image'
import styles from './PostTeaser.module.scss'
import { PostMetadata } from '../../@types/PostMetadata'
export default function PostTeaser({
post,
toggleSearch
}: {
post: { fields: { slug: string }; frontmatter: { image: any; title: string } }
post: PostMetadata
toggleSearch?: () => void
}) {
const { image, title } = post.frontmatter

View File

@ -5,7 +5,11 @@ import Container from '../atoms/Container'
import PostTeaser from '../Post/PostTeaser'
import SearchResultsEmpty from './SearchResultsEmpty'
import styles from './SearchResults.module.scss'
import { GatsbyImageProps } from 'gatsby-image'
import { PostMetadata } from '../../@types/PostMetadata'
export interface Results {
slug: string
}
const query = graphql`
query {
@ -30,48 +34,32 @@ const query = graphql`
}
`
interface Page {
slug: string
}
interface PostNode {
node: {
id: string
fields: { slug: string }
frontmatter: {
title: string
type: string
image: { childImageSharp: GatsbyImageProps }
}
}
}
export default function SearchResults({
function SearchResultsPure({
searchQuery,
results,
toggleSearch
toggleSearch,
posts
}: {
posts: [{ node: PostMetadata }]
searchQuery: string
results: any
results: Results[]
toggleSearch(): void
}) {
const data = useStaticQuery(query)
const posts = data.allMarkdownRemark.edges
// creating portal to break out of DOM node we're in
// and render the results in content container
return ReactDOM.createPortal(
return (
<div className={styles.searchResults}>
<Container>
{results.length > 0 ? (
<ul>
{results.map((page: Page) =>
{results.map((page: { slug: string }) =>
posts
.filter((post: PostNode) => post.node.fields.slug === page.slug)
.map((post: PostNode) => (
.filter(
({ node }: { node: PostMetadata }) =>
node.fields.slug === page.slug
)
.map(({ node }: { node: PostMetadata }) => (
<PostTeaser
key={page.slug}
post={post.node}
post={node}
toggleSearch={toggleSearch}
/>
))
@ -81,7 +69,31 @@ export default function SearchResults({
<SearchResultsEmpty searchQuery={searchQuery} results={results} />
)}
</Container>
</div>,
</div>
)
}
export default function SearchResults({
searchQuery,
results,
toggleSearch
}: {
searchQuery: string
results: Results[]
toggleSearch(): void
}) {
const data = useStaticQuery(query)
const posts = data.allMarkdownRemark.edges
// creating portal to break out of DOM node we're in
// and render the results in content container
return ReactDOM.createPortal(
<SearchResultsPure
posts={posts}
results={results}
searchQuery={searchQuery}
toggleSearch={toggleSearch}
/>,
document.getElementById('document')
)
}

View File

@ -1,12 +1,13 @@
import React from 'react'
import styles from './SearchResultsEmpty.module.scss'
import { Results } from './SearchResults'
const SearchResultsEmpty = ({
searchQuery,
results
}: {
searchQuery: string
results: []
results: Results[]
}) => (
<div className={styles.empty}>
<header className={styles.emptyMessage}>

View File

@ -1,26 +1,12 @@
import React, { useState } from 'react'
import { Helmet } from 'react-helmet'
import { CSSTransition } from 'react-transition-group'
import lunr from 'lunr'
import SearchInput from './SearchInput'
import SearchButton from './SearchButton'
import SearchResults from './SearchResults'
import styles from './index.module.scss'
declare global {
interface Window {
__LUNR__: {
readonly [language: string]: {
readonly index: lunr.Index
readonly store: {
readonly [key: string]: any
}
}
}
}
}
function getSearchResults(query: string, lng: string) {
if (!query || !window.__LUNR__) return []
const lunrIndex = window.__LUNR__[lng]

View File

@ -21,7 +21,7 @@ export default function Alerts({
message
}: {
transactionHash: string | null
message: { text?: MessageChannel; status?: string } | null
message: { text?: string; status?: string } | null
}) {
const constructMessage = () => {
let messageOutput

View File

@ -2,28 +2,22 @@ import React from 'react'
import testRender from '../../../jest/testRender'
import { PureChangelog as Changelog } from './Changelog'
import { GitHubRepo } from '../../@types/GitHub'
const data = {
github: {
viewer: {
repositories: {
edges: [
{
node: {
name: 'gatsby-plugin-matomo',
url: 'https://hello.com',
owner: { login: 'kremalicious' },
object: {
text: 'hello'
}
}
}
]
const repos: [{ node: GitHubRepo }] = [
{
node: {
name: 'gatsby-plugin-matomo',
url: 'https://hello.com',
owner: { login: 'kremalicious' },
object: {
id: 'hello',
text: 'hello'
}
}
}
}
]
describe('Changelog', () => {
testRender(<Changelog repo="gatsby-plugin-matomo" data={data} />)
testRender(<Changelog repo="gatsby-plugin-matomo" repos={repos} />)
})

View File

@ -3,12 +3,17 @@ import { graphql, useStaticQuery } from 'gatsby'
import remark from 'remark'
import remarkReact from 'remark-react'
import styles from './Changelog.module.scss'
import { GitHub, GitHubRepo } from '../../@types/GitHub'
export function PureChangelog({ repo, data }: { repo: string; data: any }) {
const repositoriesGitHub = data.github.viewer.repositories.edges
const repoFilteredArray = repositoriesGitHub
.map(({ node }: { node: any }) => {
export function PureChangelog({
repo,
repos
}: {
repo: string
repos: [{ node: GitHubRepo }]
}) {
const repoFilteredArray = repos
.map(({ node }: { node: GitHubRepo }) => {
if (node.name === repo) return node
})
.filter((n: any) => n)
@ -73,6 +78,7 @@ export default function Changelog({ repo }: { repo: string }) {
}
}
`
const data = useStaticQuery(queryGithub)
return <PureChangelog repo={repo} data={data} />
const data: GitHub = useStaticQuery(queryGithub)
const repos: [{ node: GitHubRepo }] = data.github.viewer.repositories.edges
return <PureChangelog repo={repo} repos={repos} />
}

View File

@ -1,22 +1,9 @@
import React from 'react'
import ExifMap from './ExifMap'
import styles from './Exif.module.scss'
import { PostMetadataImageExif } from '../../@types/PostMetadata'
interface ExifProps {
iso: string
model: string
fstop: string
shutterspeed: string
focalLength: string
lensModel: string
exposure: string
gps: {
latitude: string
longitude: string
}
}
export default function Exif({ exif }: { exif: ExifProps }) {
export default function Exif({ exif }: { exif: PostMetadataImageExif }) {
const { iso, model, fstop, shutterspeed, focalLength, exposure, gps } = exif
return (

View File

@ -2,6 +2,7 @@ import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import { Helmet } from 'react-helmet'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
import { PostMetadata } from '../../@types/PostMetadata'
const query = graphql`
query {
@ -116,7 +117,7 @@ export default function SEO({
slug,
postSEO
}: {
post?: any
post?: PostMetadata
slug?: string
postSEO?: boolean
}) {

View File

@ -2,39 +2,16 @@ import React from 'react'
import { Link, graphql, useStaticQuery } from 'gatsby'
import Image from '../atoms/Image'
import styles from './Featured.module.scss'
import { PostMetadata } from '../../@types/PostMetadata'
const query = graphql`
query {
allMarkdownRemark(
filter: { frontmatter: { featured: { eq: true } } }
sort: { fields: [fields___date], order: DESC }
) {
edges {
node {
id
frontmatter {
title
image {
childImageSharp {
...ImageFluidThumb
}
}
}
fields {
slug
}
}
}
}
}
`
export default function Featured() {
const data = useStaticQuery(query)
function FeaturedPure({
data
}: {
data: { allMarkdownRemark: { edges: [{ node: PostMetadata }] } }
}) {
return (
<div className={styles.featured}>
{data.allMarkdownRemark.edges.map(({ node }: { node: any }) => {
{data.allMarkdownRemark.edges.map(({ node }: { node: PostMetadata }) => {
const { title, image } = node.frontmatter
const { slug } = node.fields
@ -50,3 +27,34 @@ export default function Featured() {
</div>
)
}
export default function Featured() {
const query = graphql`
query {
allMarkdownRemark(
filter: { frontmatter: { featured: { eq: true } } }
sort: { fields: [fields___date], order: DESC }
) {
edges {
node {
id
frontmatter {
title
image {
childImageSharp {
...ImageFluidThumb
}
}
}
fields {
slug
}
}
}
}
}
`
const data = useStaticQuery(query)
return <FeaturedPure data={data} />
}

View File

@ -4,6 +4,7 @@ import { Link } from 'gatsby'
import Hamburger from '../atoms/Hamburger'
import styles from './Menu.module.scss'
import { useSiteMetadata } from '../../hooks/use-site-metadata'
import { MenuItem } from '../../@types/SiteMetadata'
export default function Menu() {
const [menuOpen, setMenuOpen] = useState(false)
@ -13,7 +14,7 @@ export default function Menu() {
setMenuOpen(!menuOpen)
}
const MenuItems = menu.map((item: any) => (
const MenuItems = menu.map((item: MenuItem) => (
<li key={item.title}>
<Link onClick={toggleMenu} to={item.link}>
{item.title}

View File

@ -2,6 +2,10 @@ import React, { useState } from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import PostTeaser from '../Post/PostTeaser'
import styles from './RelatedPosts.module.scss'
import {
PostMetadata,
PostMetadataFrontmatter
} from '../../@types/PostMetadata'
const query = graphql`
query {
@ -31,22 +35,26 @@ const query = graphql`
}
`
function postsWithDataFilter(posts: [], key: string, valuesToFind: string[]) {
const newArray = posts.filter((post: any) => {
const frontmatterKey = post.node.frontmatter[key]
function postsWithDataFilter(
posts: [{ node: PostMetadata }],
key: keyof PostMetadataFrontmatter,
valuesToFind: string[]
) {
const newArray = posts.filter(({ node }: { node: PostMetadata }) => {
const frontmatterKey = node.frontmatter[key] as []
if (
frontmatterKey !== null &&
frontmatterKey.some((r: string) => valuesToFind.includes(r))
) {
return post
return node
}
})
return newArray
}
function photosWithDataFilter(posts: []) {
const newArray = posts.filter((post: any) => {
const newArray = posts.filter((post: { node: PostMetadata }) => {
const { fileAbsolutePath } = post.node
if (fileAbsolutePath.includes('content/photos')) {
@ -85,7 +93,7 @@ export default function RelatedPosts({
{filteredPosts
.sort(() => 0.5 - Math.random())
.slice(0, 6)
.map(({ node }: { node: any }) => (
.map(({ node }: { node: PostMetadata }) => (
<PostTeaser key={node.id} post={node} />
))}
</ul>

View File

@ -1,6 +1,7 @@
import { useStaticQuery, graphql } from 'gatsby'
import { SiteMetadata } from '../@types/SiteMetadata'
export const useSiteMetadata = () => {
export function useSiteMetadata(): SiteMetadata {
const query = graphql`
query {
site {

View File

@ -3,6 +3,7 @@ import { graphql, Link } from 'gatsby'
import PostImage from '../components/Post/PostImage'
import Page from '../templates/Page'
import styles from './goodies.module.scss'
import { PostMetadata } from '../@types/PostMetadata'
const page = {
frontmatter: {
@ -12,16 +13,7 @@ const page = {
}
}
interface Post {
id: string
fields: { slug: string }
frontmatter: {
title: string
image: { childImageSharp: any }
}
}
const GoodiesThumb = ({ post }: { post: Post }) => {
const GoodiesThumb = ({ post }: { post: PostMetadata }) => {
const { title, image } = post.frontmatter
const { slug } = post.fields
@ -41,7 +33,7 @@ export default function Goodies({
data,
location
}: {
data: { goodies: { edges: [{ node: Post }] } }
data: { goodies: { edges: [{ node: PostMetadata }] } }
location: Location
}) {
return (

View File

@ -3,6 +3,7 @@ import { graphql, Link } from 'gatsby'
import Page from '../templates/Page'
import PostImage from '../components/Post/PostImage'
import styles from './photos.module.scss'
import { PostMetadata } from '../@types/PostMetadata'
const page = {
frontmatter: {
@ -11,17 +12,7 @@ const page = {
}
}
interface Photo {
id: string
fields: { slug: string }
frontmatter: {
title: string
type: string
image: { childImageSharp: any }
}
}
const PhotoThumb = ({ photo }: { photo: Photo }) => {
const PhotoThumb = ({ photo }: { photo: PostMetadata }) => {
const { title, image } = photo.frontmatter
const { slug } = photo.fields
const { fluid } = image.childImageSharp
@ -37,21 +28,11 @@ const PhotoThumb = ({ photo }: { photo: Photo }) => {
)
}
interface PhotosData {
photos: {
edges: [
{
node: Photo
}
]
}
}
export default function Photos({
data,
location
}: {
data: PhotosData
data: { photos: { edges: [{ node: PostMetadata }] } }
location: Location
}) {
return (

View File

@ -3,6 +3,7 @@ import { Helmet } from 'react-helmet'
import SEO from '../components/atoms/SEO'
import Layout from '../components/Layout'
import styles from './Page.module.scss'
import { PostMetadata } from '../@types/PostMetadata'
export default function Page({
title,
@ -14,8 +15,8 @@ export default function Page({
title: string
children: any
section?: string
location?: any
post?: any
location?: Location
post?: PostMetadata
}) {
return (
<>

View File

@ -13,15 +13,16 @@ import PostMeta from '../components/Post/PostMeta'
import Exif from '../components/atoms/Exif'
import RelatedPosts from '../components/molecules/RelatedPosts'
import styles from './Post.module.scss'
import { PostMetadata } from '../@types/PostMetadata'
export default function Post({
data,
location
}: {
data: any
data: { post: PostMetadata }
location: Location
}) {
const { markdownRemark: post } = data
const { post } = data
const { title, image, type, linkurl, style, tags } = post.frontmatter
const { slug, githubLink } = post.fields
@ -62,7 +63,7 @@ export default function Post({
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
post: markdownRemark(fields: { slug: { eq: $slug } }) {
html
excerpt
frontmatter {

View File

@ -12,13 +12,14 @@ import Pagination from '../components/molecules/Pagination'
import Featured from '../components/molecules/Featured'
import styles from './Posts.module.scss'
import stylesPost from './Post.module.scss'
import { PostMetadata } from '../@types/PostMetadata'
export default function Posts({
data,
location,
pageContext
}: {
data: any
data: { allMarkdownRemark: { edges: [{ node: PostMetadata }] } }
location: Location
pageContext: {
tag: string
@ -30,7 +31,7 @@ export default function Posts({
const edges = data.allMarkdownRemark.edges
const { tag, currentPageNumber, numPages, nextPage } = pageContext
const PostsList = edges.map(({ node }: { node: any }) => {
const PostsList = edges.map(({ node }: { node: PostMetadata }) => {
const { type, linkurl, title, image } = node.frontmatter
const { slug } = node.fields