Skip to content

Commit

Permalink
refactor: separate UI elements into components. (#62)
Browse files Browse the repository at this point in the history
* refactor: create dirTree.js

* refactor: detach Categories component from Aside component

* refactor: detach Home component from Aside component

* refactor: make Aside component as a single wrapper

* rename: move src/layouts to src/components/layouts

* refactor: make Article components as a single wrapper

* refactor: move every grid related properties to main component

* refactor: detach Title component from Header component
  • Loading branch information
lumirlumir authored Sep 16, 2024
1 parent 479910f commit 5592b86
Show file tree
Hide file tree
Showing 29 changed files with 175 additions and 109 deletions.
3 changes: 1 addition & 2 deletions src/app/docs/[...categories]/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import parse from 'html-react-parser';

import { REPOSITORY } from '@/constants/github';
import { DOCS } from '@/constants/path';
import Article from '@/layouts/Article';

export async function generateStaticParams() {
const paths = await fs.readdir(DOCS, {
Expand All @@ -24,7 +23,7 @@ export default async function Page({ params }) {
'utf-8',
);

return <Article>{await markdownToJsx(markdown)}</Article>;
return <>{await markdownToJsx(markdown)}</>;
}

async function markdownToHtml(markdown) {
Expand Down
37 changes: 29 additions & 8 deletions src/app/layout.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
import { SpeedInsights } from '@vercel/speed-insights/next';

import Aside from '@/layouts/Aside';
import Body from '@/layouts/Body';
import Header from '@/layouts/Header';
import Main from '@/layouts/Main';
import Article from '@/components/layouts/Article';
import Aside from '@/components/layouts/Aside';
import Body from '@/components/layouts/Body';
import Header from '@/components/layouts/Header';
import Main from '@/components/layouts/Main';

export default function Layout({ children }) {
import Categories from '@/components/aside/Categories';
import Home from '@/components/aside/Home';

import Title from '@/components/header/Title';

// TODO: import '@/styles/global.scss';

// TODO: export const metadata = {
// title: 'Next.js',
// description: 'Generated by Next.js',
// };

export default function RootLayout({ children }) {
return (
<html lang="ko">
<Body>
<Header />
<Aside />
<Main>{children}</Main>
<Header>
<Title />
</Header>
<Aside>
<Home />
<Categories />
</Aside>
<Main>
<Article>{children}</Article>
</Main>

<SpeedInsights />
</Body>
</html>
Expand Down
4 changes: 1 addition & 3 deletions src/app/page.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { USER } from '@/constants/github';

import Article from '@/layouts/Article';

export default function Page() {
return <Article>{`Hello, It's ${USER.name}'s blog!`}</Article>;
return <>{`Hello, It's ${USER.name}'s blog!`}</>;
}
37 changes: 37 additions & 0 deletions src/components/aside/Categories/Categories.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { join } from 'path';

import Link from 'next/link';

import { DOCS } from '@/constants/path';
import { getDirTree } from '@/utils/dirTree';

export default async function Categories() {
const dirTree = await getDirTree(DOCS);

return <>{renderDirTree(dirTree)}</>;
}

function renderDirTree(dirTree, basePath = '') {
return (
<ul>
{dirTree.map(dirTreeNode => {
const currPath = join(basePath, dirTreeNode.name);

return (
<li key={currPath}>
{dirTreeNode.name.endsWith('.md') ? (
<Link href={`/docs/${currPath.replace('.md', '')}`}>
{dirTreeNode.name.replace('.md', '')}
</Link>
) : (
<>
<span>{dirTreeNode.name}</span>
{renderDirTree(dirTreeNode.children, currPath)}
</>
)}
</li>
);
})}
</ul>
);
}
3 changes: 3 additions & 0 deletions src/components/aside/Categories/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Categories from './Categories';

export default Categories;
11 changes: 11 additions & 0 deletions src/components/aside/Home/Home.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Link from 'next/link';

export default async function Home() {
return (
<ul>
<li>
<Link href="/">Home</Link>
</li>
</ul>
);
}
3 changes: 3 additions & 0 deletions src/components/aside/Home/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Home from './Home';

export default Home;
7 changes: 7 additions & 0 deletions src/components/header/Title/Title.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Link from 'next/link';

import { USER } from '@/constants/github';

export default function Title() {
return <Link href={USER.htmlUrl}>{USER.name}</Link>;
}
3 changes: 3 additions & 0 deletions src/components/header/Title/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Title from './Title';

export default Title;
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions src/components/layouts/Aside/Aside.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import styles from './Aside.module.scss';

export default function Aside({ children }) {
return <aside className={styles.aside}>{children}</aside>;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.aside {
position: sticky;
top: 0;
grid-area: 1 / 1 / 3 / 2;
width: 300px;
height: 100vh;
overflow-y: scroll;
Expand Down
File renamed without changes.
File renamed without changes.
17 changes: 17 additions & 0 deletions src/components/layouts/Body/Body.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.body {
display: grid;
grid-template-rows: 80px 1fr;
grid-template-columns: 300px 1fr;

> header {
grid-area: 1 / 2 / 2 / 3;
}

> aside {
grid-area: 1 / 1 / 3 / 2;
}

> main {
grid-area: 2 / 2 / 3 / 3;
}
}
File renamed without changes.
5 changes: 5 additions & 0 deletions src/components/layouts/Header/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import styles from './Header.module.scss';

export default function Header({ children }) {
return <header className={styles.header}>{children}</header>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
position: sticky;
top: 0;
z-index: 1;
grid-area: 1 / 2 / 2 / 3;
font-size: 32px;
background-color: inherit;
}
File renamed without changes.
3 changes: 3 additions & 0 deletions src/components/layouts/Main/Main.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Main({ children }) {
return <main>{children}</main>;
}
File renamed without changes.
70 changes: 0 additions & 70 deletions src/layouts/Aside/Aside.jsx

This file was deleted.

5 changes: 0 additions & 5 deletions src/layouts/Body/Body.module.scss

This file was deleted.

11 changes: 0 additions & 11 deletions src/layouts/Header/Header.jsx

This file was deleted.

5 changes: 0 additions & 5 deletions src/layouts/Main/Main.jsx

This file was deleted.

3 changes: 0 additions & 3 deletions src/layouts/Main/Main.module.scss

This file was deleted.

50 changes: 50 additions & 0 deletions src/utils/dirTree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { promises as fs } from 'fs';
import { join } from 'path';

/**
* @typedef {object} DirTreeNode
*
* @property {string} name The name of the node.
* @property {Array<DirTreeNode>} [children] The array of child nodes if the node is a directory. This is a recursive structure.
*/

/**
* Asynchronously retrieves the directory tree structure.
*
* @async
* @param {string} dirPath The path of the directory.
* @returns {Promise<Array<DirTreeNode>>} A promise that resolves to an array of `DirTreeNode`.
*
* @example
* // Get the directory tree structure
* const dirTree = await getDirTree('/path/to/dir');
* console.log(dirTree);
*/
export async function getDirTree(dirPath) {
// `readdir` automatically throws an error when `dirPath` is not a directory.
const dirents = await fs.readdir(dirPath, { withFileTypes: true });

return await Promise.all(
dirents.map(async dirent => ({
name: dirent.name,
...(dirent.isDirectory()
? { children: await getDirTree(join(dirPath, dirent.name)) }
: {}),
})),
);
}

/**
* Checks if a `DirTreeNode` is a directory.
*
* @param {DirTreeNode} dirTreeNode The `DirTreeNode` object.
* @returns {boolean} `true` if the node is a directory. otherwise, `false`.
*
* @example
* // Check if a node is a directory
* const isDir = isDirectory({ name: 'folder', children: [...] });
* console.log(isDir); // true
*/
export function isDirectory(dirTreeNode) {
return Boolean(dirTreeNode.children);
}

0 comments on commit 5592b86

Please sign in to comment.