mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-08 23:44:09 +02:00
@@ -1,12 +1,9 @@
|
|||||||
import React from "react"
|
import React, { PropsWithChildren } from "react"
|
||||||
import * as SC from "./styles"
|
import * as SC from "./styles"
|
||||||
|
|
||||||
interface ContainerProps {
|
export function Container({
|
||||||
children: React.ReactNode
|
children,
|
||||||
|
...restProps
|
||||||
|
}: PropsWithChildren<{}>): JSX.Element {
|
||||||
|
return <SC.ContainerWrapper {...restProps}>{children}</SC.ContainerWrapper>
|
||||||
}
|
}
|
||||||
|
|
||||||
const Container = ({ children, ...restProps }: ContainerProps): JSX.Element => (
|
|
||||||
<SC.ContainerWrapper {...restProps}>{children}</SC.ContainerWrapper>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default Container
|
|
||||||
|
|||||||
@@ -8,13 +8,11 @@
|
|||||||
import React, { PropsWithChildren } from "react"
|
import React, { PropsWithChildren } from "react"
|
||||||
import { useStaticQuery, graphql } from "gatsby"
|
import { useStaticQuery, graphql } from "gatsby"
|
||||||
|
|
||||||
import Container from "../Container"
|
import { DocsSidebar } from "../DocsSidebar"
|
||||||
import DocsSidebar from "../DocsSidebar"
|
import { Footer } from "../Footer"
|
||||||
import { Main, MainContent } from "./styles"
|
import * as SC from "./styles"
|
||||||
import Scrollbar from "react-perfect-scrollbar"
|
|
||||||
import "react-perfect-scrollbar/dist/css/styles.css"
|
|
||||||
|
|
||||||
const DocsLayout = ({ children }: PropsWithChildren<{}>) => {
|
export function DocsLayout({ children }: PropsWithChildren<{}>) {
|
||||||
const data = useStaticQuery(graphql`
|
const data = useStaticQuery(graphql`
|
||||||
query {
|
query {
|
||||||
site {
|
site {
|
||||||
@@ -27,20 +25,14 @@ const DocsLayout = ({ children }: PropsWithChildren<{}>) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Main>
|
<SC.Main>
|
||||||
<DocsSidebar />
|
<DocsSidebar />
|
||||||
<MainContent>
|
<SC.MainContent>
|
||||||
<h1>{data.site.siteMetadata.title}</h1>
|
<h1>{data.site.siteMetadata.title}</h1>
|
||||||
{children}
|
{children}
|
||||||
</MainContent>
|
</SC.MainContent>
|
||||||
</Main>
|
</SC.Main>
|
||||||
<footer>
|
<Footer />
|
||||||
© {new Date().getFullYear()}, Built with
|
|
||||||
{` `}
|
|
||||||
<a href="https://www.gatsbyjs.org">Gatsby</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DocsLayout
|
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
// TODO: refactor this into styled components
|
|
||||||
|
|
||||||
html {
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
|
|
||||||
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
|
||||||
-ms-text-size-adjust: 100%;
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If you already use line highlighting
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Adjust the position of the line numbers */
|
|
||||||
.gatsby-highlight pre[class*="language-"].line-numbers {
|
|
||||||
padding-left: 2.8em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If you only want to use line numbering
|
|
||||||
*/
|
|
||||||
|
|
||||||
.gatsby-highlight {
|
|
||||||
background-color: #fdf6e3;
|
|
||||||
border-radius: 0.3em;
|
|
||||||
margin: 0.5em 0;
|
|
||||||
padding: 1em;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gatsby-highlight pre[class*="language-"].line-numbers {
|
|
||||||
padding: 0;
|
|
||||||
padding-left: 2.8em;
|
|
||||||
overflow: initial;
|
|
||||||
}
|
|
||||||
@@ -1,99 +1,25 @@
|
|||||||
import * as R from "ramda"
|
|
||||||
import React, { useState } from "react"
|
import React, { useState } from "react"
|
||||||
import Tree from "react-treeview"
|
import Tree from "react-treeview"
|
||||||
import { useStaticQuery, graphql } from "gatsby"
|
import { useStaticQuery, graphql } from "gatsby"
|
||||||
|
import useBuildTree from "./useBuildTree"
|
||||||
import * as SC from "./styles"
|
import * as SC from "./styles"
|
||||||
|
|
||||||
interface IFile {
|
export interface IFile {
|
||||||
title: string
|
title: string
|
||||||
type: "file"
|
type: "file"
|
||||||
path: string
|
path: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IFolder {
|
export interface IFolder {
|
||||||
title: string
|
title: string
|
||||||
type: "folder"
|
type: "folder"
|
||||||
path: string
|
path: string
|
||||||
children: IFileOrFolder[]
|
children: IFileOrFolder[]
|
||||||
}
|
}
|
||||||
|
|
||||||
type IFileOrFolder = IFile | IFolder
|
export type IFileOrFolder = IFile | IFolder
|
||||||
|
|
||||||
const traverse = (
|
export interface IFileQuery {
|
||||||
[head, ...tail]: string[],
|
|
||||||
basePath = "/docs"
|
|
||||||
): IFileOrFolder => {
|
|
||||||
const path = basePath + "/" + head
|
|
||||||
const isFile = !tail.length
|
|
||||||
if (isFile) {
|
|
||||||
// probably not more than one dot
|
|
||||||
const [name] = head.split(".")
|
|
||||||
return {
|
|
||||||
title: name,
|
|
||||||
type: "file",
|
|
||||||
path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
title: head,
|
|
||||||
type: "folder",
|
|
||||||
path,
|
|
||||||
children: [traverse(tail, path)],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const generateFolder = ({
|
|
||||||
title,
|
|
||||||
path,
|
|
||||||
targets,
|
|
||||||
}: {
|
|
||||||
title: IFolder["title"]
|
|
||||||
path: IFile["path"]
|
|
||||||
targets: IFolder[]
|
|
||||||
}): IFolder => {
|
|
||||||
const children = join(R.chain(target => target.children, targets))
|
|
||||||
|
|
||||||
return {
|
|
||||||
title,
|
|
||||||
type: "folder",
|
|
||||||
path,
|
|
||||||
children,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const generateFile = ({
|
|
||||||
title,
|
|
||||||
path,
|
|
||||||
}: {
|
|
||||||
title: IFile["title"]
|
|
||||||
path: IFile["path"]
|
|
||||||
}): IFile => {
|
|
||||||
return {
|
|
||||||
title,
|
|
||||||
path,
|
|
||||||
type: "file",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const join = ([head, ...tail]: IFileOrFolder[]): IFileOrFolder[] => {
|
|
||||||
if (!head) return []
|
|
||||||
|
|
||||||
const [similarFs, remaining] = R.partition(
|
|
||||||
obj => obj.title === head.title && obj.type === head.type,
|
|
||||||
tail
|
|
||||||
)
|
|
||||||
const targets = [head, ...similarFs]
|
|
||||||
const { title, path } = head
|
|
||||||
|
|
||||||
const current =
|
|
||||||
head.type === "folder"
|
|
||||||
? generateFolder({ title, path, targets: targets as IFolder[] })
|
|
||||||
: generateFile({ title, path })
|
|
||||||
|
|
||||||
return [current, ...join(remaining)]
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IFileQuery {
|
|
||||||
node: {
|
node: {
|
||||||
relativePath: string
|
relativePath: string
|
||||||
childMarkdownRemark: {
|
childMarkdownRemark: {
|
||||||
@@ -105,7 +31,7 @@ interface IFileQuery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IAllDocsQuery {
|
export interface IAllDocsQuery {
|
||||||
allFile: {
|
allFile: {
|
||||||
edges: IFileQuery[]
|
edges: IFileQuery[]
|
||||||
}
|
}
|
||||||
@@ -129,7 +55,7 @@ const ALL_DOCS = graphql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const plantTree = (item: IFileOrFolder) => {
|
function plantTree(item: IFileOrFolder) {
|
||||||
if (item.type === "file") {
|
if (item.type === "file") {
|
||||||
return (
|
return (
|
||||||
<SC.PageLink to={item.path} activeClassName="active">
|
<SC.PageLink to={item.path} activeClassName="active">
|
||||||
@@ -158,21 +84,13 @@ function Folder({ item }: { item: IFolder }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const DocsSidebar = () => {
|
export function DocsSidebar() {
|
||||||
const docs = useStaticQuery<IAllDocsQuery>(ALL_DOCS)
|
const docs = useStaticQuery<IAllDocsQuery>(ALL_DOCS)
|
||||||
|
const tree = useBuildTree(docs)
|
||||||
const objects = docs.allFile.edges.map(({ node: file }: IFileQuery) =>
|
|
||||||
traverse(file.relativePath.split("/"))
|
|
||||||
)
|
|
||||||
const results = join(objects)
|
|
||||||
|
|
||||||
console.log(results)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SC.DocsSidebarWrapper>
|
<SC.DocsSidebarWrapper>
|
||||||
{results.map(node => plantTree(node))}
|
{tree.map(node => plantTree(node))}
|
||||||
</SC.DocsSidebarWrapper>
|
</SC.DocsSidebarWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DocsSidebar
|
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
import * as R from "ramda"
|
||||||
|
import {
|
||||||
|
IFileOrFolder,
|
||||||
|
IFile,
|
||||||
|
IFolder,
|
||||||
|
IAllDocsQuery,
|
||||||
|
IFileQuery,
|
||||||
|
} from "./index"
|
||||||
|
|
||||||
|
function traverse(
|
||||||
|
[head, ...tail]: string[],
|
||||||
|
basePath = "/docs"
|
||||||
|
): IFileOrFolder {
|
||||||
|
const path = basePath + "/" + head
|
||||||
|
const isFile = !tail.length
|
||||||
|
if (isFile) {
|
||||||
|
// probably not more than one dot
|
||||||
|
const [name] = head.split(".")
|
||||||
|
return {
|
||||||
|
title: name,
|
||||||
|
type: "file",
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
title: head,
|
||||||
|
type: "folder",
|
||||||
|
path,
|
||||||
|
children: [traverse(tail, path)],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateFolder({
|
||||||
|
title,
|
||||||
|
path,
|
||||||
|
targets,
|
||||||
|
}: {
|
||||||
|
title: IFolder["title"]
|
||||||
|
path: IFile["path"]
|
||||||
|
targets: IFolder[]
|
||||||
|
}): IFolder {
|
||||||
|
const children = join(R.chain(target => target.children, targets))
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
type: "folder",
|
||||||
|
path,
|
||||||
|
children,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateFile({
|
||||||
|
title,
|
||||||
|
path,
|
||||||
|
}: {
|
||||||
|
title: IFile["title"]
|
||||||
|
path: IFile["path"]
|
||||||
|
}): IFile {
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
type: "file",
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function join([head, ...tail]: IFileOrFolder[]): IFileOrFolder[] {
|
||||||
|
if (!head) return []
|
||||||
|
|
||||||
|
const [similarFs, remaining] = R.partition(
|
||||||
|
obj => obj.title === head.title && obj.type === head.type,
|
||||||
|
tail
|
||||||
|
)
|
||||||
|
const targets = [head, ...similarFs]
|
||||||
|
const { title, path } = head
|
||||||
|
|
||||||
|
const current =
|
||||||
|
head.type === "folder"
|
||||||
|
? generateFolder({ title, path, targets: targets as IFolder[] })
|
||||||
|
: generateFile({ title, path })
|
||||||
|
|
||||||
|
return [current, ...join(remaining)]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useBuildTree(docs: IAllDocsQuery) {
|
||||||
|
const objects = docs.allFile.edges.map(({ node: file }: IFileQuery) =>
|
||||||
|
traverse(file.relativePath.split("/"))
|
||||||
|
)
|
||||||
|
|
||||||
|
return join(objects)
|
||||||
|
}
|
||||||
@@ -1,20 +1,18 @@
|
|||||||
import React from "react"
|
import React, { PropsWithChildren } from "react"
|
||||||
import { SidebarTitle } from "./style"
|
import * as SC from "./styles"
|
||||||
|
|
||||||
export interface DocsSidebarSectionProps {
|
export interface DocsSidebarSectionProps {
|
||||||
readonly title: string
|
readonly title: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const DocsSidebarSection = ({
|
export function DocsSidebarSection({
|
||||||
title,
|
title,
|
||||||
children,
|
children,
|
||||||
}: React.PropsWithChildren<DocsSidebarSectionProps>) => {
|
}: PropsWithChildren<DocsSidebarSectionProps>) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SidebarTitle>{title}</SidebarTitle>
|
<SC.SidebarTitle>{title}</SC.SidebarTitle>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DocsSidebarSection
|
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components"
|
||||||
|
|
||||||
export const SidebarTitle = styled.h3`
|
export const SidebarTitle = styled.h3`
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
`;
|
`
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import React from "react"
|
||||||
|
import * as SC from "./styles"
|
||||||
|
import { Container } from "../Container"
|
||||||
|
|
||||||
|
export function Footer() {
|
||||||
|
return (
|
||||||
|
<SC.FooterWrapper>
|
||||||
|
<Container>
|
||||||
|
© {new Date().getFullYear()}, Built with
|
||||||
|
{` `}
|
||||||
|
<a href="https://www.gatsbyjs.org">Gatsby</a>
|
||||||
|
</Container>
|
||||||
|
</SC.FooterWrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { Link } from "gatsby"
|
||||||
|
import styled from "styled-components"
|
||||||
|
|
||||||
|
export const FooterWrapper = styled.footer``
|
||||||
@@ -8,15 +8,15 @@
|
|||||||
import React, { PropsWithChildren } from "react"
|
import React, { PropsWithChildren } from "react"
|
||||||
import { useStaticQuery, graphql } from "gatsby"
|
import { useStaticQuery, graphql } from "gatsby"
|
||||||
|
|
||||||
import Container from "../Container"
|
import { Container } from "../Container"
|
||||||
import Navbar from "../Navbar"
|
import { Footer } from "../Footer"
|
||||||
import Sidebar from "../Sidebar"
|
import { Sidebar } from "../Sidebar"
|
||||||
import "./layout.scss"
|
import "./layout.scss"
|
||||||
import { Main, MainContent } from "./styles"
|
import * as SC from "./styles"
|
||||||
import Scrollbar from "react-perfect-scrollbar"
|
import Scrollbar from "react-perfect-scrollbar"
|
||||||
import "react-perfect-scrollbar/dist/css/styles.css"
|
import "react-perfect-scrollbar/dist/css/styles.css"
|
||||||
|
|
||||||
const Layout = ({ children }: PropsWithChildren<{}>) => {
|
export function Layout({ children }: PropsWithChildren<{}>) {
|
||||||
const data = useStaticQuery(graphql`
|
const data = useStaticQuery(graphql`
|
||||||
query {
|
query {
|
||||||
site {
|
site {
|
||||||
@@ -30,23 +30,15 @@ const Layout = ({ children }: PropsWithChildren<{}>) => {
|
|||||||
return (
|
return (
|
||||||
<Scrollbar>
|
<Scrollbar>
|
||||||
<Container>
|
<Container>
|
||||||
<Main>
|
<SC.Main>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<MainContent>
|
<SC.MainContent>
|
||||||
<h1>{data.site.siteMetadata.title}</h1>
|
<h1>{data.site.siteMetadata.title}</h1>
|
||||||
{children}
|
{children}
|
||||||
</MainContent>
|
</SC.MainContent>
|
||||||
</Main>
|
</SC.Main>
|
||||||
</Container>
|
</Container>
|
||||||
<footer>
|
<Footer />
|
||||||
<Container>
|
|
||||||
© {new Date().getFullYear()}, Built with
|
|
||||||
{` `}
|
|
||||||
<a href="https://www.gatsbyjs.org">Gatsby</a>
|
|
||||||
</Container>
|
|
||||||
</footer>
|
|
||||||
</Scrollbar>
|
</Scrollbar>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Layout
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ html {
|
|||||||
-ms-text-size-adjust: 100%;
|
-ms-text-size-adjust: 100%;
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import { Link } from "gatsby";
|
|
||||||
import * as React from "react";
|
|
||||||
import icon from "./icon.png";
|
|
||||||
import { HeaderWrapper } from "./styles";
|
|
||||||
|
|
||||||
// @todo maybe find alternative type for data
|
|
||||||
const Navbar = ({ siteTitle }: any) => (
|
|
||||||
<HeaderWrapper>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
margin: `0 auto`,
|
|
||||||
maxWidth: 960,
|
|
||||||
padding: `1.45rem 1.0875rem`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: "flex", flexDirection: "row", alignItems: "center" }}>
|
|
||||||
{/* <img src={icon} style={{ width: "70px" }} /> */}
|
|
||||||
<h1 style={{ margin: 0 }}>
|
|
||||||
<Link
|
|
||||||
to="/"
|
|
||||||
style={{
|
|
||||||
color: `white`,
|
|
||||||
textDecoration: `none`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{siteTitle}
|
|
||||||
</Link>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</HeaderWrapper>
|
|
||||||
)
|
|
||||||
|
|
||||||
Navbar.propTypes = {
|
|
||||||
siteTitle: String
|
|
||||||
}
|
|
||||||
|
|
||||||
Navbar.defaultProps = {
|
|
||||||
siteTitle: ``,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Navbar;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import styled from "styled-components";
|
|
||||||
|
|
||||||
export const HeaderWrapper = styled.header`
|
|
||||||
background: #ba1a2e;
|
|
||||||
marginBottom: 1.45rem;
|
|
||||||
`;
|
|
||||||
@@ -3,13 +3,20 @@ import Helmet from "react-helmet"
|
|||||||
import { useStaticQuery, graphql } from "gatsby"
|
import { useStaticQuery, graphql } from "gatsby"
|
||||||
|
|
||||||
interface SEOProps {
|
interface SEOProps {
|
||||||
readonly description: string;
|
readonly description?: string
|
||||||
readonly lang: string;
|
readonly lang?: string
|
||||||
readonly meta: object[];
|
readonly meta?: any[]
|
||||||
readonly title: string;
|
readonly keywords?: string[]
|
||||||
|
readonly title: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const SEO = ({ description = "", lang = "en", meta = [], title }: SEOProps) => {
|
export function SEO({
|
||||||
|
description,
|
||||||
|
lang = "en",
|
||||||
|
meta = [],
|
||||||
|
keywords = [],
|
||||||
|
title,
|
||||||
|
}: SEOProps) {
|
||||||
const { site } = useStaticQuery(
|
const { site } = useStaticQuery(
|
||||||
graphql`
|
graphql`
|
||||||
query {
|
query {
|
||||||
@@ -66,9 +73,16 @@ const SEO = ({ description = "", lang = "en", meta = [], title }: SEOProps) => {
|
|||||||
name: `twitter:description`,
|
name: `twitter:description`,
|
||||||
content: metaDescription,
|
content: metaDescription,
|
||||||
},
|
},
|
||||||
]}
|
]
|
||||||
|
.concat(
|
||||||
|
keywords.length > 0
|
||||||
|
? {
|
||||||
|
name: `keywords`,
|
||||||
|
content: keywords.join(`, `),
|
||||||
|
}
|
||||||
|
: []
|
||||||
|
)
|
||||||
|
.concat(meta)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default SEO
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from "react"
|
import React, { PropsWithChildren } from "react"
|
||||||
import logo from "../../images/tph-logo.png"
|
import logo from "../../images/tph-logo.png"
|
||||||
import * as SC from "./styles"
|
import * as SC from "./styles"
|
||||||
import ArrowRight from "../../icons/arrow-right.svg"
|
import ArrowRight from "../../icons/arrow-right.svg"
|
||||||
|
|
||||||
function MenuItem({ children, to }: { children: React.ReactNode; to: string }) {
|
function MenuItem({ children, to }: PropsWithChildren<{ to: string }>) {
|
||||||
return (
|
return (
|
||||||
<SC.MenuItem to={to}>
|
<SC.MenuItem to={to}>
|
||||||
{children} <ArrowRight />
|
{children} <ArrowRight />
|
||||||
@@ -11,7 +11,7 @@ function MenuItem({ children, to }: { children: React.ReactNode; to: string }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sidebar = () => {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<SC.SidebarWrapper>
|
<SC.SidebarWrapper>
|
||||||
<SC.Logo src={logo} />
|
<SC.Logo src={logo} />
|
||||||
@@ -27,5 +27,3 @@ const Sidebar = () => {
|
|||||||
</SC.SidebarWrapper>
|
</SC.SidebarWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Sidebar
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ called `getMembers` that retrieves all the members in a discord server. When we
|
|||||||
function we see the following result.
|
function we see the following result.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const members = getMembers("The Programmers Hangout");
|
const members = getMembers("The Programmers Hangout")
|
||||||
console.log(members); // Promise {<pending>}
|
console.log(members) // Promise {<pending>}
|
||||||
```
|
```
|
||||||
|
|
||||||
Normally, we would have expected to see an array of all the members but it takes time to
|
Normally, we would have expected to see an array of all the members but it takes time to
|
||||||
@@ -44,8 +44,8 @@ to access the actual members like so.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
getMembers("The Programmers Hangout").then(members => {
|
getMembers("The Programmers Hangout").then(members => {
|
||||||
console.log(members); // (32k) [{...}, {...}, {...}]
|
console.log(members) // (32k) [{...}, {...}, {...}]
|
||||||
});
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
This way we are able to make sure that we only try to `console.log` when the `getMembers` function has resolved and ready to be used.
|
This way we are able to make sure that we only try to `console.log` when the `getMembers` function has resolved and ready to be used.
|
||||||
@@ -63,15 +63,15 @@ You may have tried doing something like this before.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
// Incorrect code, don't copy!
|
// Incorrect code, don't copy!
|
||||||
let results;
|
let results
|
||||||
getWeather("Los Angeles").then(weather => {
|
getWeather("Los Angeles").then(weather => {
|
||||||
results = weather;
|
results = weather
|
||||||
});
|
})
|
||||||
console.log(results) // undefined
|
console.log(results) // undefined
|
||||||
```
|
```
|
||||||
|
|
||||||
Why is `results` undefined? Because **Javascript doesn't wait**. Whenever a Promise is created,
|
Why is `results` undefined? Because **Javascript doesn't wait**. Whenever a Promise is created,
|
||||||
your code will continue to run until there's no more code left in the stack. Only then
|
your code will continue to run until there's no more code left in the stack. Only then
|
||||||
will javascript try to run the `.then` callback of a Promise. Even if your Promise resolves
|
will javascript try to run the `.then` callback of a Promise. Even if your Promise resolves
|
||||||
immediately you are going to have to wait until you've run all the code in the stack before
|
immediately you are going to have to wait until you've run all the code in the stack before
|
||||||
your `.then` callback has a chance to start running. This is due to the way the event loop works,
|
your `.then` callback has a chance to start running. This is due to the way the event loop works,
|
||||||
@@ -81,8 +81,8 @@ In order to fix this problem we need to move the `console.log` inside the `.then
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
getWeather("Los Angeles").then(weather => {
|
getWeather("Los Angeles").then(weather => {
|
||||||
console.log(weather); // Sunny, probably
|
console.log(weather) // Sunny, probably
|
||||||
});
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Real World Example
|
## Real World Example
|
||||||
@@ -94,14 +94,14 @@ You can try it in your browser if you want to test it out.
|
|||||||
function getCharacters() {
|
function getCharacters() {
|
||||||
return fetch(`https://rickandmortyapi.com/api/character`)
|
return fetch(`https://rickandmortyapi.com/api/character`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(response => response.results);
|
.then(response => response.results)
|
||||||
}
|
}
|
||||||
|
|
||||||
getCharacters().then(characters => {
|
getCharacters().then(characters => {
|
||||||
console.log(characters); // (20) [{...}, {...}, {...}]
|
console.log(characters) // (20) [{...}, {...}, {...}]
|
||||||
});
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's break down what's happening in this function
|
Let's break down what's happening in this function
|
||||||
|
|
||||||
// TODO: finish this
|
// TODO: finish this
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ function doAsync(number) {
|
|||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
doDatabase().then(function(dbResult) {
|
doDatabase().then(function(dbResult) {
|
||||||
otherDbFunction(dbResult).then(function(secondResult) {
|
otherDbFunction(dbResult).then(function(secondResult) {
|
||||||
resolve(secondResult + 10);
|
resolve(secondResult + 10)
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -29,9 +29,9 @@ already returns a promise, you can just return the original thing.
|
|||||||
function doAsync(number) {
|
function doAsync(number) {
|
||||||
return doDatabase().then(function(dbResult) {
|
return doDatabase().then(function(dbResult) {
|
||||||
otherDbFunction(dbResult).then(function(secondResult) {
|
otherDbFunction(dbResult).then(function(secondResult) {
|
||||||
return secondResult + 10;
|
return secondResult + 10
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -40,11 +40,13 @@ is that they allow you do chain them sequentially.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
function doAsync(number) {
|
function doAsync(number) {
|
||||||
return doDatabase().then(function(dbResult) {
|
return doDatabase()
|
||||||
return otherDbFunction(dbResult)
|
.then(function(dbResult) {
|
||||||
}).then(function(secondResult) {
|
return otherDbFunction(dbResult)
|
||||||
return secondResult + 10;
|
})
|
||||||
});
|
.then(function(secondResult) {
|
||||||
|
return secondResult + 10
|
||||||
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -56,17 +58,18 @@ function doAsync(number) {
|
|||||||
return doDatabase()
|
return doDatabase()
|
||||||
.then(otherDbFunction)
|
.then(otherDbFunction)
|
||||||
.then(function(secondResult) {
|
.then(function(secondResult) {
|
||||||
return secondResult + 10;
|
return secondResult + 10
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And you don't need those returns if you just have ES6 arrow functions
|
And you don't need those returns if you just have ES6 arrow functions
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const doAsync = number => doDatabase()
|
const doAsync = number =>
|
||||||
.then(otherDbFunction)
|
doDatabase()
|
||||||
.then(secondResult => secondResult + 10);
|
.then(otherDbFunction)
|
||||||
|
.then(secondResult => secondResult + 10)
|
||||||
```
|
```
|
||||||
|
|
||||||
Wow, that last one looks a lot cleaner to me than the first. Keeping that in mind, maybe we could be making some of our other functions cleaner as well
|
Wow, that last one looks a lot cleaner to me than the first. Keeping that in mind, maybe we could be making some of our other functions cleaner as well
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ There are multiple benefits to using a singleton class
|
|||||||
- You're always going to pull the same instance of the class
|
- You're always going to pull the same instance of the class
|
||||||
- It's only instantiated once
|
- It's only instantiated once
|
||||||
- Use `$this` in a static-like context
|
- Use `$this` in a static-like context
|
||||||
-
|
|
||||||
|
|
||||||
By using a singleton instead of a static class we expose a cleaner class to use and we can use regular instance properties instead of static properties.
|
By using a singleton instead of a static class we expose a cleaner class to use and we can use regular instance properties instead of static properties.
|
||||||
|
|
||||||
@@ -28,13 +27,13 @@ namespace Example;
|
|||||||
|
|
||||||
class Singleton
|
class Singleton
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The singleton instance
|
* The singleton instance
|
||||||
* @var Singleton
|
* @var Singleton
|
||||||
*/
|
*/
|
||||||
private static $instance;
|
private static $instance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the instantiated singleton, or create it if it hasn't been instantiated yet.
|
* Get the instantiated singleton, or create it if it hasn't been instantiated yet.
|
||||||
* @return Singleton
|
* @return Singleton
|
||||||
@@ -44,7 +43,7 @@ class Singleton
|
|||||||
// static::$instance =?? new static();
|
// static::$instance =?? new static();
|
||||||
// The double ?'s is a null-coalesce operator. There's a link about it below.
|
// The double ?'s is a null-coalesce operator. There's a link about it below.
|
||||||
static::$instance = static::$instance ?? new static();
|
static::$instance = static::$instance ?? new static();
|
||||||
|
|
||||||
return static::$instance;
|
return static::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,12 +56,12 @@ To give a little functionality to our freshly baked Singleton we add these three
|
|||||||
|
|
||||||
```php
|
```php
|
||||||
private $word = "Pineapple";
|
private $word = "Pineapple";
|
||||||
|
|
||||||
public function getWord(): string {
|
public function getWord(): string {
|
||||||
// PHP_EOL is a constant for a new line (\r\n) or whichever your OS uses.
|
// PHP_EOL is a constant for a new line (\r\n) or whichever your OS uses.
|
||||||
return $this->word . PHP_EOL;
|
return $this->word . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setWord(string $word): void {
|
public function setWord(string $word): void {
|
||||||
$this->word = $word;
|
$this->word = $word;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-9
@@ -1,14 +1,16 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
|
|
||||||
import Layout from "../components/Layout"
|
import { Layout } from "../components/Layout"
|
||||||
import SEO from "../components/SEO"
|
import { SEO } from "../components/SEO"
|
||||||
|
|
||||||
const NotFoundPage = () => (
|
function NotFoundPage() {
|
||||||
<Layout>
|
return (
|
||||||
<SEO title="404: Not found" />
|
<Layout>
|
||||||
<h1>NOT FOUND</h1>
|
<SEO title="404: Not found" />
|
||||||
<p>You just hit a route that doesn't exist... the sadness.</p>
|
<h1>NOT FOUND</h1>
|
||||||
</Layout>
|
<p>You just hit a route that doesn't exist... the sadness.</p>
|
||||||
)
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default NotFoundPage
|
export default NotFoundPage
|
||||||
|
|||||||
+10
-8
@@ -1,13 +1,15 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
|
|
||||||
import DocsLayout from "../components/DocsLayout"
|
import { DocsLayout } from "../components/DocsLayout"
|
||||||
import SEO from "../components/SEO"
|
import { SEO } from "../components/SEO"
|
||||||
|
|
||||||
const DocsPage = () => (
|
function DocsPage() {
|
||||||
<DocsLayout>
|
return (
|
||||||
<SEO title="Docs" />
|
<DocsLayout>
|
||||||
the docs
|
<SEO title="Docs" />
|
||||||
</DocsLayout>
|
the docs
|
||||||
)
|
</DocsLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default DocsPage
|
export default DocsPage
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
# Hello
|
|
||||||
+14
-13
@@ -1,19 +1,20 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { Link } from "gatsby"
|
import { Link } from "gatsby"
|
||||||
|
|
||||||
import Layout from "../components/Layout"
|
import { Layout } from "../components/Layout"
|
||||||
import SEO from "../components/SEO"
|
import { SEO } from "../components/SEO"
|
||||||
|
|
||||||
const IndexPage = () => (
|
function IndexPage() {
|
||||||
<Layout>
|
return (
|
||||||
<SEO title="Home" />
|
<Layout>
|
||||||
<h1>Hi people</h1>
|
<SEO title="Home" />
|
||||||
<p>Welcome to your new Gatsby site.</p>
|
<h1>Hi people</h1>
|
||||||
<p>Now go build something great.</p>
|
<p>Welcome to your new Gatsby site.</p>
|
||||||
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
|
<p>Now go build something great.</p>
|
||||||
</div>
|
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}></div>
|
||||||
<Link to="/page-2/">Go to page 2</Link>
|
<Link to="/page-2/">Go to page 2</Link>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default IndexPage
|
export default IndexPage
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { graphql } from "gatsby"
|
import { graphql } from "gatsby"
|
||||||
import SEO from "../components/SEO"
|
import { SEO } from "../components/SEO"
|
||||||
import DocsLayout from "../components/DocsLayout"
|
import { DocsLayout } from "../components/DocsLayout"
|
||||||
|
|
||||||
// @todo maybe find alternative type for data
|
// @todo maybe find alternative type for data
|
||||||
const LanguagePost = ({ data }: any) => {
|
function LanguagePost({ data }: any) {
|
||||||
const { html, frontmatter } = data.file.post
|
const { html, frontmatter } = data.file.post
|
||||||
console.log(data)
|
console.log(data)
|
||||||
return (
|
return (
|
||||||
|
|||||||
Vendored
+1
@@ -1 +1,2 @@
|
|||||||
declare module "*.svg"
|
declare module "*.svg"
|
||||||
|
declare module "*.png"
|
||||||
|
|||||||
Reference in New Issue
Block a user