- added custom spinner to use instead of imported ones
- added new empty blog post - changed react-helmet to react-helmet-async for faster tab title change and reduced console warning - better eslint config and corresponding warning fixes (changing let -> const, removed unused variables, etc.) - removed redundant Router from footer - removed ignored preload attribute value from font loading link tag in index.html
This commit is contained in:
parent
94b5af4ab8
commit
8a2db03c0f
15 changed files with 205 additions and 78 deletions
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:json/recommended",
|
||||
"prettier"
|
||||
|
@ -12,6 +14,7 @@
|
|||
"version": "17.0"
|
||||
}
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
|
@ -19,7 +22,16 @@
|
|||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["react", "@typescript-eslint"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-module-boundary-types": ["off"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"react/no-unknown-property": [
|
||||
"error",
|
||||
|
|
8
source/markdown/blog/death of miracle.md
Normal file
8
source/markdown/blog/death of miracle.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: death of miracle
|
||||
author: developomp
|
||||
date: May 15, 2021
|
||||
---
|
||||
|
||||
Understanding things what we once called magic.
|
||||
Science.
|
|
@ -37,10 +37,9 @@
|
|||
"react": "^17.0.2",
|
||||
"react-burger-menu": "^3.0.6",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-helmet-async": "^1.0.9",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "^4.0.3",
|
||||
"react-spinners": "^0.10.6",
|
||||
"react-tooltip": "^4.2.19",
|
||||
"styled-components": "^5.3.0",
|
||||
"styled-theming": "^2.2.0",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR&family=Source+Code+Pro&display=swap"
|
||||
rel="stylesheet preload"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<title>pomp</title>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"
|
||||
import { ThemeProvider, createGlobalStyle, css } from "styled-components"
|
||||
import { ThemeProvider, createGlobalStyle } from "styled-components"
|
||||
import { HelmetProvider } from "react-helmet-async"
|
||||
import storage from "local-storage-fallback"
|
||||
import { useState, useEffect } from "react"
|
||||
import theme from "styled-theming"
|
||||
import Loader from "react-spinners/HashLoader"
|
||||
import Spinner from "./components/Spinner"
|
||||
|
||||
import theming from "./theming"
|
||||
|
||||
|
@ -123,15 +124,6 @@ blockquote {
|
|||
}
|
||||
`
|
||||
|
||||
// the loader is not compatible with styled-components so I'm converting it to string.
|
||||
// doing this gives intellisense and stuff in my IDE
|
||||
const LoaderStyle = css`
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 50%);
|
||||
`.toString()
|
||||
|
||||
function App() {
|
||||
const [usingTheme, _setTheme] = useState(() => {
|
||||
const savedTheme = storage.getItem("theme")
|
||||
|
@ -145,12 +137,12 @@ function App() {
|
|||
const [isLoading, setLoading] = useState(true)
|
||||
|
||||
// show loading screen until all fonts are loaded.
|
||||
// Experimental feature. Not fully supported on all browsers (ehem IE ehem).
|
||||
// Experimental feature. Not fully supported on all browsers (IE, I'm looking at you).
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet
|
||||
useEffect(() => {
|
||||
// checks if document.fonts.onloadingdone is supported on the browser
|
||||
if (typeof document.fonts.onloadingdone != undefined) {
|
||||
document.fonts.onloadingdone = (_: EventListener) => {
|
||||
document.fonts.onloadingdone = () => {
|
||||
setLoading(false)
|
||||
}
|
||||
} else {
|
||||
|
@ -159,53 +151,55 @@ function App() {
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
theme={{
|
||||
...usingTheme,
|
||||
setTheme: ({ setTheme, ...theme }) => _setTheme(theme),
|
||||
}}
|
||||
>
|
||||
<GlobalStyle />
|
||||
<Router>
|
||||
<Navbar />
|
||||
<div id="content">
|
||||
{isLoading ? (
|
||||
<Loader
|
||||
color={
|
||||
usingTheme.mode == "light"
|
||||
? theming.light.color1
|
||||
: theming.dark.color1
|
||||
}
|
||||
css={LoaderStyle}
|
||||
size={200}
|
||||
/>
|
||||
) : (
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/"
|
||||
component={() => (
|
||||
<Home howMany={4} title="Home" />
|
||||
)}
|
||||
<HelmetProvider>
|
||||
<ThemeProvider
|
||||
theme={{
|
||||
...usingTheme,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
setTheme: ({ setTheme, ...theme }) => _setTheme(theme), // make setTheme function available in other components
|
||||
}}
|
||||
>
|
||||
<GlobalStyle />
|
||||
<Router>
|
||||
<Navbar />
|
||||
<div id="content">
|
||||
{isLoading ? (
|
||||
<Spinner
|
||||
size={200}
|
||||
color={
|
||||
usingTheme.mode == "light"
|
||||
? theming.light.color1
|
||||
: theming.dark.color1
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/archives"
|
||||
component={() => <Home title="Archives" />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/portfolio"
|
||||
component={Portfolio}
|
||||
/>
|
||||
<Route exact path="/404" component={NotFound} />
|
||||
<Route exact path="/:path*" component={Page} />
|
||||
</Switch>
|
||||
)}
|
||||
</div>
|
||||
<Footer />
|
||||
</Router>
|
||||
</ThemeProvider>
|
||||
) : (
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/"
|
||||
component={() => (
|
||||
<Home howMany={4} title="Home" />
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/archives"
|
||||
component={() => <Home title="Archives" />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/portfolio"
|
||||
component={Portfolio}
|
||||
/>
|
||||
<Route exact path="/404" component={NotFound} />
|
||||
<Route exact path="/:path*" component={Page} />
|
||||
</Switch>
|
||||
)}
|
||||
</div>
|
||||
<Footer />
|
||||
</Router>
|
||||
</ThemeProvider>
|
||||
</HelmetProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
|||
import { faGithub } from "@fortawesome/free-brands-svg-icons"
|
||||
import styled from "styled-components"
|
||||
import theme from "styled-theming"
|
||||
import { HashRouter as Router, Link } from "react-router-dom"
|
||||
|
||||
const StyledFooter = styled.footer`
|
||||
display: flex;
|
||||
|
@ -51,14 +50,14 @@ function Footer() {
|
|||
Copyright © <strong>develo</strong>pomp
|
||||
</div>
|
||||
|
||||
<Router className="icons">
|
||||
<div className="icons">
|
||||
<StyledLink
|
||||
href="https://github.com/developomp/developomp-site"
|
||||
target="_blank"
|
||||
>
|
||||
<FontAwesomeIcon icon={faGithub} />
|
||||
</StyledLink>
|
||||
</Router>
|
||||
</div>
|
||||
</StyledFooter>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||
import { faGithub } from "@fortawesome/free-brands-svg-icons"
|
||||
import styled, { ThemeConsumer } from "styled-components"
|
||||
import styled from "styled-components"
|
||||
import theme from "styled-theming"
|
||||
import ReactTooltip from "react-tooltip"
|
||||
import NavbarData from "../data/NavbarData"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||
import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
||||
import styled, { ThemeConsumer, css } from "styled-components"
|
||||
import styled from "styled-components"
|
||||
import theme from "styled-theming"
|
||||
|
||||
const StyledSearchBoxContainer = styled.div`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useState } from "react"
|
||||
import { useState } from "react"
|
||||
import styled, { css } from "styled-components"
|
||||
import NavbarData from "../data/NavbarData"
|
||||
import theme from "styled-theming"
|
||||
|
|
116
source/src/components/Spinner.tsx
Normal file
116
source/src/components/Spinner.tsx
Normal file
|
@ -0,0 +1,116 @@
|
|||
/** Spinner.tsx
|
||||
* https://github.com/dmitrymorozoff/react-spinners-kit/tree/master/src/components/whisper
|
||||
*/
|
||||
|
||||
import styled, { keyframes } from "styled-components"
|
||||
|
||||
const motion = keyframes`
|
||||
0% {
|
||||
transform: scale(1, 1);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(0, 0);
|
||||
opacity: 0;
|
||||
}
|
||||
`
|
||||
|
||||
const spin = keyframes`
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
75% {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
`
|
||||
|
||||
interface BallInterface {
|
||||
color: string
|
||||
size: number
|
||||
key: string
|
||||
index: number
|
||||
}
|
||||
|
||||
const Ball = styled.div<BallInterface>`
|
||||
float: left;
|
||||
clear: right;
|
||||
margin: ${(props) => props.size / 15}px;
|
||||
width: ${(props) => props.size / 5}px;
|
||||
height: ${(props) => props.size / 5}px;
|
||||
border-radius: 2px;
|
||||
background-color: ${(props) => props.color};
|
||||
animation-name: ${motion};
|
||||
animation-direction: alternate;
|
||||
animation-duration: 800ms;
|
||||
animation-iteration-count: infinite;
|
||||
&:nth-child(1) {
|
||||
animation-delay: 200ms;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
animation-delay: 400ms;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
animation-delay: 600ms;
|
||||
}
|
||||
&:nth-child(4) {
|
||||
animation-delay: 400ms;
|
||||
}
|
||||
&:nth-child(5) {
|
||||
animation-delay: 600ms;
|
||||
}
|
||||
&:nth-child(6) {
|
||||
animation-delay: 800ms;
|
||||
}
|
||||
&:nth-child(7) {
|
||||
animation-delay: 600ms;
|
||||
}
|
||||
&:nth-child(8) {
|
||||
animation-delay: 800ms;
|
||||
}
|
||||
&:nth-child(9) {
|
||||
animation-delay: 1000ms;
|
||||
}
|
||||
`
|
||||
|
||||
interface WrapperInterface {
|
||||
size: number
|
||||
}
|
||||
|
||||
const Wrapper = styled.div<WrapperInterface>`
|
||||
margin: 5rem auto 0 auto;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
animation: ${spin} 10s infinite;
|
||||
`
|
||||
|
||||
function Spinner({ size, color }) {
|
||||
const balls: unknown[] = []
|
||||
let keyValue = 0
|
||||
const countBallsInLine = 3
|
||||
for (let i = 0; i < countBallsInLine; i++) {
|
||||
for (let j = 0; j < countBallsInLine; j++) {
|
||||
balls.push(
|
||||
<Ball
|
||||
color={color}
|
||||
size={size}
|
||||
key={keyValue.toString()}
|
||||
index={keyValue}
|
||||
/>
|
||||
)
|
||||
keyValue++
|
||||
}
|
||||
}
|
||||
|
||||
return <Wrapper size={size}>{balls}</Wrapper>
|
||||
}
|
||||
|
||||
export default Spinner
|
|
@ -28,7 +28,7 @@ function Navbar() {
|
|||
data-tip
|
||||
data-for="theme"
|
||||
className="right"
|
||||
onClick={(_: any) =>
|
||||
onClick={() =>
|
||||
_theme.setTheme(
|
||||
_theme.mode === "dark"
|
||||
? { ..._theme, mode: "light" }
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Link } from "react-router-dom"
|
|||
import styled from "styled-components"
|
||||
import theme from "styled-theming"
|
||||
import marked from "marked"
|
||||
import Helmet from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
|
||||
import pages from "../pages.json"
|
||||
|
||||
|
@ -48,9 +48,9 @@ const StyledPostCard = styled.div`
|
|||
`
|
||||
|
||||
function Home(props) {
|
||||
let PostCards: Array<any> = []
|
||||
const PostCards: Array<unknown> = []
|
||||
let howMany = props.howMany
|
||||
let isLimited = Boolean(howMany)
|
||||
const isLimited = Boolean(howMany)
|
||||
|
||||
let h1Text = "All posts"
|
||||
if (isLimited) {
|
||||
|
@ -60,7 +60,7 @@ function Home(props) {
|
|||
for (const pagePath in pages) {
|
||||
if (isLimited && howMany <= 0) continue
|
||||
|
||||
let post = pages[pagePath]
|
||||
const post = pages[pagePath]
|
||||
post.title = post.meta?.title ? post.meta.title : "Unknown title"
|
||||
post.date = post.meta?.date ? post.meta.date : "Unknown date"
|
||||
post.author = post.meta?.author ? post.meta.author : "Unknown author"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import styled from "styled-components"
|
||||
import theme from "styled-theming"
|
||||
import Helmet from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
|
||||
const StyledNotFound = styled.div`
|
||||
margin: auto;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import marked from "marked"
|
||||
import NotFound from "./notfound"
|
||||
import Helmet from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
|
||||
import pages from "../pages.json"
|
||||
import { useParams } from "react-router-dom"
|
||||
|
||||
function Page() {
|
||||
const path = `/${useParams().path}`
|
||||
let fetched = pages[path]
|
||||
const fetched = pages[path]
|
||||
if (!fetched) return <NotFound />
|
||||
|
||||
// to prevent wrapping. I don't want to touch prettier stuff
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import styled from "styled-components"
|
||||
import theme from "styled-theming"
|
||||
import Helmet from "react-helmet"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
|
||||
const StyledPortfolio = styled.div``
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue