mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-04 09:15:58 +02:00
feat(archives): bootstrap what-is-archives from Github
This commit is contained in:
@@ -63,6 +63,14 @@ module.exports = {
|
|||||||
path: `${__dirname}/src/content/resources`,
|
path: `${__dirname}/src/content/resources`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
resolve: `gatsby-source-git`,
|
||||||
|
options: {
|
||||||
|
name: `what-is-archive`,
|
||||||
|
remote: `https://github.com/the-programmers-hangout/technology-spotlight`,
|
||||||
|
patterns: [`*.md`, `!README.md`],
|
||||||
|
},
|
||||||
|
},
|
||||||
`gatsby-transformer-sharp`,
|
`gatsby-transformer-sharp`,
|
||||||
`gatsby-plugin-react-svg`,
|
`gatsby-plugin-react-svg`,
|
||||||
`gatsby-plugin-sharp`,
|
`gatsby-plugin-sharp`,
|
||||||
|
|||||||
+55
-5
@@ -7,8 +7,21 @@ const fs = require("fs")
|
|||||||
const requiredArticleFrontmatter = ["authors", "date"]
|
const requiredArticleFrontmatter = ["authors", "date"]
|
||||||
|
|
||||||
const LAYOUT_RESOURCES = "resources"
|
const LAYOUT_RESOURCES = "resources"
|
||||||
|
const LAYOUT_ARCHIVES = "archives"
|
||||||
const LAYOUT_REGULAR = "regular"
|
const LAYOUT_REGULAR = "regular"
|
||||||
|
|
||||||
|
function resolveLayout(path) {
|
||||||
|
if (path.match(/resources/)) {
|
||||||
|
return LAYOUT_RESOURCES
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.match(/archives/)) {
|
||||||
|
return LAYOUT_ARCHIVES
|
||||||
|
}
|
||||||
|
|
||||||
|
return LAYOUT_REGULAR
|
||||||
|
}
|
||||||
|
|
||||||
let users = []
|
let users = []
|
||||||
try {
|
try {
|
||||||
users = JSON.parse(fs.readFileSync("./users.json", "utf-8"))
|
users = JSON.parse(fs.readFileSync("./users.json", "utf-8"))
|
||||||
@@ -38,6 +51,7 @@ const createResources = async ({ createPage, graphql }) => {
|
|||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
relativePath
|
relativePath
|
||||||
|
sourceInstanceName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,9 +74,43 @@ const createResources = async ({ createPage, graphql }) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createArchives = async ({ createPage, graphql }) => {
|
||||||
|
const archive = path.resolve(`src/templates/archive.tsx`)
|
||||||
|
|
||||||
|
const result = await graphql(`
|
||||||
|
query FetchArchives {
|
||||||
|
allFile(filter: { sourceInstanceName: { eq: "what-is-archive" } }) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
relativePath
|
||||||
|
sourceInstanceName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
if (result.errors) {
|
||||||
|
return Promise.reject(result.errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.data.allFile.edges.forEach(({ node }) => {
|
||||||
|
createPage({
|
||||||
|
path: path.join("archives", node.relativePath),
|
||||||
|
component: archive,
|
||||||
|
context: {
|
||||||
|
file: node.relativePath,
|
||||||
|
layout: LAYOUT_ARCHIVES,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
exports.onCreateNode = async ({ node, getNode, actions }) => {
|
exports.onCreateNode = async ({ node, getNode, actions }) => {
|
||||||
const { createPage, createNodeField } = actions
|
const { createPage, createNodeField } = actions
|
||||||
if (node.internal.type === "MarkdownRemark") {
|
// TODO: find a better way to avoid handling non-resources
|
||||||
|
// or better, attach authors to what-is archives
|
||||||
|
if (node.internal.type === "MarkdownRemark" && node.frontmatter.authors) {
|
||||||
const { frontmatter } = node
|
const { frontmatter } = node
|
||||||
const isDoc = Boolean(!frontmatter.path)
|
const isDoc = Boolean(!frontmatter.path)
|
||||||
|
|
||||||
@@ -91,13 +139,15 @@ exports.onCreateNode = async ({ node, getNode, actions }) => {
|
|||||||
exports.onCreatePage = ({ page, actions }) => {
|
exports.onCreatePage = ({ page, actions }) => {
|
||||||
const { createPage } = actions
|
const { createPage } = actions
|
||||||
|
|
||||||
page.context.layout = page.path.match(/resources/)
|
page.context.layout = resolveLayout(page.path)
|
||||||
? LAYOUT_RESOURCES
|
|
||||||
: LAYOUT_REGULAR
|
|
||||||
createPage(page)
|
createPage(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.createPages = ({ actions, graphql }) => {
|
exports.createPages = ({ actions, graphql }) => {
|
||||||
const { createPage } = actions
|
const { createPage } = actions
|
||||||
return createResources({ createPage, graphql })
|
|
||||||
|
return Promise.all([
|
||||||
|
createArchives({ createPage, graphql }),
|
||||||
|
createResources({ createPage, graphql }),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+95
-13
@@ -7770,7 +7770,8 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@@ -7791,12 +7792,14 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -7811,17 +7814,20 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
|
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -7938,7 +7944,8 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@@ -7950,6 +7957,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -7964,6 +7972,7 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@@ -7971,12 +7980,14 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
|
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@@ -7995,6 +8006,7 @@
|
|||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@@ -8075,7 +8087,8 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@@ -8087,6 +8100,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@@ -8172,7 +8186,8 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@@ -8208,6 +8223,7 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@@ -8227,6 +8243,7 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@@ -8270,12 +8287,14 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
|
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -9522,6 +9541,39 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"gatsby-source-git": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/gatsby-source-git/-/gatsby-source-git-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-TNCC8PnRK3knrO5Q9qpOWVsYuRuLZ07LGB2kQw4/b4bmbciVFZSNUfuJpokpl3/6DPvcePQtNjARVpdKrRYhog==",
|
||||||
|
"requires": {
|
||||||
|
"fast-glob": "^2.2.3",
|
||||||
|
"fs-extra": "^5.0.0",
|
||||||
|
"gatsby-source-filesystem": "^2.1.19",
|
||||||
|
"git-url-parse": "^11.1.1",
|
||||||
|
"rimraf": "^2.6.2",
|
||||||
|
"simple-git": "^1.105.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"fs-extra": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"jsonfile": "^4.0.0",
|
||||||
|
"universalify": "^0.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rimraf": {
|
||||||
|
"version": "2.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||||
|
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||||
|
"requires": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"gatsby-telemetry": {
|
"gatsby-telemetry": {
|
||||||
"version": "1.1.33",
|
"version": "1.1.33",
|
||||||
"resolved": "https://registry.npmjs.org/gatsby-telemetry/-/gatsby-telemetry-1.1.33.tgz",
|
"resolved": "https://registry.npmjs.org/gatsby-telemetry/-/gatsby-telemetry-1.1.33.tgz",
|
||||||
@@ -9821,6 +9873,14 @@
|
|||||||
"parse-url": "^5.0.0"
|
"parse-url": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"git-url-parse": {
|
||||||
|
"version": "11.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.1.2.tgz",
|
||||||
|
"integrity": "sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ==",
|
||||||
|
"requires": {
|
||||||
|
"git-up": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"github-from-package": {
|
"github-from-package": {
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||||
@@ -11061,12 +11121,14 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
|
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"is-fullwidth-code-point": {
|
"is-fullwidth-code-point": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"slice-ansi": {
|
"slice-ansi": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -11092,6 +11154,7 @@
|
|||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^4.1.0"
|
"ansi-regex": "^4.1.0"
|
||||||
}
|
}
|
||||||
@@ -16383,6 +16446,7 @@
|
|||||||
"version": "0.15.0",
|
"version": "0.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz",
|
||||||
"integrity": "sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==",
|
"integrity": "sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"object-assign": "^4.1.1"
|
"object-assign": "^4.1.1"
|
||||||
@@ -16757,6 +16821,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"simple-git": {
|
||||||
|
"version": "1.126.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.126.0.tgz",
|
||||||
|
"integrity": "sha512-47mqHxgZnN8XRa9HbpWprzUv3Ooqz9RY/LSZgvA7jCkW8jcwLahMz7LKugY91KZehfG0sCVPtgXiU72hd6b1Bw==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"simple-swizzle": {
|
"simple-swizzle": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
"gatsby-remark-auto-headers": "^1.0.3",
|
"gatsby-remark-auto-headers": "^1.0.3",
|
||||||
"gatsby-remark-katex": "^3.1.15",
|
"gatsby-remark-katex": "^3.1.15",
|
||||||
"gatsby-source-filesystem": "^2.1.33",
|
"gatsby-source-filesystem": "^2.1.33",
|
||||||
|
"gatsby-source-git": "^1.0.2",
|
||||||
"gatsby-transformer-remark": "^2.6.30",
|
"gatsby-transformer-remark": "^2.6.30",
|
||||||
"gatsby-transformer-sharp": "^2.3.0",
|
"gatsby-transformer-sharp": "^2.3.0",
|
||||||
"katex": "^0.11.1",
|
"katex": "^0.11.1",
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { graphql, useStaticQuery } from "gatsby"
|
||||||
|
import React, { FC, HTMLAttributes } from "react"
|
||||||
|
import { IAllArchivesQuery, IFileOrFolder } from "../../types"
|
||||||
|
import { humanize } from "../../utils"
|
||||||
|
import { ColumnSidebar } from "../ColumnSidebar"
|
||||||
|
import useBuildTree from "./../../hooks/useBuildTree"
|
||||||
|
import * as SC from "./styles"
|
||||||
|
|
||||||
|
const ALL_ARCHIVES = graphql`
|
||||||
|
query {
|
||||||
|
allFile(filter: { sourceInstanceName: { eq: "what-is-archive" } }) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
relativePath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
function plantTree(item: IFileOrFolder) {
|
||||||
|
return (
|
||||||
|
<SC.PageLink key={item.title} to={item.path} activeClassName="active">
|
||||||
|
{humanize(item.title)}
|
||||||
|
</SC.PageLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ArchivesSidebar: FC<HTMLAttributes<HTMLDivElement>> = props => {
|
||||||
|
const archives = useStaticQuery<IAllArchivesQuery>(ALL_ARCHIVES)
|
||||||
|
const tree = useBuildTree(archives, "/archives")
|
||||||
|
const sortedTree = tree.sort((a, b) => a.title.localeCompare(b.title))
|
||||||
|
|
||||||
|
return <ColumnSidebar {...props}>{sortedTree.map(plantTree)}</ColumnSidebar>
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Link } from "gatsby"
|
||||||
|
import { transparentize } from "polished"
|
||||||
|
import styled from "styled-components"
|
||||||
|
|
||||||
|
export const PageLink = styled(Link)`
|
||||||
|
display: block;
|
||||||
|
padding: 4px 0 0;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
color: ${props => props.theme.sidebar.foreground};
|
||||||
|
align-self: flex-start;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: ${props =>
|
||||||
|
transparentize(0.7, props.theme.sidebar.foreground)};
|
||||||
|
}
|
||||||
|
|
||||||
|
& + & {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
font-weight: 700;
|
||||||
|
color: ${props => props.theme.sidebar.active};
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active:hover {
|
||||||
|
border-color: ${props => transparentize(0.7, props.theme.sidebar.active)};
|
||||||
|
}
|
||||||
|
`
|
||||||
@@ -9,8 +9,9 @@ interface ILinkProps {
|
|||||||
item: IFileOrFolder
|
item: IFileOrFolder
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IResourceBreadcrumbProps {
|
interface IBreadcrumbProps {
|
||||||
relativePath: any
|
relativePath: any
|
||||||
|
basePath: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Link: FC<ILinkProps> = ({ item }) => {
|
const Link: FC<ILinkProps> = ({ item }) => {
|
||||||
@@ -28,12 +29,12 @@ function flatten([
|
|||||||
return flatten([...currNode.children, ...previousNodes, currNode])
|
return flatten([...currNode.children, ...previousNodes, currNode])
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ResourceBreadcrumb({ relativePath }: IResourceBreadcrumbProps) {
|
export function Breadcrumb({ relativePath, basePath }: IBreadcrumbProps) {
|
||||||
const paths = relativePath.split("/")
|
const paths = relativePath.split("/")
|
||||||
const breadcrumbItems = flatten([traversePaths(paths)])
|
const breadcrumbItems = flatten([traversePaths(paths, basePath)])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SC.ResourceBreadcrumbWrapper>
|
<SC.BreadcrumbWrapper>
|
||||||
<SC.LinkWrapper>
|
<SC.LinkWrapper>
|
||||||
<Link
|
<Link
|
||||||
item={{ path: "/", title: "home", type: "folder", children: [] }}
|
item={{ path: "/", title: "home", type: "folder", children: [] }}
|
||||||
@@ -43,8 +44,8 @@ export function ResourceBreadcrumb({ relativePath }: IResourceBreadcrumbProps) {
|
|||||||
<SC.LinkWrapper>
|
<SC.LinkWrapper>
|
||||||
<Link
|
<Link
|
||||||
item={{
|
item={{
|
||||||
path: "/resources",
|
path: basePath,
|
||||||
title: "resources",
|
title: basePath.replace(/\//, ""),
|
||||||
type: "folder",
|
type: "folder",
|
||||||
children: [],
|
children: [],
|
||||||
}}
|
}}
|
||||||
@@ -67,6 +68,6 @@ export function ResourceBreadcrumb({ relativePath }: IResourceBreadcrumbProps) {
|
|||||||
</SC.CurrentPage>
|
</SC.CurrentPage>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</SC.ResourceBreadcrumbWrapper>
|
</SC.BreadcrumbWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ import { Link } from "gatsby"
|
|||||||
import { darken, lighten } from "polished"
|
import { darken, lighten } from "polished"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
|
|
||||||
export const ResourceBreadcrumbWrapper = styled.div`
|
export const BreadcrumbWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
import React, { FC, Fragment } from "react"
|
import React, { FC, Fragment } from "react"
|
||||||
|
|
||||||
import ChevronUp from "../../icons/chevron-up.svg"
|
import ChevronUp from "../../icons/chevron-up.svg"
|
||||||
import { ResourceBreadcrumb } from "../ResourceBreadcrumb"
|
import { Breadcrumb } from "../Breadcrumb"
|
||||||
import { StackedAvatars } from "../StackedAvatars"
|
import { StackedAvatars } from "../StackedAvatars"
|
||||||
import * as SC from "./styles"
|
import * as SC from "./styles"
|
||||||
|
|
||||||
interface IResourceHeaderProps {
|
interface IColumnHeaderProps {
|
||||||
relativePath: string
|
relativePath: string
|
||||||
|
basePath: string
|
||||||
title: string
|
title: string
|
||||||
authors: Array<{
|
authors?: Array<{
|
||||||
avatar: string
|
avatar: string
|
||||||
hash: string
|
hash: string
|
||||||
name: string
|
name: string
|
||||||
}>
|
}>
|
||||||
createdAt: string
|
createdAt: string
|
||||||
timeToRead: number
|
timeToRead: number
|
||||||
recommendedReading: string[]
|
recommendedReading?: string[]
|
||||||
externalResources: string[]
|
externalResources?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function ExtraLink({
|
function ExtraLink({
|
||||||
@@ -47,7 +48,8 @@ function ExtraLink({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ResourceHeader: FC<IResourceHeaderProps> = ({
|
export const ColumnHeader: FC<IColumnHeaderProps> = ({
|
||||||
|
basePath,
|
||||||
relativePath,
|
relativePath,
|
||||||
title,
|
title,
|
||||||
authors,
|
authors,
|
||||||
@@ -63,24 +65,26 @@ export const ResourceHeader: FC<IResourceHeaderProps> = ({
|
|||||||
const dateToHuman = `${month} ${day}, ${year}`
|
const dateToHuman = `${month} ${day}, ${year}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SC.ResourceHeaderWrapper>
|
<SC.ColumnHeaderWrapper>
|
||||||
<ResourceBreadcrumb relativePath={relativePath} />
|
<Breadcrumb relativePath={relativePath} basePath={basePath} />
|
||||||
|
|
||||||
<SC.Title>{title}</SC.Title>
|
<SC.Title>{title}</SC.Title>
|
||||||
|
|
||||||
<SC.Top>
|
<SC.Top>
|
||||||
<SC.Meta>
|
{authors && (
|
||||||
<StackedAvatars authors={authors} />
|
<SC.Meta>
|
||||||
<SC.PopoverToggler>
|
<StackedAvatars authors={authors} />
|
||||||
{authors.length} contributor{authors.length > 1 && "s"}
|
<SC.PopoverToggler>
|
||||||
<SC.Popover>
|
{authors.length} contributor{authors.length > 1 && "s"}
|
||||||
{authors
|
<SC.Popover>
|
||||||
.map(author => `${author.name}#${author.hash}`)
|
{authors
|
||||||
.join(", ")}
|
.map(author => `${author.name}#${author.hash}`)
|
||||||
</SC.Popover>
|
.join(", ")}
|
||||||
</SC.PopoverToggler>
|
</SC.Popover>
|
||||||
</SC.Meta>
|
</SC.PopoverToggler>
|
||||||
<SC.Meta>{dateToHuman}</SC.Meta>
|
</SC.Meta>
|
||||||
|
)}
|
||||||
|
{dateToHuman && <SC.Meta>{dateToHuman}</SC.Meta>}
|
||||||
<SC.Meta>
|
<SC.Meta>
|
||||||
{timeToRead} minute{timeToRead !== 1 && "s"} read time
|
{timeToRead} minute{timeToRead !== 1 && "s"} read time
|
||||||
</SC.Meta>
|
</SC.Meta>
|
||||||
@@ -103,6 +107,6 @@ export const ResourceHeader: FC<IResourceHeaderProps> = ({
|
|||||||
})}
|
})}
|
||||||
</SC.ExternalResources>
|
</SC.ExternalResources>
|
||||||
)}
|
)}
|
||||||
</SC.ResourceHeaderWrapper>
|
</SC.ColumnHeaderWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ import { darken, lighten } from "polished"
|
|||||||
import styled, { css } from "styled-components"
|
import styled, { css } from "styled-components"
|
||||||
import { fontFamily, modularScale } from "../../design/typography"
|
import { fontFamily, modularScale } from "../../design/typography"
|
||||||
|
|
||||||
export const ResourceHeaderWrapper = styled.div`
|
export const ColumnHeaderWrapper = styled.div`
|
||||||
border-bottom: 1px solid #dbdbdb;
|
border-bottom: 1px solid #dbdbdb;
|
||||||
padding-bottom: 32px;
|
padding-bottom: 32px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import React, { FC } from "react"
|
||||||
|
import * as SC from "./styles"
|
||||||
|
|
||||||
|
interface IColumnLinkProps {
|
||||||
|
to: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ColumnLink: FC<IColumnLinkProps> = ({ children, to }) => {
|
||||||
|
if (!to.match(/^(https?:\/\/)/)) {
|
||||||
|
return <SC.ColumnLinkInternal to={to}>{children}</SC.ColumnLinkInternal>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SC.ColumnLinkExternal href={to} target="_blank">
|
||||||
|
{children}
|
||||||
|
</SC.ColumnLinkExternal>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -15,10 +15,10 @@ const linkStyle = css`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const ResourcesLinkInternal = styled(Link)`
|
export const ColumnLinkInternal = styled(Link)`
|
||||||
${linkStyle}
|
${linkStyle}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const ResourcesLinkExternal = styled.a`
|
export const ColumnLinkExternal = styled.a`
|
||||||
${linkStyle}
|
${linkStyle}
|
||||||
`
|
`
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { Link } from "gatsby"
|
||||||
|
import React, { FC, HTMLAttributes, PropsWithChildren } from "react"
|
||||||
|
import Scrollbar from "react-perfect-scrollbar"
|
||||||
|
import "react-perfect-scrollbar/dist/css/styles.css"
|
||||||
|
import Banner from "../../images/tph-banner.svg"
|
||||||
|
import { ThemeToggler } from "../ThemeToggler"
|
||||||
|
import * as SC from "./styles"
|
||||||
|
|
||||||
|
interface IMenuItemProps {
|
||||||
|
to: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const MenuItem: FC<IMenuItemProps> = ({ children, to }) => {
|
||||||
|
return (
|
||||||
|
<SC.MenuItem to={to} activeClassName="active">
|
||||||
|
{children}
|
||||||
|
</SC.MenuItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ColumnSidebar: FC<
|
||||||
|
PropsWithChildren<HTMLAttributes<HTMLDivElement>>
|
||||||
|
> = props => {
|
||||||
|
const { children, ...restProps } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SC.ColumnSidebarWrapper {...restProps}>
|
||||||
|
<Scrollbar>
|
||||||
|
<Link to="/">
|
||||||
|
<Banner />
|
||||||
|
</Link>
|
||||||
|
<SC.Inner>
|
||||||
|
{children}
|
||||||
|
|
||||||
|
<SC.Menu>
|
||||||
|
<MenuItem to="/about">about</MenuItem>
|
||||||
|
<MenuItem to="/rules">rules</MenuItem>
|
||||||
|
<MenuItem to="/faq">faq</MenuItem>
|
||||||
|
<MenuItem to="/">hotbot</MenuItem>
|
||||||
|
<MenuItem to="/resources">resources</MenuItem>
|
||||||
|
<MenuItem to="/archives">tech spotlights</MenuItem>
|
||||||
|
</SC.Menu>
|
||||||
|
|
||||||
|
<ThemeToggler />
|
||||||
|
</SC.Inner>
|
||||||
|
</Scrollbar>
|
||||||
|
</SC.ColumnSidebarWrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { Link } from "gatsby"
|
||||||
|
import styled from "styled-components"
|
||||||
|
|
||||||
|
export const ColumnSidebarWrapper = styled.div`
|
||||||
|
box-sizing: border-box;
|
||||||
|
flex: 0 0 320px;
|
||||||
|
background: ${props => props.theme.sidebar.background};
|
||||||
|
color: ${props => props.theme.sidebar.foreground};
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 320px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
z-index: 100;
|
||||||
|
width: auto;
|
||||||
|
/* TODO: maybe find a less "awkward" way to animate this */
|
||||||
|
left: calc(-100% - 100px);
|
||||||
|
right: calc(100% - 0px);
|
||||||
|
transition: left 0.3s, right 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-open {
|
||||||
|
left: 0;
|
||||||
|
right: 100px;
|
||||||
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export const Inner = styled.div`
|
||||||
|
padding: 30px 0 30px 20px;
|
||||||
|
`
|
||||||
|
|
||||||
|
export const Menu = styled.nav`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-top: 1px dashed #a5a5a5;
|
||||||
|
margin: 20px 0 40px;
|
||||||
|
padding-top: 20px;
|
||||||
|
`
|
||||||
|
|
||||||
|
export const MenuItem = styled(Link)`
|
||||||
|
padding: 4px 0;
|
||||||
|
font-size: 20px;
|
||||||
|
color: ${props => props.theme.sidebar.foreground};
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
`
|
||||||
@@ -86,7 +86,7 @@ export const Header: FC<IHeaderProps> = ({ isHome }) => {
|
|||||||
<MenuItem to="/">faq</MenuItem>
|
<MenuItem to="/">faq</MenuItem>
|
||||||
<MenuItem to="/">hotbot</MenuItem>
|
<MenuItem to="/">hotbot</MenuItem>
|
||||||
<MenuItem to="/resources">resources</MenuItem>
|
<MenuItem to="/resources">resources</MenuItem>
|
||||||
<MenuItem to="/">tech spotlight</MenuItem>
|
<MenuItem to="/archives">tech spotlights</MenuItem>
|
||||||
</SC.Menu>
|
</SC.Menu>
|
||||||
<DiscordButton>join us</DiscordButton>
|
<DiscordButton>join us</DiscordButton>
|
||||||
{isHome && <Partner />}
|
{isHome && <Partner />}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
import React, { FC } from "react"
|
|
||||||
import * as SC from "./styles"
|
|
||||||
|
|
||||||
interface IResourcesLinkProps {
|
|
||||||
to: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ResourcesLink: FC<IResourcesLinkProps> = ({ children, to }) => {
|
|
||||||
if (!to.match(/^(https?:\/\/)/)) {
|
|
||||||
return (
|
|
||||||
<SC.ResourcesLinkInternal to={to}>{children}</SC.ResourcesLinkInternal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SC.ResourcesLinkExternal href={to} target="_blank">
|
|
||||||
{children}
|
|
||||||
</SC.ResourcesLinkExternal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ import { join, traversePathsToFiles } from "../../utils"
|
|||||||
|
|
||||||
export default function useBuildTree(resources: IAllResourcesQuery) {
|
export default function useBuildTree(resources: IAllResourcesQuery) {
|
||||||
const objects = resources.allFile.edges.map(({ node: file }: IFileQuery) =>
|
const objects = resources.allFile.edges.map(({ node: file }: IFileQuery) =>
|
||||||
traversePathsToFiles(file.relativePath.split("/"))
|
traversePathsToFiles(file.relativePath.split("/"), "/resources")
|
||||||
)
|
)
|
||||||
|
|
||||||
return join(objects)
|
return join(objects)
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import { graphql, Link, useStaticQuery } from "gatsby"
|
import { graphql, useStaticQuery } from "gatsby"
|
||||||
import React, { FC, HTMLAttributes, memo, useState } from "react"
|
import React, { FC, HTMLAttributes, memo, useState } from "react"
|
||||||
import Scrollbar from "react-perfect-scrollbar"
|
|
||||||
import "react-perfect-scrollbar/dist/css/styles.css"
|
|
||||||
import TriangleDown from "../../icons/triangle-down.svg"
|
import TriangleDown from "../../icons/triangle-down.svg"
|
||||||
import Banner from "../../images/tph-banner.svg"
|
|
||||||
import { IAllResourcesQuery, IFileOrFolder, IFolder } from "../../types"
|
import { IAllResourcesQuery, IFileOrFolder, IFolder } from "../../types"
|
||||||
import { humanize } from "../../utils"
|
import { humanize } from "../../utils"
|
||||||
import { ThemeToggler } from "../ThemeToggler"
|
import { ColumnSidebar } from "../ColumnSidebar"
|
||||||
|
import useBuildTree from "./../../hooks/useBuildTree"
|
||||||
import useSidebar from "./../../hooks/useSidebar"
|
import useSidebar from "./../../hooks/useSidebar"
|
||||||
import * as SC from "./styles"
|
import * as SC from "./styles"
|
||||||
import useBuildTree from "./useBuildTree"
|
|
||||||
import useMatchingPath from "./useMatchingPath"
|
import useMatchingPath from "./useMatchingPath"
|
||||||
|
|
||||||
const ALL_RESOURCES = graphql`
|
const ALL_RESOURCES = graphql`
|
||||||
@@ -93,44 +90,14 @@ const FirstLevelFolder = memo(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
interface IMenuItemProps {
|
|
||||||
to: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const MenuItem: FC<IMenuItemProps> = ({ children, to }) => {
|
|
||||||
return (
|
|
||||||
<SC.MenuItem to={to} activeClassName="active">
|
|
||||||
{children}
|
|
||||||
</SC.MenuItem>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ResourcesSidebar: FC<HTMLAttributes<HTMLDivElement>> = props => {
|
export const ResourcesSidebar: FC<HTMLAttributes<HTMLDivElement>> = props => {
|
||||||
const resources = useStaticQuery<IAllResourcesQuery>(ALL_RESOURCES)
|
const resources = useStaticQuery<IAllResourcesQuery>(ALL_RESOURCES)
|
||||||
const tree = useBuildTree(resources)
|
const tree = useBuildTree(resources, "/resources")
|
||||||
const sortedTree = tree.sort((a, b) => a.title.localeCompare(b.title))
|
const sortedTree = tree.sort((a, b) => a.title.localeCompare(b.title))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SC.ResourcesSidebarWrapper {...props}>
|
<ColumnSidebar {...props}>
|
||||||
<Scrollbar>
|
{sortedTree.map((node, index) => plantTree(node, index, true))}
|
||||||
<Link to="/">
|
</ColumnSidebar>
|
||||||
<Banner />
|
|
||||||
</Link>
|
|
||||||
<SC.Inner>
|
|
||||||
{sortedTree.map((node, index) => plantTree(node, index, true))}
|
|
||||||
|
|
||||||
<SC.Menu>
|
|
||||||
<MenuItem to="/about">about</MenuItem>
|
|
||||||
<MenuItem to="/rules">rules</MenuItem>
|
|
||||||
<MenuItem to="/faq">faq</MenuItem>
|
|
||||||
<MenuItem to="/">hotbot</MenuItem>
|
|
||||||
<MenuItem to="/resources">resources</MenuItem>
|
|
||||||
<MenuItem to="/">tech</MenuItem>
|
|
||||||
</SC.Menu>
|
|
||||||
|
|
||||||
<ThemeToggler />
|
|
||||||
</SC.Inner>
|
|
||||||
</Scrollbar>
|
|
||||||
</SC.ResourcesSidebarWrapper>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,32 +3,6 @@ import { transparentize } from "polished"
|
|||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import ChevronUp from "../../icons/chevron-up.svg"
|
import ChevronUp from "../../icons/chevron-up.svg"
|
||||||
|
|
||||||
export const ResourcesSidebarWrapper = styled.div`
|
|
||||||
box-sizing: border-box;
|
|
||||||
flex: 0 0 320px;
|
|
||||||
background: ${props => props.theme.sidebar.background};
|
|
||||||
color: ${props => props.theme.sidebar.foreground};
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 320px;
|
|
||||||
|
|
||||||
@media screen and (max-width: 767px) {
|
|
||||||
z-index: 100;
|
|
||||||
width: auto;
|
|
||||||
/* TODO: maybe find a less "awkward" way to animate this */
|
|
||||||
left: calc(-100% - 100px);
|
|
||||||
right: calc(100% - 0px);
|
|
||||||
transition: left 0.3s, right 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-open {
|
|
||||||
left: 0;
|
|
||||||
right: 100px;
|
|
||||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export const Children = styled.div`
|
export const Children = styled.div`
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
@@ -131,10 +105,6 @@ export const TreeWrapper = styled.div<{ collapsed: boolean }>`
|
|||||||
|
|
||||||
export const CollapseToggler = styled(ChevronUp)``
|
export const CollapseToggler = styled(ChevronUp)``
|
||||||
|
|
||||||
export const Inner = styled.div`
|
|
||||||
padding: 30px 0 30px 20px;
|
|
||||||
`
|
|
||||||
|
|
||||||
export const PageLink = styled(Link)`
|
export const PageLink = styled(Link)`
|
||||||
display: block;
|
display: block;
|
||||||
padding: 4px 0 0;
|
padding: 4px 0 0;
|
||||||
@@ -162,27 +132,3 @@ export const PageLink = styled(Link)`
|
|||||||
border-color: ${props => transparentize(0.7, props.theme.sidebar.active)};
|
border-color: ${props => transparentize(0.7, props.theme.sidebar.active)};
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const Menu = styled.nav`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
border-top: 1px dashed #a5a5a5;
|
|
||||||
margin: 20px 0 40px;
|
|
||||||
padding-top: 20px;
|
|
||||||
`
|
|
||||||
|
|
||||||
export const MenuItem = styled(Link)`
|
|
||||||
padding: 4px 0;
|
|
||||||
font-size: 20px;
|
|
||||||
color: ${props => props.theme.sidebar.foreground};
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:active {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
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) =>
|
|
||||||
traversePaths(file.relativePath.split("/"))
|
|
||||||
)
|
|
||||||
|
|
||||||
return join(objects)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { IAllFilesQuery, IFileQuery } from "../types"
|
||||||
|
import { join, traversePaths } from "../utils"
|
||||||
|
|
||||||
|
export default function useBuildTree(
|
||||||
|
resources: IAllFilesQuery,
|
||||||
|
basePath: string
|
||||||
|
) {
|
||||||
|
const objects = resources.allFile.edges.map(({ node: file }: IFileQuery) =>
|
||||||
|
traversePaths(file.relativePath.split("/"), basePath)
|
||||||
|
)
|
||||||
|
|
||||||
|
return join(objects)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import React, { FC } from "react"
|
||||||
|
|
||||||
|
import { ArchivesSidebar } from "../../components/ArchivesSidebar"
|
||||||
|
import { ColumnLayout } from "../ColumnLayout"
|
||||||
|
|
||||||
|
export const ArchivesLayout: FC = ({ children }) => {
|
||||||
|
return <ColumnLayout sidebar={ArchivesSidebar} content={children} />
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import React, { FC, useMemo, useState } from "react"
|
||||||
|
|
||||||
|
import { ColumnSidebar } from "../../components/ColumnSidebar"
|
||||||
|
import { MobileHeader } from "../../components/MobileHeader"
|
||||||
|
import { GlobalStyles } from "../../globalStyles"
|
||||||
|
import { useLockBodyScroll } from "../../hooks/useLockBodyScroll"
|
||||||
|
import { SidebarProvider } from "../../SidebarProvider"
|
||||||
|
import { ThemeProvider } from "../../ThemeProvider"
|
||||||
|
import * as SC from "./styles"
|
||||||
|
|
||||||
|
interface IColumnLayoutProps {
|
||||||
|
sidebar: React.ReactNode
|
||||||
|
content: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ColumnLayout: FC<IColumnLayoutProps> = ({ sidebar, content }) => {
|
||||||
|
const [activeMobileMenu, setActiveMobileMenu] = useState(false)
|
||||||
|
const { lock, unlock } = useLockBodyScroll()
|
||||||
|
|
||||||
|
function openMenu() {
|
||||||
|
setActiveMobileMenu(true)
|
||||||
|
lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeMenu() {
|
||||||
|
setActiveMobileMenu(false)
|
||||||
|
unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider>
|
||||||
|
<SidebarProvider>
|
||||||
|
<GlobalStyles />
|
||||||
|
<SC.Main>
|
||||||
|
<MobileHeader openMenu={openMenu} />
|
||||||
|
{sidebar({ className: activeMobileMenu ? "is-open" : "" })}
|
||||||
|
<SC.MainContent>
|
||||||
|
<SC.Container>{content}</SC.Container>
|
||||||
|
</SC.MainContent>
|
||||||
|
</SC.Main>
|
||||||
|
<SC.Overlay
|
||||||
|
className={activeMobileMenu ? "is-open" : ""}
|
||||||
|
onClick={closeMenu}
|
||||||
|
/>
|
||||||
|
</SidebarProvider>
|
||||||
|
</ThemeProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,10 +1,3 @@
|
|||||||
/**
|
|
||||||
* Layout component that queries for data
|
|
||||||
* with Gatsby's useStaticQuery component
|
|
||||||
*
|
|
||||||
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { RouteComponentProps } from "@reach/router"
|
import { RouteComponentProps } from "@reach/router"
|
||||||
import React, { FC, Fragment, useEffect } from "react"
|
import React, { FC, Fragment, useEffect } from "react"
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +1,8 @@
|
|||||||
/**
|
import React, { FC } from "react"
|
||||||
* Layout component that queries for data
|
|
||||||
* with Gatsby's useStaticQuery component
|
|
||||||
*
|
|
||||||
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React, { FC, useState } from "react"
|
|
||||||
|
|
||||||
import { MobileHeader } from "../../components/MobileHeader"
|
|
||||||
import { ResourcesSidebar } from "../../components/ResourcesSidebar"
|
import { ResourcesSidebar } from "../../components/ResourcesSidebar"
|
||||||
import { GlobalStyles } from "../../globalStyles"
|
import { ColumnLayout } from "../ColumnLayout"
|
||||||
import { useLockBodyScroll } from "../../hooks/useLockBodyScroll"
|
|
||||||
import { SidebarProvider } from "../../SidebarProvider"
|
|
||||||
import { ThemeProvider } from "../../ThemeProvider"
|
|
||||||
import * as SC from "./styles"
|
|
||||||
|
|
||||||
export const ResourcesLayout: FC = ({ children }) => {
|
export const ResourcesLayout: FC = ({ children }) => {
|
||||||
const [activeMobileMenu, setActiveMobileMenu] = useState(false)
|
return <ColumnLayout sidebar={ResourcesSidebar} content={children} />
|
||||||
const { lock, unlock } = useLockBodyScroll()
|
|
||||||
|
|
||||||
function openMenu() {
|
|
||||||
setActiveMobileMenu(true)
|
|
||||||
lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeMenu() {
|
|
||||||
setActiveMobileMenu(false)
|
|
||||||
unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ThemeProvider>
|
|
||||||
<SidebarProvider>
|
|
||||||
<GlobalStyles />
|
|
||||||
<SC.Main>
|
|
||||||
<MobileHeader openMenu={openMenu} />
|
|
||||||
<ResourcesSidebar className={activeMobileMenu ? "is-open" : ""} />
|
|
||||||
<SC.MainContent>
|
|
||||||
<SC.Container>{children}</SC.Container>
|
|
||||||
</SC.MainContent>
|
|
||||||
</SC.Main>
|
|
||||||
<SC.Overlay
|
|
||||||
className={activeMobileMenu ? "is-open" : ""}
|
|
||||||
onClick={closeMenu}
|
|
||||||
/>
|
|
||||||
</SidebarProvider>
|
|
||||||
</ThemeProvider>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-6
@@ -1,6 +1,7 @@
|
|||||||
import { WindowLocation } from "@reach/router"
|
import { WindowLocation } from "@reach/router"
|
||||||
import React, { PropsWithChildren } from "react"
|
import React, { PropsWithChildren, useMemo } from "react"
|
||||||
import { LocationProvider } from "../LocationProvider"
|
import { LocationProvider } from "../LocationProvider"
|
||||||
|
import { ArchivesLayout } from "./ArchivesLayout"
|
||||||
import { Layout } from "./Layout"
|
import { Layout } from "./Layout"
|
||||||
import { ResourcesLayout } from "./ResourcesLayout"
|
import { ResourcesLayout } from "./ResourcesLayout"
|
||||||
|
|
||||||
@@ -14,13 +15,20 @@ export default function BaseLayout({
|
|||||||
}
|
}
|
||||||
location: WindowLocation
|
location: WindowLocation
|
||||||
}>) {
|
}>) {
|
||||||
|
const ResolvedLayout = useMemo(() => {
|
||||||
|
switch (pageContext.layout) {
|
||||||
|
case "resources":
|
||||||
|
return ResourcesLayout
|
||||||
|
case "archives":
|
||||||
|
return ArchivesLayout
|
||||||
|
default:
|
||||||
|
return Layout
|
||||||
|
}
|
||||||
|
}, [pageContext.layout])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LocationProvider location={location}>
|
<LocationProvider location={location}>
|
||||||
{pageContext.layout === "resources" ? (
|
<ResolvedLayout>{children}</ResolvedLayout>
|
||||||
<ResourcesLayout>{children}</ResourcesLayout>
|
|
||||||
) : (
|
|
||||||
<Layout>{children}</Layout>
|
|
||||||
)}
|
|
||||||
</LocationProvider>
|
</LocationProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import React, { Fragment } from "react"
|
||||||
|
|
||||||
|
import { ColumnLink } from "../components/ColumnLink"
|
||||||
|
import { SEO } from "../components/SEO"
|
||||||
|
|
||||||
|
function ResourcesPage() {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<SEO title="Tech Spotlights Archives" />
|
||||||
|
<p>Welcome to the TPH tech spotlights archives.</p>
|
||||||
|
<p>
|
||||||
|
This regroups the archives of our occasional, temporary channels that
|
||||||
|
cover a piece of technology that might be unknown to part of our users.
|
||||||
|
You can find those on{" "}
|
||||||
|
<ColumnLink to="/about">The Programmer's Hangout</ColumnLink>.
|
||||||
|
</p>
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ResourcesPage
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { Fragment } from "react"
|
import React, { Fragment } from "react"
|
||||||
|
|
||||||
import packageJson from "../../package.json"
|
import packageJson from "../../package.json"
|
||||||
import { ResourcesLink } from "../components/ResourcesLink"
|
import { ColumnLink } from "../components/ColumnLink"
|
||||||
import { ResourcesList } from "../components/ResourcesList"
|
import { ResourcesList } from "../components/ResourcesList"
|
||||||
import { SEO } from "../components/SEO"
|
import { SEO } from "../components/SEO"
|
||||||
|
|
||||||
@@ -13,11 +13,11 @@ function ResourcesPage() {
|
|||||||
<p>
|
<p>
|
||||||
This is meant as a small knowledge base for commonly answered questions
|
This is meant as a small knowledge base for commonly answered questions
|
||||||
on our Discord community,{" "}
|
on our Discord community,{" "}
|
||||||
<ResourcesLink to="/about">The Programmer's Hangout</ResourcesLink>.
|
<ColumnLink to="/about">The Programmer's Hangout</ColumnLink>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
All of it is open source, and you can contribute to it on{" "}
|
All of it is open source, and you can contribute to it on{" "}
|
||||||
<ResourcesLink to={packageJson.repository.url}>GitHub</ResourcesLink>.
|
<ColumnLink to={packageJson.repository.url}>GitHub</ColumnLink>.
|
||||||
</p>
|
</p>
|
||||||
<ResourcesList />
|
<ResourcesList />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { graphql } from "gatsby"
|
||||||
|
import React, { FC, Fragment } from "react"
|
||||||
|
import { ColumnHeader } from "../components/ColumnHeader"
|
||||||
|
import { Markdown } from "../components/Markdown"
|
||||||
|
import { SEO } from "../components/SEO"
|
||||||
|
import { humanize } from "../utils"
|
||||||
|
|
||||||
|
// @todo maybe find alternative type for data
|
||||||
|
const Archive: FC<any> = ({ data }) => {
|
||||||
|
const { relativePath, ctime } = data.file
|
||||||
|
const { html, excerpt, timeToRead } = data.file.post
|
||||||
|
|
||||||
|
const title = humanize(relativePath)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<SEO title={title} description={excerpt} />
|
||||||
|
<ColumnHeader
|
||||||
|
relativePath={relativePath}
|
||||||
|
basePath="/archives"
|
||||||
|
title={title}
|
||||||
|
createdAt={ctime}
|
||||||
|
timeToRead={timeToRead}
|
||||||
|
/>
|
||||||
|
<Markdown content={html} />
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Archive
|
||||||
|
|
||||||
|
export const query = graphql`
|
||||||
|
query Archive($file: String!) {
|
||||||
|
file(relativePath: { eq: $file }) {
|
||||||
|
relativePath
|
||||||
|
ctime
|
||||||
|
post: childMarkdownRemark {
|
||||||
|
html
|
||||||
|
excerpt
|
||||||
|
timeToRead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { graphql } from "gatsby"
|
import { graphql } from "gatsby"
|
||||||
import React, { FC, Fragment } from "react"
|
import React, { FC, Fragment } from "react"
|
||||||
|
import { ColumnHeader } from "../components/ColumnHeader"
|
||||||
import { Markdown } from "../components/Markdown"
|
import { Markdown } from "../components/Markdown"
|
||||||
import { ResourceHeader } from "../components/ResourceHeader"
|
|
||||||
import { SEO } from "../components/SEO"
|
import { SEO } from "../components/SEO"
|
||||||
|
|
||||||
import "katex/dist/katex.min.css"
|
import "katex/dist/katex.min.css"
|
||||||
@@ -14,8 +14,9 @@ const LanguagePost: FC<any> = ({ data }) => {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SEO title={frontmatter.title} description={excerpt} />
|
<SEO title={frontmatter.title} description={excerpt} />
|
||||||
<ResourceHeader
|
<ColumnHeader
|
||||||
relativePath={relativePath}
|
relativePath={relativePath}
|
||||||
|
basePath="/resources"
|
||||||
title={frontmatter.title}
|
title={frontmatter.title}
|
||||||
authors={fields.authors}
|
authors={fields.authors}
|
||||||
createdAt={frontmatter.created_at}
|
createdAt={frontmatter.created_at}
|
||||||
|
|||||||
Vendored
+25
-1
@@ -14,6 +14,12 @@ export interface IFolder {
|
|||||||
export type IFileOrFolder = IFile | IFolder
|
export type IFileOrFolder = IFile | IFolder
|
||||||
|
|
||||||
export interface IFileQuery {
|
export interface IFileQuery {
|
||||||
|
node: {
|
||||||
|
relativePath: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFileResourceQuery {
|
||||||
node: {
|
node: {
|
||||||
relativePath: string
|
relativePath: string
|
||||||
childMarkdownRemark: {
|
childMarkdownRemark: {
|
||||||
@@ -25,8 +31,26 @@ export interface IFileQuery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAllResourcesQuery {
|
export interface IFileArchiveQuery {
|
||||||
|
node: {
|
||||||
|
relativePath: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAllFilesQuery {
|
||||||
allFile: {
|
allFile: {
|
||||||
edges: IFileQuery[]
|
edges: IFileQuery[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IAllResourcesQuery extends IAllFilesQuery {
|
||||||
|
allFile: {
|
||||||
|
edges: IFileResourceQuery[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAllArchivesQuery extends IAllFilesQuery {
|
||||||
|
allFile: {
|
||||||
|
edges: IFileArchiveQuery[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -32,7 +32,7 @@ export function humanize(str: string): string {
|
|||||||
|
|
||||||
export function traversePaths(
|
export function traversePaths(
|
||||||
[head, ...tail]: string[],
|
[head, ...tail]: string[],
|
||||||
basePath: string = "/resources"
|
basePath: string
|
||||||
): IFileOrFolder {
|
): IFileOrFolder {
|
||||||
const path = basePath + "/" + head
|
const path = basePath + "/" + head
|
||||||
const isFile = !tail.length
|
const isFile = !tail.length
|
||||||
@@ -55,7 +55,7 @@ export function traversePaths(
|
|||||||
|
|
||||||
export function traversePathsToFiles(
|
export function traversePathsToFiles(
|
||||||
[head, ...tail]: string[],
|
[head, ...tail]: string[],
|
||||||
basePath: string = "/resources",
|
basePath: string,
|
||||||
depth: number = 0
|
depth: number = 0
|
||||||
): IFileOrFolder {
|
): IFileOrFolder {
|
||||||
const path = basePath + "/" + head + "/" + tail.join("/")
|
const path = basePath + "/" + head + "/" + tail.join("/")
|
||||||
|
|||||||
Reference in New Issue
Block a user