mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-09 07:56:12 +02:00
refact: extract tree build a hook
This commit is contained in:
@@ -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[]
|
||||||
}
|
}
|
||||||
@@ -160,17 +86,11 @@ function Folder({ item }: { item: IFolder }) {
|
|||||||
|
|
||||||
const DocsSidebar = () => {
|
const 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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
import * as R from "ramda"
|
||||||
|
import {
|
||||||
|
IFileOrFolder,
|
||||||
|
IFile,
|
||||||
|
IFolder,
|
||||||
|
IAllDocsQuery,
|
||||||
|
IFileQuery,
|
||||||
|
} from "./index"
|
||||||
|
|
||||||
|
const 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)],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useBuildTree(docs: IAllDocsQuery) {
|
||||||
|
const objects = docs.allFile.edges.map(({ node: file }: IFileQuery) =>
|
||||||
|
traverse(file.relativePath.split("/"))
|
||||||
|
)
|
||||||
|
|
||||||
|
return join(objects)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user