From 5bd07871127a8b1a66c3215901e93b58532eb0e4 Mon Sep 17 00:00:00 2001
From: Jean-Philippe Sirois
Date: Tue, 17 Sep 2019 00:21:33 -0400
Subject: [PATCH 1/5] resources: set up home page
---
src/components/ResourcesList/index.tsx | 94 ++++++++++++++++
src/components/ResourcesList/styles.tsx | 103 ++++++++++++++++++
src/components/ResourcesList/useBuildTree.tsx | 76 +++++++++++++
src/pages/resources.tsx | 10 +-
src/utils/index.ts | 27 ++++-
5 files changed, 308 insertions(+), 2 deletions(-)
create mode 100644 src/components/ResourcesList/index.tsx
create mode 100644 src/components/ResourcesList/styles.tsx
create mode 100644 src/components/ResourcesList/useBuildTree.tsx
diff --git a/src/components/ResourcesList/index.tsx b/src/components/ResourcesList/index.tsx
new file mode 100644
index 0000000..72ad9f6
--- /dev/null
+++ b/src/components/ResourcesList/index.tsx
@@ -0,0 +1,94 @@
+import { graphql, useStaticQuery } from "gatsby"
+import React, { memo } from "react"
+import "react-perfect-scrollbar/dist/css/styles.css"
+import * as SC from "./styles"
+import useBuildTree from "./useBuildTree"
+
+export interface IFile {
+ title: string
+ type: "file"
+ path: string
+}
+
+export interface IFolder {
+ title: string
+ type: "folder"
+ path: string
+ children: IFileOrFolder[]
+}
+
+export type IFileOrFolder = IFile | IFolder
+
+export interface IFileQuery {
+ node: {
+ relativePath: string
+ childMarkdownRemark: {
+ frontmatter: {
+ author: string
+ date: string
+ }
+ }
+ }
+}
+
+export interface IAllResourcesQuery {
+ allFile: {
+ edges: IFileQuery[]
+ }
+}
+
+const ALL_RESOURCES = graphql`
+ query {
+ allFile(filter: { sourceInstanceName: { eq: "resources" } }) {
+ edges {
+ node {
+ relativePath
+ childMarkdownRemark {
+ frontmatter {
+ authors
+ title
+ date
+ }
+ }
+ }
+ }
+ }
+ }
+`
+
+function plantTree(item: IFileOrFolder, index?: number) {
+ if (item.type === "file") {
+ // remove the first elements, treat as hardcoded
+ const [, , , ...cleanedUpPath] = item.path.split("/")
+ return (
+
+ {cleanedUpPath.map(node => (
+ // TODO: use helper to format path
+ {node.replace(".md", "")}
+ ))}
+
+ )
+ }
+
+ return
+}
+
+const Language = memo(({ item }: { item: IFolder; index: number }) => {
+ return (
+
+ {item.title}
+ {item.children.map(node => plantTree(node))}
+
+ )
+})
+
+export function ResourcesList(props: React.HTMLAttributes) {
+ const resources = useStaticQuery(ALL_RESOURCES)
+ const tree = useBuildTree(resources)
+
+ return (
+
+ {tree.map((node, index) => plantTree(node, index))}
+
+ )
+}
diff --git a/src/components/ResourcesList/styles.tsx b/src/components/ResourcesList/styles.tsx
new file mode 100644
index 0000000..156d03d
--- /dev/null
+++ b/src/components/ResourcesList/styles.tsx
@@ -0,0 +1,103 @@
+import { Link } from "gatsby"
+import { transparentize } from "polished"
+import styled from "styled-components"
+
+export const ResourcesListWrapper = styled.div`
+ box-sizing: border-box;
+ color: ${props => props.theme.main.foreground};
+`
+
+export const Children = styled.div`
+ padding-left: 16px;
+ padding-bottom: 8px;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ overflow: hidden;
+`
+
+export const Label = styled.div`
+ user-select: none;
+ position: relative;
+ padding: 4px 0 2px;
+ margin-bottom: 2px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ border-bottom: 1px solid transparent;
+ align-self: flex-start;
+
+ &:hover {
+ border-color: ${props =>
+ transparentize(0.7, props.theme.sidebar.foreground)};
+ }
+
+ svg {
+ position: absolute;
+ right: 100%;
+ margin-right: 4px;
+ width: 10px;
+ }
+`
+
+export const LanguageLabel = styled.div`
+ display: flex;
+ align-items: center;
+ width: 100%;
+ box-sizing: border-box;
+ padding: 4px 15px 4px 0;
+ font-weight: 700;
+ color: ${props => transparentize(0.5, props.theme.sidebar.foreground)};
+
+ svg {
+ margin-left: auto;
+ transform: rotate(90deg);
+ transition: transform 0.3s;
+
+ path {
+ fill: ${props => transparentize(0.5, props.theme.sidebar.foreground)};
+ }
+ }
+`
+
+export const TreeWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ font-size: 16px;
+ margin: 32px 0;
+
+ ${Children} {
+ display: flex;
+ }
+
+ & > ${Label} svg {
+ fill: ${props => props.theme.sidebar.foreground};
+ }
+`
+
+export const PageLink = styled(Link)`
+ display: block;
+ padding: 2px 0;
+ color: ${props => props.theme.sidebar.foreground};
+ align-self: flex-start;
+ text-decoration: none;
+ border-bottom: 1px solid transparent;
+
+ &:hover {
+ border-color: ${props =>
+ transparentize(0.7, props.theme.sidebar.foreground)};
+ }
+
+ & + & {
+ margin-top: 4px;
+ }
+`
+
+export const NodePart = styled.span`
+ & + &::before {
+ content: "/";
+ opacity: 0.3;
+ margin: 0 4px;
+ }
+`
diff --git a/src/components/ResourcesList/useBuildTree.tsx b/src/components/ResourcesList/useBuildTree.tsx
new file mode 100644
index 0000000..5adc513
--- /dev/null
+++ b/src/components/ResourcesList/useBuildTree.tsx
@@ -0,0 +1,76 @@
+import chain from "ramda/es/chain"
+import partition from "ramda/es/partition"
+
+import { traversePathsToFiles } from "../../utils"
+import {
+ IAllResourcesQuery,
+ IFile,
+ IFileOrFolder,
+ IFileQuery,
+ IFolder,
+} from "./index"
+
+function generateFolder({
+ title,
+ path,
+ targets,
+}: {
+ title: IFolder["title"]
+ path: IFile["path"]
+ targets: IFolder[]
+}): IFolder {
+ const children = join(chain(target => target.children, targets))
+
+ return {
+ title,
+ type: "folder",
+ path,
+ children: children.sort((a, b) =>
+ a.title.split("/").length > b.title.split("/").length
+ ? -1
+ : a.title.localeCompare(b.title)
+ ),
+ }
+}
+
+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] = 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(resources: IAllResourcesQuery) {
+ const objects = resources.allFile.edges.map(({ node: file }: IFileQuery) =>
+ traversePathsToFiles(file.relativePath.split("/"))
+ )
+
+ return join(objects)
+}
diff --git a/src/pages/resources.tsx b/src/pages/resources.tsx
index c171d75..1f8ec2c 100644
--- a/src/pages/resources.tsx
+++ b/src/pages/resources.tsx
@@ -1,12 +1,20 @@
+import { Link } from "gatsby"
import React, { Fragment } from "react"
+import { ResourcesList } from "../components/ResourcesList"
import { SEO } from "../components/SEO"
function ResourcesPage() {
return (
- the resources
+ Welcome to the TPH resources.
+
+ This is meant as a small knowledge base for commonly answered questions
+ on our Discord community,{" "}
+ The Programmer's Hangout.
+
+
)
}
diff --git a/src/utils/index.ts b/src/utils/index.ts
index a7a3fd2..0a9c680 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,4 +1,4 @@
-import { IFileOrFolder } from "../components/ResourcesSidebar/index"
+import { IFile, IFileOrFolder } from "../components/ResourcesSidebar/index"
export function traversePaths(
[head, ...tail]: string[],
@@ -22,3 +22,28 @@ export function traversePaths(
children: [traversePaths(tail, path)],
}
}
+
+export function traversePathsToFiles(
+ [head, ...tail]: string[],
+ basePath: string = "/resources",
+ depth: number = 0
+): IFileOrFolder {
+ const path = basePath + "/" + head + "/" + tail.join("/")
+
+ if (depth !== 0) {
+ // probably not more than one dot
+ const [name] = basePath.split(".")
+ return {
+ title: name,
+ type: "file",
+ path: basePath,
+ }
+ }
+
+ return {
+ title: head,
+ type: "folder",
+ path,
+ children: [traversePathsToFiles(tail, path, 1)],
+ }
+}
From fee748c67d2b53edb036d1a481a3accfc66c4a94 Mon Sep 17 00:00:00 2001
From: Jean-Philippe Sirois
Date: Tue, 17 Sep 2019 00:28:29 -0400
Subject: [PATCH 2/5] refact: extract duplicated File/Folder types
---
src/components/ResourcesList/index.tsx | 34 +------------------
src/components/ResourcesList/useBuildTree.tsx | 4 +--
src/components/ResourcesSidebar/index.tsx | 34 +------------------
.../ResourcesSidebar/useBuildTree.tsx | 4 +--
src/types/index.d.ts | 32 +++++++++++++++++
src/utils/index.ts | 2 +-
6 files changed, 39 insertions(+), 71 deletions(-)
create mode 100644 src/types/index.d.ts
diff --git a/src/components/ResourcesList/index.tsx b/src/components/ResourcesList/index.tsx
index 72ad9f6..7109ad1 100644
--- a/src/components/ResourcesList/index.tsx
+++ b/src/components/ResourcesList/index.tsx
@@ -1,42 +1,10 @@
import { graphql, useStaticQuery } from "gatsby"
import React, { memo } from "react"
import "react-perfect-scrollbar/dist/css/styles.css"
+import { IAllResourcesQuery, IFileOrFolder, IFolder } from "../../types"
import * as SC from "./styles"
import useBuildTree from "./useBuildTree"
-export interface IFile {
- title: string
- type: "file"
- path: string
-}
-
-export interface IFolder {
- title: string
- type: "folder"
- path: string
- children: IFileOrFolder[]
-}
-
-export type IFileOrFolder = IFile | IFolder
-
-export interface IFileQuery {
- node: {
- relativePath: string
- childMarkdownRemark: {
- frontmatter: {
- author: string
- date: string
- }
- }
- }
-}
-
-export interface IAllResourcesQuery {
- allFile: {
- edges: IFileQuery[]
- }
-}
-
const ALL_RESOURCES = graphql`
query {
allFile(filter: { sourceInstanceName: { eq: "resources" } }) {
diff --git a/src/components/ResourcesList/useBuildTree.tsx b/src/components/ResourcesList/useBuildTree.tsx
index 5adc513..8a26996 100644
--- a/src/components/ResourcesList/useBuildTree.tsx
+++ b/src/components/ResourcesList/useBuildTree.tsx
@@ -1,14 +1,14 @@
import chain from "ramda/es/chain"
import partition from "ramda/es/partition"
-import { traversePathsToFiles } from "../../utils"
import {
IAllResourcesQuery,
IFile,
IFileOrFolder,
IFileQuery,
IFolder,
-} from "./index"
+} from "../../types"
+import { traversePathsToFiles } from "../../utils"
function generateFolder({
title,
diff --git a/src/components/ResourcesSidebar/index.tsx b/src/components/ResourcesSidebar/index.tsx
index 0dca75c..75b82ad 100644
--- a/src/components/ResourcesSidebar/index.tsx
+++ b/src/components/ResourcesSidebar/index.tsx
@@ -4,44 +4,12 @@ import Scrollbar from "react-perfect-scrollbar"
import "react-perfect-scrollbar/dist/css/styles.css"
import TriangleDown from "../../icons/triangle-down.svg"
import Banner from "../../images/tph-banner.svg"
+import { IAllResourcesQuery, IFileOrFolder, IFolder } from "../../types"
import { ThemeToggler } from "../ThemeToggler"
import useSidebar from "./../../hooks/useSidebar"
import * as SC from "./styles"
import useBuildTree from "./useBuildTree"
-export interface IFile {
- title: string
- type: "file"
- path: string
-}
-
-export interface IFolder {
- title: string
- type: "folder"
- path: string
- children: IFileOrFolder[]
-}
-
-export type IFileOrFolder = IFile | IFolder
-
-export interface IFileQuery {
- node: {
- relativePath: string
- childMarkdownRemark: {
- frontmatter: {
- author: string
- date: string
- }
- }
- }
-}
-
-export interface IAllResourcesQuery {
- allFile: {
- edges: IFileQuery[]
- }
-}
-
const ALL_RESOURCES = graphql`
query {
allFile(filter: { sourceInstanceName: { eq: "resources" } }) {
diff --git a/src/components/ResourcesSidebar/useBuildTree.tsx b/src/components/ResourcesSidebar/useBuildTree.tsx
index b038b2f..0e0b01a 100644
--- a/src/components/ResourcesSidebar/useBuildTree.tsx
+++ b/src/components/ResourcesSidebar/useBuildTree.tsx
@@ -1,14 +1,14 @@
import chain from "ramda/es/chain"
import partition from "ramda/es/partition"
-import { traversePaths } from "../../utils"
import {
IAllResourcesQuery,
IFile,
IFileOrFolder,
IFileQuery,
IFolder,
-} from "./index"
+} from "../../types"
+import { traversePaths } from "../../utils"
function generateFolder({
title,
diff --git a/src/types/index.d.ts b/src/types/index.d.ts
new file mode 100644
index 0000000..5d1a69c
--- /dev/null
+++ b/src/types/index.d.ts
@@ -0,0 +1,32 @@
+export interface IFile {
+ title: string
+ type: "file"
+ path: string
+}
+
+export interface IFolder {
+ title: string
+ type: "folder"
+ path: string
+ children: IFileOrFolder[]
+}
+
+export type IFileOrFolder = IFile | IFolder
+
+export interface IFileQuery {
+ node: {
+ relativePath: string
+ childMarkdownRemark: {
+ frontmatter: {
+ author: string
+ date: string
+ }
+ }
+ }
+}
+
+export interface IAllResourcesQuery {
+ allFile: {
+ edges: IFileQuery[]
+ }
+}
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 0a9c680..3aced7c 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,4 +1,4 @@
-import { IFile, IFileOrFolder } from "../components/ResourcesSidebar/index"
+import { IFileOrFolder } from "../types"
export function traversePaths(
[head, ...tail]: string[],
From b6b4c9df61bbf71bfa1dcd3fc7f6b882e10f47be Mon Sep 17 00:00:00 2001
From: Jean-Philippe Sirois
Date: Tue, 17 Sep 2019 00:49:09 -0400
Subject: [PATCH 3/5] refact: extract resources helpers to utils
---
src/components/ResourcesList/useBuildTree.tsx | 70 +------------------
.../ResourcesSidebar/useBuildTree.tsx | 66 +----------------
src/utils/index.ts | 62 +++++++++++++++-
3 files changed, 65 insertions(+), 133 deletions(-)
diff --git a/src/components/ResourcesList/useBuildTree.tsx b/src/components/ResourcesList/useBuildTree.tsx
index 8a26996..f347827 100644
--- a/src/components/ResourcesList/useBuildTree.tsx
+++ b/src/components/ResourcesList/useBuildTree.tsx
@@ -1,71 +1,5 @@
-import chain from "ramda/es/chain"
-import partition from "ramda/es/partition"
-
-import {
- IAllResourcesQuery,
- IFile,
- IFileOrFolder,
- IFileQuery,
- IFolder,
-} from "../../types"
-import { traversePathsToFiles } from "../../utils"
-
-function generateFolder({
- title,
- path,
- targets,
-}: {
- title: IFolder["title"]
- path: IFile["path"]
- targets: IFolder[]
-}): IFolder {
- const children = join(chain(target => target.children, targets))
-
- return {
- title,
- type: "folder",
- path,
- children: children.sort((a, b) =>
- a.title.split("/").length > b.title.split("/").length
- ? -1
- : a.title.localeCompare(b.title)
- ),
- }
-}
-
-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] = 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)]
-}
+import { IAllResourcesQuery, IFileQuery } from "../../types"
+import { join, traversePathsToFiles } from "../../utils"
export default function useBuildTree(resources: IAllResourcesQuery) {
const objects = resources.allFile.edges.map(({ node: file }: IFileQuery) =>
diff --git a/src/components/ResourcesSidebar/useBuildTree.tsx b/src/components/ResourcesSidebar/useBuildTree.tsx
index 0e0b01a..0be532b 100644
--- a/src/components/ResourcesSidebar/useBuildTree.tsx
+++ b/src/components/ResourcesSidebar/useBuildTree.tsx
@@ -1,67 +1,5 @@
-import chain from "ramda/es/chain"
-import partition from "ramda/es/partition"
-
-import {
- IAllResourcesQuery,
- IFile,
- IFileOrFolder,
- IFileQuery,
- IFolder,
-} from "../../types"
-import { traversePaths } from "../../utils"
-
-function generateFolder({
- title,
- path,
- targets,
-}: {
- title: IFolder["title"]
- path: IFile["path"]
- targets: IFolder[]
-}): IFolder {
- const children = join(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] = 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)]
-}
+import { IAllResourcesQuery, IFileQuery } from "../../types"
+import { join, traversePaths } from "../../utils"
export default function useBuildTree(resources: IAllResourcesQuery) {
const objects = resources.allFile.edges.map(({ node: file }: IFileQuery) =>
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 3aced7c..0f12043 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,4 +1,7 @@
-import { IFileOrFolder } from "../types"
+import chain from "ramda/es/chain"
+import partition from "ramda/es/partition"
+
+import { IFile, IFileOrFolder, IFolder } from "../types"
export function traversePaths(
[head, ...tail]: string[],
@@ -47,3 +50,60 @@ export function traversePathsToFiles(
children: [traversePathsToFiles(tail, path, 1)],
}
}
+
+function generateFolder({
+ title,
+ path,
+ targets,
+}: {
+ title: IFolder["title"]
+ path: IFile["path"]
+ targets: IFolder[]
+}): IFolder {
+ const children = join(chain(target => target.children, targets))
+
+ return {
+ title,
+ type: "folder",
+ path,
+ children: children.sort((a, b) =>
+ a.title.split("/").length > b.title.split("/").length
+ ? -1
+ : a.title.localeCompare(b.title)
+ ),
+ }
+}
+
+function generateFile({
+ title,
+ path,
+}: {
+ title: IFile["title"]
+ path: IFile["path"]
+}): IFile {
+ return {
+ title,
+ type: "file",
+ path,
+ }
+}
+
+export function join([head, ...tail]: IFileOrFolder[]): IFileOrFolder[] {
+ if (!head) {
+ return []
+ }
+
+ const [similarFs, remaining] = 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)]
+}
From 94f8c5317d01feeb0a32cc32b6123fa9cc3ca4dd Mon Sep 17 00:00:00 2001
From: Jean-Philippe Sirois
Date: Tue, 17 Sep 2019 01:17:16 -0400
Subject: [PATCH 4/5] ui(resources): style the TPH link
---
src/components/ResourcesLink/index.tsx | 11 +++++++++++
src/components/ResourcesLink/styles.tsx | 16 ++++++++++++++++
src/pages/resources.tsx | 4 ++--
3 files changed, 29 insertions(+), 2 deletions(-)
create mode 100644 src/components/ResourcesLink/index.tsx
create mode 100644 src/components/ResourcesLink/styles.tsx
diff --git a/src/components/ResourcesLink/index.tsx b/src/components/ResourcesLink/index.tsx
new file mode 100644
index 0000000..671711e
--- /dev/null
+++ b/src/components/ResourcesLink/index.tsx
@@ -0,0 +1,11 @@
+import React, { PropsWithChildren } from "react"
+import * as SC from "./styles"
+
+export function ResourcesLink({
+ children,
+ to,
+}: PropsWithChildren<{
+ to: string
+}>) {
+ return {children}
+}
diff --git a/src/components/ResourcesLink/styles.tsx b/src/components/ResourcesLink/styles.tsx
new file mode 100644
index 0000000..11ddcaf
--- /dev/null
+++ b/src/components/ResourcesLink/styles.tsx
@@ -0,0 +1,16 @@
+import { Link } from "gatsby"
+import styled from "styled-components"
+
+export const ResourcesLinkWrapper = styled(Link)`
+ color: #0090d8;
+ font-weight: 700;
+ border-bottom: 2px solid;
+ text-decoration: none;
+ transition: color 0.3s;
+
+ &:hover,
+ &:focus {
+ color: #5dbbea;
+ transition: none;
+ }
+`
diff --git a/src/pages/resources.tsx b/src/pages/resources.tsx
index 1f8ec2c..ed723c7 100644
--- a/src/pages/resources.tsx
+++ b/src/pages/resources.tsx
@@ -1,6 +1,6 @@
-import { Link } from "gatsby"
import React, { Fragment } from "react"
+import { ResourcesLink } from "../components/ResourcesLink"
import { ResourcesList } from "../components/ResourcesList"
import { SEO } from "../components/SEO"
@@ -12,7 +12,7 @@ function ResourcesPage() {
This is meant as a small knowledge base for commonly answered questions
on our Discord community,{" "}
- The Programmer's Hangout.
+ The Programmer's Hangout .
From 568977a4ee3fb18e5fb957996ca35d2baa17ff4a Mon Sep 17 00:00:00 2001
From: Jean-Philippe Sirois
Date: Tue, 17 Sep 2019 01:47:38 -0400
Subject: [PATCH 5/5] content(resources): add link to GitHub
---
src/components/ResourcesLink/index.tsx | 12 +++++++++++-
src/components/ResourcesLink/styles.tsx | 12 ++++++++++--
src/pages/resources.tsx | 5 +++++
tsconfig.json | 3 ++-
typings.d.ts | 1 +
5 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/src/components/ResourcesLink/index.tsx b/src/components/ResourcesLink/index.tsx
index 671711e..60b4055 100644
--- a/src/components/ResourcesLink/index.tsx
+++ b/src/components/ResourcesLink/index.tsx
@@ -7,5 +7,15 @@ export function ResourcesLink({
}: PropsWithChildren<{
to: string
}>) {
- return {children}
+ if (!to.match(/^(https?:\/\/)/)) {
+ return (
+ {children}
+ )
+ }
+
+ return (
+
+ {children}
+
+ )
}
diff --git a/src/components/ResourcesLink/styles.tsx b/src/components/ResourcesLink/styles.tsx
index 11ddcaf..27a0eee 100644
--- a/src/components/ResourcesLink/styles.tsx
+++ b/src/components/ResourcesLink/styles.tsx
@@ -1,7 +1,7 @@
import { Link } from "gatsby"
-import styled from "styled-components"
+import styled, { css } from "styled-components"
-export const ResourcesLinkWrapper = styled(Link)`
+const linkStyle = css`
color: #0090d8;
font-weight: 700;
border-bottom: 2px solid;
@@ -14,3 +14,11 @@ export const ResourcesLinkWrapper = styled(Link)`
transition: none;
}
`
+
+export const ResourcesLinkInternal = styled(Link)`
+ ${linkStyle}
+`
+
+export const ResourcesLinkExternal = styled.a`
+ ${linkStyle}
+`
diff --git a/src/pages/resources.tsx b/src/pages/resources.tsx
index ed723c7..9b062e4 100644
--- a/src/pages/resources.tsx
+++ b/src/pages/resources.tsx
@@ -1,5 +1,6 @@
import React, { Fragment } from "react"
+import packageJson from "../../package.json"
import { ResourcesLink } from "../components/ResourcesLink"
import { ResourcesList } from "../components/ResourcesList"
import { SEO } from "../components/SEO"
@@ -14,6 +15,10 @@ function ResourcesPage() {
on our Discord community,{" "}
The Programmer's Hangout .
+
+ All of it is open source, and you can contribute to it on{" "}
+ GitHub .
+
)
diff --git a/tsconfig.json b/tsconfig.json
index 3565c9a..8249c01 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -46,7 +46,7 @@
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
- "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
@@ -59,5 +59,6 @@
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
+ "resolveJsonModule": true
}
}
diff --git a/typings.d.ts b/typings.d.ts
index 3a47d73..04494d2 100644
--- a/typings.d.ts
+++ b/typings.d.ts
@@ -3,6 +3,7 @@ import "styled-components"
declare module "*.svg"
declare module "*.png"
+declare module "*.json"
type ComponentQuery = {
readonly data: T