changed from hexo to custom react stuff #1
15 changed files with 205 additions and 78 deletions
|
@ -1,5 +1,7 @@
|
||||||
{
|
{
|
||||||
"extends": [
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
"plugin:react/recommended",
|
"plugin:react/recommended",
|
||||||
"plugin:json/recommended",
|
"plugin:json/recommended",
|
||||||
"prettier"
|
"prettier"
|
||||||
|
@ -12,6 +14,7 @@
|
||||||
"version": "17.0"
|
"version": "17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"jsx": true
|
"jsx": true
|
||||||
|
@ -19,7 +22,16 @@
|
||||||
"sourceType": "module"
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
"plugins": ["react", "@typescript-eslint"],
|
"plugins": ["react", "@typescript-eslint"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx"],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": ["off"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
"react/jsx-uses-vars": "error",
|
"react/jsx-uses-vars": "error",
|
||||||
"react/no-unknown-property": [
|
"react/no-unknown-property": [
|
||||||
"error",
|
"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": "^17.0.2",
|
||||||
"react-burger-menu": "^3.0.6",
|
"react-burger-menu": "^3.0.6",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet-async": "^1.0.9",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "^4.0.3",
|
"react-scripts": "^4.0.3",
|
||||||
"react-spinners": "^0.10.6",
|
|
||||||
"react-tooltip": "^4.2.19",
|
"react-tooltip": "^4.2.19",
|
||||||
"styled-components": "^5.3.0",
|
"styled-components": "^5.3.0",
|
||||||
"styled-theming": "^2.2.0",
|
"styled-theming": "^2.2.0",
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR&family=Source+Code+Pro&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR&family=Source+Code+Pro&display=swap"
|
||||||
rel="stylesheet preload"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<title>pomp</title>
|
<title>pomp</title>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"
|
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 storage from "local-storage-fallback"
|
||||||
import { useState, useEffect } from "react"
|
import { useState, useEffect } from "react"
|
||||||
import theme from "styled-theming"
|
import theme from "styled-theming"
|
||||||
import Loader from "react-spinners/HashLoader"
|
import Spinner from "./components/Spinner"
|
||||||
|
|
||||||
import theming from "./theming"
|
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() {
|
function App() {
|
||||||
const [usingTheme, _setTheme] = useState(() => {
|
const [usingTheme, _setTheme] = useState(() => {
|
||||||
const savedTheme = storage.getItem("theme")
|
const savedTheme = storage.getItem("theme")
|
||||||
|
@ -145,12 +137,12 @@ function App() {
|
||||||
const [isLoading, setLoading] = useState(true)
|
const [isLoading, setLoading] = useState(true)
|
||||||
|
|
||||||
// show loading screen until all fonts are loaded.
|
// 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
|
// https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// checks if document.fonts.onloadingdone is supported on the browser
|
// checks if document.fonts.onloadingdone is supported on the browser
|
||||||
if (typeof document.fonts.onloadingdone != undefined) {
|
if (typeof document.fonts.onloadingdone != undefined) {
|
||||||
document.fonts.onloadingdone = (_: EventListener) => {
|
document.fonts.onloadingdone = () => {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -159,53 +151,55 @@ function App() {
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider
|
<HelmetProvider>
|
||||||
theme={{
|
<ThemeProvider
|
||||||
...usingTheme,
|
theme={{
|
||||||
setTheme: ({ setTheme, ...theme }) => _setTheme(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 />
|
<GlobalStyle />
|
||||||
<div id="content">
|
<Router>
|
||||||
{isLoading ? (
|
<Navbar />
|
||||||
<Loader
|
<div id="content">
|
||||||
color={
|
{isLoading ? (
|
||||||
usingTheme.mode == "light"
|
<Spinner
|
||||||
? theming.light.color1
|
size={200}
|
||||||
: theming.dark.color1
|
color={
|
||||||
}
|
usingTheme.mode == "light"
|
||||||
css={LoaderStyle}
|
? theming.light.color1
|
||||||
size={200}
|
: theming.dark.color1
|
||||||
/>
|
}
|
||||||
) : (
|
|
||||||
<Switch>
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path="/"
|
|
||||||
component={() => (
|
|
||||||
<Home howMany={4} title="Home" />
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<Route
|
) : (
|
||||||
exact
|
<Switch>
|
||||||
path="/archives"
|
<Route
|
||||||
component={() => <Home title="Archives" />}
|
exact
|
||||||
/>
|
path="/"
|
||||||
<Route
|
component={() => (
|
||||||
exact
|
<Home howMany={4} title="Home" />
|
||||||
path="/portfolio"
|
)}
|
||||||
component={Portfolio}
|
/>
|
||||||
/>
|
<Route
|
||||||
<Route exact path="/404" component={NotFound} />
|
exact
|
||||||
<Route exact path="/:path*" component={Page} />
|
path="/archives"
|
||||||
</Switch>
|
component={() => <Home title="Archives" />}
|
||||||
)}
|
/>
|
||||||
</div>
|
<Route
|
||||||
<Footer />
|
exact
|
||||||
</Router>
|
path="/portfolio"
|
||||||
</ThemeProvider>
|
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 { faGithub } from "@fortawesome/free-brands-svg-icons"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import theme from "styled-theming"
|
import theme from "styled-theming"
|
||||||
import { HashRouter as Router, Link } from "react-router-dom"
|
|
||||||
|
|
||||||
const StyledFooter = styled.footer`
|
const StyledFooter = styled.footer`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -51,14 +50,14 @@ function Footer() {
|
||||||
Copyright © <strong>develo</strong>pomp
|
Copyright © <strong>develo</strong>pomp
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Router className="icons">
|
<div className="icons">
|
||||||
<StyledLink
|
<StyledLink
|
||||||
href="https://github.com/developomp/developomp-site"
|
href="https://github.com/developomp/developomp-site"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faGithub} />
|
<FontAwesomeIcon icon={faGithub} />
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
</Router>
|
</div>
|
||||||
</StyledFooter>
|
</StyledFooter>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faGithub } from "@fortawesome/free-brands-svg-icons"
|
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 theme from "styled-theming"
|
||||||
import ReactTooltip from "react-tooltip"
|
import ReactTooltip from "react-tooltip"
|
||||||
import NavbarData from "../data/NavbarData"
|
import NavbarData from "../data/NavbarData"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faSearch } from "@fortawesome/free-solid-svg-icons"
|
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"
|
import theme from "styled-theming"
|
||||||
|
|
||||||
const StyledSearchBoxContainer = styled.div`
|
const StyledSearchBoxContainer = styled.div`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, useState } from "react"
|
import { useState } from "react"
|
||||||
import styled, { css } from "styled-components"
|
import styled, { css } from "styled-components"
|
||||||
import NavbarData from "../data/NavbarData"
|
import NavbarData from "../data/NavbarData"
|
||||||
import theme from "styled-theming"
|
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-tip
|
||||||
data-for="theme"
|
data-for="theme"
|
||||||
className="right"
|
className="right"
|
||||||
onClick={(_: any) =>
|
onClick={() =>
|
||||||
_theme.setTheme(
|
_theme.setTheme(
|
||||||
_theme.mode === "dark"
|
_theme.mode === "dark"
|
||||||
? { ..._theme, mode: "light" }
|
? { ..._theme, mode: "light" }
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Link } from "react-router-dom"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import theme from "styled-theming"
|
import theme from "styled-theming"
|
||||||
import marked from "marked"
|
import marked from "marked"
|
||||||
import Helmet from "react-helmet"
|
import { Helmet } from "react-helmet-async"
|
||||||
|
|
||||||
import pages from "../pages.json"
|
import pages from "../pages.json"
|
||||||
|
|
||||||
|
@ -48,9 +48,9 @@ const StyledPostCard = styled.div`
|
||||||
`
|
`
|
||||||
|
|
||||||
function Home(props) {
|
function Home(props) {
|
||||||
let PostCards: Array<any> = []
|
const PostCards: Array<unknown> = []
|
||||||
let howMany = props.howMany
|
let howMany = props.howMany
|
||||||
let isLimited = Boolean(howMany)
|
const isLimited = Boolean(howMany)
|
||||||
|
|
||||||
let h1Text = "All posts"
|
let h1Text = "All posts"
|
||||||
if (isLimited) {
|
if (isLimited) {
|
||||||
|
@ -60,7 +60,7 @@ function Home(props) {
|
||||||
for (const pagePath in pages) {
|
for (const pagePath in pages) {
|
||||||
if (isLimited && howMany <= 0) continue
|
if (isLimited && howMany <= 0) continue
|
||||||
|
|
||||||
let post = pages[pagePath]
|
const post = pages[pagePath]
|
||||||
post.title = post.meta?.title ? post.meta.title : "Unknown title"
|
post.title = post.meta?.title ? post.meta.title : "Unknown title"
|
||||||
post.date = post.meta?.date ? post.meta.date : "Unknown date"
|
post.date = post.meta?.date ? post.meta.date : "Unknown date"
|
||||||
post.author = post.meta?.author ? post.meta.author : "Unknown author"
|
post.author = post.meta?.author ? post.meta.author : "Unknown author"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import theme from "styled-theming"
|
import theme from "styled-theming"
|
||||||
import Helmet from "react-helmet"
|
import { Helmet } from "react-helmet-async"
|
||||||
|
|
||||||
const StyledNotFound = styled.div`
|
const StyledNotFound = styled.div`
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import marked from "marked"
|
import marked from "marked"
|
||||||
import NotFound from "./notfound"
|
import NotFound from "./notfound"
|
||||||
import Helmet from "react-helmet"
|
import { Helmet } from "react-helmet-async"
|
||||||
|
|
||||||
import pages from "../pages.json"
|
import pages from "../pages.json"
|
||||||
import { useParams } from "react-router-dom"
|
import { useParams } from "react-router-dom"
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const path = `/${useParams().path}`
|
const path = `/${useParams().path}`
|
||||||
let fetched = pages[path]
|
const fetched = pages[path]
|
||||||
if (!fetched) return <NotFound />
|
if (!fetched) return <NotFound />
|
||||||
|
|
||||||
// to prevent wrapping. I don't want to touch prettier stuff
|
// to prevent wrapping. I don't want to touch prettier stuff
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import theme from "styled-theming"
|
import { Helmet } from "react-helmet-async"
|
||||||
import Helmet from "react-helmet"
|
|
||||||
|
|
||||||
const StyledPortfolio = styled.div``
|
const StyledPortfolio = styled.div``
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue