Files
datacontroller.io/src/templates/post/index.tsx
T

189 lines
3.9 KiB
TypeScript

import * as React from 'react'
import { Link } from 'gatsby'
import kebabCase from 'lodash/kebabCase'
import { GatsbyImage, IGatsbyImageData } from 'gatsby-plugin-image'
import styled from 'styled-components'
import type { PostNode } from '../../types'
export const StyledLink = styled(Link)`
text-decoration: none;
color: black;
&:hover {
opacity: 0.8;
color: black;
}
`
const StyledTitle = styled.h5`
font-family:
'Montserrat', 'HelveticaNeue', 'Helvetica Neue', Helvetica, Arial,
sans-serif;
margin-bottom: 0;
`
const StyledDate = styled.span`
opacity: 0.5;
font-size: 0.8rem;
a {
color: black;
text-decoration: none;
&:hover {
text-decoration: underline;
color: black;
opacity: 1;
}
}
`
const StyledDesc = styled.p`
margin-top: 10px;
opacity: 0.7;
font-size: 0.8rem;
margin-bottom: 100px;
`
const StyledContent = styled.div`
padding: 15px 0;
color: #666666;
font-family:
'Montserrat', 'HelveticaNeue', 'Helvetica Neue', Helvetica, Arial,
sans-serif;
a {
color: black;
text-decoration: none;
&:hover {
text-decoration: underline;
color: #666666;
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: #222222;
}
* + h2,
* + h3 {
margin: 2rem auto 0.8rem;
}
img {
float: right;
max-width: 100%;
margin: 10px;
&.alignleft {
float: left;
}
&.aligncenter {
float: none;
max-width: 90%;
display: block;
margin: 10px auto;
}
}
.imgHolder {
padding: 5px;
margin-left: 5px;
float: right;
text-align: center;
border: 1px solid #e1e1e1;
border-radius: 2px;
font-style: italic;
font-family: Georgia, 'Times New Roman';
img {
float: none;
}
> div {
display: flex;
span {
flex-grow: 1;
width: 0;
}
}
}
pre {
background-image: linear-gradient(
rgba(0, 0, 0, 0.05) 50%,
transparent 50%,
transparent
);
background-size: 100% 4em;
border: 1px solid #e1e1e1;
padding: 2em;
line-height: 2em;
font-family: Monaco, 'Andale Mono', 'Courier New', Courier, monospace;
}
/* A fenced block tagged with the 'poem' language is verse, not code: drop
the code chrome and set it in the serif face, keeping the author's line
breaks and blank lines (which read as stanza breaks). */
pre:has(> code.language-poem) {
background-image: none;
border: none;
padding: 0;
margin: 1.8rem 0;
line-height: 1.75;
}
pre > code.language-poem {
font-family: Georgia, 'Times New Roman', serif;
font-size: 1.05rem;
color: #222222;
white-space: pre-wrap;
}
`
interface PostProps {
post: PostNode
location?: Location
}
const Post: React.FC<PostProps> = ({ post }) => {
const tagsJSX = (post.frontmatter?.tags || []).map((tag, index) => (
<span key={index}>
{index > 0 && ', '}
<Link to={`/category/${kebabCase(tag)}/`} rel="category tag">
{tag}
</Link>
</span>
))
const authorJSX = post.frontmatter.authorLink ? (
<span>
<a href={post.frontmatter.authorLink} target="_blank" rel="noopener">
{post.frontmatter.author}
</a>
</span>
) : (
<span>{post.frontmatter.author}</span>
)
const previewImgData = post.frontmatter.previewImg?.childImageSharp
?.gatsbyImageData as IGatsbyImageData | undefined
return (
<div>
{previewImgData && (
<GatsbyImage
image={previewImgData}
style={{ width: '100%', marginBottom: '1rem' }}
imgStyle={{ objectFit: 'contain' }}
alt={post.frontmatter.title}
/>
)}
<StyledTitle>{post.frontmatter.title}</StyledTitle>
<StyledDate>
{post.frontmatter.date} / in {tagsJSX} / by {authorJSX}
</StyledDate>
<StyledContent
dangerouslySetInnerHTML={{
__html: post.html
}}
/>
</div>
)
}
export default Post