From 8da66a8f7907a5855ddeac705417b800f07afd82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sat, 5 Oct 2024 23:11:53 +0900 Subject: [PATCH 01/16] refactor: make the posts/docs directory more shallow not deeply nested --- src/posts/docs/{ps/baekjoon => }/2558.md | 0 src/posts/docs/{tools/git => }/classic-branch-protection-rules.md | 0 .../docs/{languages/javascript => }/composition-of-javascript.md | 0 .../{conventions/git => }/convention-of-git-commit-message.md | 0 .../html => }/difference-between-b-i-tag-and-strong-em-tag.md | 0 .../difference-between-console-log-and-console-dir.md | 0 .../docs/{misc => }/difference-between-framework-and-library.md | 0 .../difference-between-raw-githubusercontent-and-cdn-jsdelivr.md | 0 .../vscode => }/difference-between-vscode-and-visual-studio.md | 0 .../docs/{languages/markdown => }/everything-about-markdown.md | 0 .../{conventions/git => }/git-repository-naming-convention.md | 0 .../nodejs => }/global-variables-and-objects-in-nodejs.md | 0 .../docs/{languages/html => }/how-to-handle-spaces-in-html.md | 0 src/posts/docs/{tools/git => }/how-to-separate-case-in-git.md | 0 .../docs/{conventions/misc => }/identifier-naming-convention.md | 0 src/posts/docs/{languages/nodejs => }/module-path.md | 0 .../npm => }/npm-concepts-and-frequently-used-cli-commands.md | 0 src/posts/docs/{languages/npm => }/npm-package-babel.md | 0 src/posts/docs/{languages/npm => }/npm-package-dotenv.md | 0 src/posts/docs/{languages/npm => }/npm-package-react.md | 0 .../docs/{languages/javascript => }/overview-of-javascript.md | 0 src/posts/docs/{languages/nodejs => }/require-and-import.md | 0 src/posts/docs/{misc => }/software-developer-types.md | 0 src/posts/docs/{tools/git => }/what-is-github-issues.md | 0 src/posts/docs/{languages/nodejs => }/what-is-nvm-and-nvmrc.md | 0 ...s-in-a-server-component-should-i-use-process-cwd-or-dirname.md | 0 ...-file-based-metadata-the-favicon-is-not-displayed-correctly.md | 0 27 files changed, 0 insertions(+), 0 deletions(-) rename src/posts/docs/{ps/baekjoon => }/2558.md (100%) rename src/posts/docs/{tools/git => }/classic-branch-protection-rules.md (100%) rename src/posts/docs/{languages/javascript => }/composition-of-javascript.md (100%) rename src/posts/docs/{conventions/git => }/convention-of-git-commit-message.md (100%) rename src/posts/docs/{languages/html => }/difference-between-b-i-tag-and-strong-em-tag.md (100%) rename src/posts/docs/{languages/javascript => }/difference-between-console-log-and-console-dir.md (100%) rename src/posts/docs/{misc => }/difference-between-framework-and-library.md (100%) rename src/posts/docs/{tools/git => }/difference-between-raw-githubusercontent-and-cdn-jsdelivr.md (100%) rename src/posts/docs/{tools/vscode => }/difference-between-vscode-and-visual-studio.md (100%) rename src/posts/docs/{languages/markdown => }/everything-about-markdown.md (100%) rename src/posts/docs/{conventions/git => }/git-repository-naming-convention.md (100%) rename src/posts/docs/{languages/nodejs => }/global-variables-and-objects-in-nodejs.md (100%) rename src/posts/docs/{languages/html => }/how-to-handle-spaces-in-html.md (100%) rename src/posts/docs/{tools/git => }/how-to-separate-case-in-git.md (100%) rename src/posts/docs/{conventions/misc => }/identifier-naming-convention.md (100%) rename src/posts/docs/{languages/nodejs => }/module-path.md (100%) rename src/posts/docs/{languages/npm => }/npm-concepts-and-frequently-used-cli-commands.md (100%) rename src/posts/docs/{languages/npm => }/npm-package-babel.md (100%) rename src/posts/docs/{languages/npm => }/npm-package-dotenv.md (100%) rename src/posts/docs/{languages/npm => }/npm-package-react.md (100%) rename src/posts/docs/{languages/javascript => }/overview-of-javascript.md (100%) rename src/posts/docs/{languages/nodejs => }/require-and-import.md (100%) rename src/posts/docs/{misc => }/software-developer-types.md (100%) rename src/posts/docs/{tools/git => }/what-is-github-issues.md (100%) rename src/posts/docs/{languages/nodejs => }/what-is-nvm-and-nvmrc.md (100%) rename src/posts/docs/{languages/nextjs => }/when-loading-files-in-a-server-component-should-i-use-process-cwd-or-dirname.md (100%) rename src/posts/docs/{languages/nextjs => }/when-using-file-based-metadata-the-favicon-is-not-displayed-correctly.md (100%) diff --git a/src/posts/docs/ps/baekjoon/2558.md b/src/posts/docs/2558.md similarity index 100% rename from src/posts/docs/ps/baekjoon/2558.md rename to src/posts/docs/2558.md diff --git a/src/posts/docs/tools/git/classic-branch-protection-rules.md b/src/posts/docs/classic-branch-protection-rules.md similarity index 100% rename from src/posts/docs/tools/git/classic-branch-protection-rules.md rename to src/posts/docs/classic-branch-protection-rules.md diff --git a/src/posts/docs/languages/javascript/composition-of-javascript.md b/src/posts/docs/composition-of-javascript.md similarity index 100% rename from src/posts/docs/languages/javascript/composition-of-javascript.md rename to src/posts/docs/composition-of-javascript.md diff --git a/src/posts/docs/conventions/git/convention-of-git-commit-message.md b/src/posts/docs/convention-of-git-commit-message.md similarity index 100% rename from src/posts/docs/conventions/git/convention-of-git-commit-message.md rename to src/posts/docs/convention-of-git-commit-message.md diff --git a/src/posts/docs/languages/html/difference-between-b-i-tag-and-strong-em-tag.md b/src/posts/docs/difference-between-b-i-tag-and-strong-em-tag.md similarity index 100% rename from src/posts/docs/languages/html/difference-between-b-i-tag-and-strong-em-tag.md rename to src/posts/docs/difference-between-b-i-tag-and-strong-em-tag.md diff --git a/src/posts/docs/languages/javascript/difference-between-console-log-and-console-dir.md b/src/posts/docs/difference-between-console-log-and-console-dir.md similarity index 100% rename from src/posts/docs/languages/javascript/difference-between-console-log-and-console-dir.md rename to src/posts/docs/difference-between-console-log-and-console-dir.md diff --git a/src/posts/docs/misc/difference-between-framework-and-library.md b/src/posts/docs/difference-between-framework-and-library.md similarity index 100% rename from src/posts/docs/misc/difference-between-framework-and-library.md rename to src/posts/docs/difference-between-framework-and-library.md diff --git a/src/posts/docs/tools/git/difference-between-raw-githubusercontent-and-cdn-jsdelivr.md b/src/posts/docs/difference-between-raw-githubusercontent-and-cdn-jsdelivr.md similarity index 100% rename from src/posts/docs/tools/git/difference-between-raw-githubusercontent-and-cdn-jsdelivr.md rename to src/posts/docs/difference-between-raw-githubusercontent-and-cdn-jsdelivr.md diff --git a/src/posts/docs/tools/vscode/difference-between-vscode-and-visual-studio.md b/src/posts/docs/difference-between-vscode-and-visual-studio.md similarity index 100% rename from src/posts/docs/tools/vscode/difference-between-vscode-and-visual-studio.md rename to src/posts/docs/difference-between-vscode-and-visual-studio.md diff --git a/src/posts/docs/languages/markdown/everything-about-markdown.md b/src/posts/docs/everything-about-markdown.md similarity index 100% rename from src/posts/docs/languages/markdown/everything-about-markdown.md rename to src/posts/docs/everything-about-markdown.md diff --git a/src/posts/docs/conventions/git/git-repository-naming-convention.md b/src/posts/docs/git-repository-naming-convention.md similarity index 100% rename from src/posts/docs/conventions/git/git-repository-naming-convention.md rename to src/posts/docs/git-repository-naming-convention.md diff --git a/src/posts/docs/languages/nodejs/global-variables-and-objects-in-nodejs.md b/src/posts/docs/global-variables-and-objects-in-nodejs.md similarity index 100% rename from src/posts/docs/languages/nodejs/global-variables-and-objects-in-nodejs.md rename to src/posts/docs/global-variables-and-objects-in-nodejs.md diff --git a/src/posts/docs/languages/html/how-to-handle-spaces-in-html.md b/src/posts/docs/how-to-handle-spaces-in-html.md similarity index 100% rename from src/posts/docs/languages/html/how-to-handle-spaces-in-html.md rename to src/posts/docs/how-to-handle-spaces-in-html.md diff --git a/src/posts/docs/tools/git/how-to-separate-case-in-git.md b/src/posts/docs/how-to-separate-case-in-git.md similarity index 100% rename from src/posts/docs/tools/git/how-to-separate-case-in-git.md rename to src/posts/docs/how-to-separate-case-in-git.md diff --git a/src/posts/docs/conventions/misc/identifier-naming-convention.md b/src/posts/docs/identifier-naming-convention.md similarity index 100% rename from src/posts/docs/conventions/misc/identifier-naming-convention.md rename to src/posts/docs/identifier-naming-convention.md diff --git a/src/posts/docs/languages/nodejs/module-path.md b/src/posts/docs/module-path.md similarity index 100% rename from src/posts/docs/languages/nodejs/module-path.md rename to src/posts/docs/module-path.md diff --git a/src/posts/docs/languages/npm/npm-concepts-and-frequently-used-cli-commands.md b/src/posts/docs/npm-concepts-and-frequently-used-cli-commands.md similarity index 100% rename from src/posts/docs/languages/npm/npm-concepts-and-frequently-used-cli-commands.md rename to src/posts/docs/npm-concepts-and-frequently-used-cli-commands.md diff --git a/src/posts/docs/languages/npm/npm-package-babel.md b/src/posts/docs/npm-package-babel.md similarity index 100% rename from src/posts/docs/languages/npm/npm-package-babel.md rename to src/posts/docs/npm-package-babel.md diff --git a/src/posts/docs/languages/npm/npm-package-dotenv.md b/src/posts/docs/npm-package-dotenv.md similarity index 100% rename from src/posts/docs/languages/npm/npm-package-dotenv.md rename to src/posts/docs/npm-package-dotenv.md diff --git a/src/posts/docs/languages/npm/npm-package-react.md b/src/posts/docs/npm-package-react.md similarity index 100% rename from src/posts/docs/languages/npm/npm-package-react.md rename to src/posts/docs/npm-package-react.md diff --git a/src/posts/docs/languages/javascript/overview-of-javascript.md b/src/posts/docs/overview-of-javascript.md similarity index 100% rename from src/posts/docs/languages/javascript/overview-of-javascript.md rename to src/posts/docs/overview-of-javascript.md diff --git a/src/posts/docs/languages/nodejs/require-and-import.md b/src/posts/docs/require-and-import.md similarity index 100% rename from src/posts/docs/languages/nodejs/require-and-import.md rename to src/posts/docs/require-and-import.md diff --git a/src/posts/docs/misc/software-developer-types.md b/src/posts/docs/software-developer-types.md similarity index 100% rename from src/posts/docs/misc/software-developer-types.md rename to src/posts/docs/software-developer-types.md diff --git a/src/posts/docs/tools/git/what-is-github-issues.md b/src/posts/docs/what-is-github-issues.md similarity index 100% rename from src/posts/docs/tools/git/what-is-github-issues.md rename to src/posts/docs/what-is-github-issues.md diff --git a/src/posts/docs/languages/nodejs/what-is-nvm-and-nvmrc.md b/src/posts/docs/what-is-nvm-and-nvmrc.md similarity index 100% rename from src/posts/docs/languages/nodejs/what-is-nvm-and-nvmrc.md rename to src/posts/docs/what-is-nvm-and-nvmrc.md diff --git a/src/posts/docs/languages/nextjs/when-loading-files-in-a-server-component-should-i-use-process-cwd-or-dirname.md b/src/posts/docs/when-loading-files-in-a-server-component-should-i-use-process-cwd-or-dirname.md similarity index 100% rename from src/posts/docs/languages/nextjs/when-loading-files-in-a-server-component-should-i-use-process-cwd-or-dirname.md rename to src/posts/docs/when-loading-files-in-a-server-component-should-i-use-process-cwd-or-dirname.md diff --git a/src/posts/docs/languages/nextjs/when-using-file-based-metadata-the-favicon-is-not-displayed-correctly.md b/src/posts/docs/when-using-file-based-metadata-the-favicon-is-not-displayed-correctly.md similarity index 100% rename from src/posts/docs/languages/nextjs/when-using-file-based-metadata-the-favicon-is-not-displayed-correctly.md rename to src/posts/docs/when-using-file-based-metadata-the-favicon-is-not-displayed-correctly.md From b435f90e033573384497518cf0e3adda1c557f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sat, 5 Oct 2024 23:58:31 +0900 Subject: [PATCH 02/16] refactor: change the dynamic route folder name from docs/[...categories] to posts/[markdown] --- .../{docs/[...categories] => posts/[markdown]}/layout.jsx | 0 src/app/{docs/[...categories] => posts/[markdown]}/page.jsx | 6 +++--- src/components/aside/Categories/Categories.jsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename src/app/{docs/[...categories] => posts/[markdown]}/layout.jsx (100%) rename src/app/{docs/[...categories] => posts/[markdown]}/page.jsx (87%) diff --git a/src/app/docs/[...categories]/layout.jsx b/src/app/posts/[markdown]/layout.jsx similarity index 100% rename from src/app/docs/[...categories]/layout.jsx rename to src/app/posts/[markdown]/layout.jsx diff --git a/src/app/docs/[...categories]/page.jsx b/src/app/posts/[markdown]/page.jsx similarity index 87% rename from src/app/docs/[...categories]/page.jsx rename to src/app/posts/[markdown]/page.jsx index 9ec3440..2e35252 100644 --- a/src/app/docs/[...categories]/page.jsx +++ b/src/app/posts/[markdown]/page.jsx @@ -1,5 +1,5 @@ import { promises as fs } from 'fs'; -import { join, sep } from 'path'; +import { join } from 'path'; import { DOCS } from '@/constants/path'; import markdownToJsx, { readMarkdownWithFrontMatter } from '@/utils/markdownToJsx'; @@ -7,7 +7,7 @@ import markdownToText from '@/utils/markdownToText'; /* Custom Declaration */ function getFilePath(params) { - return join(DOCS, `${params.categories.join(sep)}.md`); + return join(DOCS, `${params.markdown}.md`); } /* Next.js Declaration */ @@ -22,7 +22,7 @@ export async function generateStaticParams() { return paths .filter(path => path.endsWith('.md')) .map(path => ({ - categories: path.replace(/\.md$/, '').split(sep), + markdown: path.replace(/\.md$/, ''), })); } diff --git a/src/components/aside/Categories/Categories.jsx b/src/components/aside/Categories/Categories.jsx index 174ff6b..8821612 100644 --- a/src/components/aside/Categories/Categories.jsx +++ b/src/components/aside/Categories/Categories.jsx @@ -20,7 +20,7 @@ function renderDirTree(dirTree, basePath = '') { return (
  • {dirTreeNode.name.endsWith('.md') ? ( - + {dirTreeNode.name.replace('.md', '')} ) : ( From 7b0229203518908c3a4c981003cf35f63400b1e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 15:15:53 +0900 Subject: [PATCH 03/16] refactor: create utils/fs.js --- src/utils/fs.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/utils/fs.js diff --git a/src/utils/fs.js b/src/utils/fs.js new file mode 100644 index 0000000..ee18fe4 --- /dev/null +++ b/src/utils/fs.js @@ -0,0 +1,36 @@ +import { promises as fs } from 'fs'; + +import matter from 'gray-matter'; + +/** + * Reads the contents of a file. + * + * @async + * @param {string} filePath The path to the file. + * @returns {Promise} The content of the file. + */ +export async function readFile(filePath) { + return fs.readFile(filePath, 'utf-8'); +} + +/** + * Reads a Markdown file and returns either the content or data(front matter). + * + * @async + * @param {string} filePath The path to the Markdown file. + * @param {'content' | 'data'} [option='content'] The type of data to return. + * @returns {Promise} The content or data(front matter) of the file. + * @throws {TypeError} If the option is invalid. + */ +export async function readMarkdown(filePath, option = 'content') { + const { content, data } = matter(await readFile(filePath)); + + switch (option) { + case 'content': + return content; + case 'data': + return data; + default: + throw TypeError(); + } +} From a955e149aa1e15d32a78fae93e74083eeff77030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 17:22:10 +0900 Subject: [PATCH 04/16] refactor: create path.js and update markdownToJsx.js --- src/app/posts/[markdown]/page.jsx | 17 ++++---- .../aside/Categories/Categories.jsx | 22 ++++++---- src/constants/path.js | 7 ++++ src/utils/markdownToJsx.js | 42 +++++++------------ 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/app/posts/[markdown]/page.jsx b/src/app/posts/[markdown]/page.jsx index 2e35252..de76804 100644 --- a/src/app/posts/[markdown]/page.jsx +++ b/src/app/posts/[markdown]/page.jsx @@ -1,13 +1,16 @@ import { promises as fs } from 'fs'; import { join } from 'path'; -import { DOCS } from '@/constants/path'; -import markdownToJsx, { readMarkdownWithFrontMatter } from '@/utils/markdownToJsx'; +import { DOCS, EXTENSION } from '@/constants/path'; +import { readMarkdown } from '@/utils/fs'; +import markdownToJsx from '@/utils/markdownToJsx'; import markdownToText from '@/utils/markdownToText'; /* Custom Declaration */ +const { md, mdRegExp } = EXTENSION; + function getFilePath(params) { - return join(DOCS, `${params.markdown}.md`); + return join(DOCS, `${params.markdown}${md}`); } /* Next.js Declaration */ @@ -20,16 +23,14 @@ export async function generateStaticParams() { }); return paths - .filter(path => path.endsWith('.md')) + .filter(path => path.endsWith(md)) .map(path => ({ - markdown: path.replace(/\.md$/, ''), + markdown: path.replace(mdRegExp, ''), })); } export async function generateMetadata({ params }) { - const { - data: { title, description }, - } = await readMarkdownWithFrontMatter(getFilePath(params)); + const { title, description } = await readMarkdown(getFilePath(params), 'data'); return { title: markdownToText(title), diff --git a/src/components/aside/Categories/Categories.jsx b/src/components/aside/Categories/Categories.jsx index 8821612..ce89dc2 100644 --- a/src/components/aside/Categories/Categories.jsx +++ b/src/components/aside/Categories/Categories.jsx @@ -2,14 +2,11 @@ import { join } from 'path'; import Link from 'next/link'; -import { DOCS } from '@/constants/path'; +import { DOCS, EXTENSION } from '@/constants/path'; import { getDirTree } from '@/utils/dirTree'; -export default async function Categories() { - const dirTree = await getDirTree(DOCS); - - return <>{renderDirTree(dirTree)}; -} +/* Custom Declaration */ +const { md, mdRegExp } = EXTENSION; function renderDirTree(dirTree, basePath = '') { return ( @@ -19,9 +16,9 @@ function renderDirTree(dirTree, basePath = '') { return (
  • - {dirTreeNode.name.endsWith('.md') ? ( - - {dirTreeNode.name.replace('.md', '')} + {dirTreeNode.name.endsWith(md) ? ( + + {dirTreeNode.name.replace(mdRegExp, '')} ) : ( <> @@ -35,3 +32,10 @@ function renderDirTree(dirTree, basePath = '') { ); } + +/* React Declaration */ +export default async function Categories() { + const dirTree = await getDirTree(DOCS); + + return <>{renderDirTree(dirTree)}; +} diff --git a/src/constants/path.js b/src/constants/path.js index 7d92562..fbbf208 100644 --- a/src/constants/path.js +++ b/src/constants/path.js @@ -1,3 +1,10 @@ import { join } from 'path'; export const DOCS = join(process.cwd(), 'src', 'posts', 'docs'); + +export const EXTENSION = Object.freeze({ + md: '.md', + get mdRegExp() { + return new RegExp(`${this.md}$`, 'i'); + }, +}); diff --git a/src/utils/markdownToJsx.js b/src/utils/markdownToJsx.js index 0c16534..51d50ba 100644 --- a/src/utils/markdownToJsx.js +++ b/src/utils/markdownToJsx.js @@ -1,61 +1,47 @@ -import { promises as fs } from 'fs'; - import parse from 'html-react-parser'; -import matter from 'gray-matter'; import { REPOSITORY } from '@/constants/github'; +import { readMarkdown } from './fs'; /** - * Converts a markdown file to JSX. + * Converts a markdown content to JSX. * * @async * @param {string} filePath Path to the markdown file. * @returns {Promise} A promise that resolves to JSX. */ export default async function markdownToJsx(filePath) { - const markdownWithFrontMatter = await readMarkdownWithFrontMatter(filePath); - - const markdown = writeTitleIntoMarkdown( - markdownWithFrontMatter.data.title, - markdownWithFrontMatter.content, + const { title } = await readMarkdown(filePath, 'data'); + const markdownContent = writeTitleIntoMarkdown( + title, + await readMarkdown(filePath, 'content'), ); - const html = await markdownToHtml(markdown); + const html = await markdownToHtml(markdownContent); const jsx = htmlToJsx(html); return jsx; } -/** - * Reads a markdown file with a front matter block. - * - * @async - * @param {string} filePath Path to the markdown file with a front matter block. - * @returns {Promise} A promise that resolves to the markdown content with a front matter block. - */ -export async function readMarkdownWithFrontMatter(filePath) { - return matter(await fs.readFile(filePath, 'utf-8')); -} - /** * Adds a title as a top-level heading to the given markdown content. * * @param {string} title The title to add as a heading. - * @param {string} markdown The markdown content. + * @param {string} markdownContent The markdown content. * @returns {string} The markdown content with the title as a heading, if provided. */ -export function writeTitleIntoMarkdown(title, markdown) { - return `${title ? `# ${title}\n\n` : ''}${markdown}`; +export function writeTitleIntoMarkdown(title, markdownContent) { + return `${title ? `# ${title}\n\n` : ''}${markdownContent}`; } /** - * Converts markdown text to HTML using GitHub's Markdown API. + * Converts markdown content to HTML using GitHub's Markdown API. * * @async - * @param {string} markdown The markdown content. + * @param {string} markdownContent The markdown content. * @returns {Promise} A promise that resolves to HTML. */ -export async function markdownToHtml(markdown) { +export async function markdownToHtml(markdownContent) { const response = await fetch('https://api.github.com/markdown', { method: 'POST', headers: { @@ -64,7 +50,7 @@ export async function markdownToHtml(markdown) { 'X-GitHub-Api-Version': '2022-11-28', }, body: JSON.stringify({ - text: markdown, + text: markdownContent, mode: 'gfm', context: REPOSITORY.fullName, }), From d1f33569df35675b6c13bc40a9eb4fc3de8b550a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 18:58:37 +0900 Subject: [PATCH 05/16] refactor: update utils/dirTree.js --- .../aside/Categories/Categories.jsx | 4 ++-- src/types/index.d.ts | 9 ++++++++ src/utils/dirTree.js | 21 +++++++------------ 3 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 src/types/index.d.ts diff --git a/src/components/aside/Categories/Categories.jsx b/src/components/aside/Categories/Categories.jsx index ce89dc2..1cc8e01 100644 --- a/src/components/aside/Categories/Categories.jsx +++ b/src/components/aside/Categories/Categories.jsx @@ -3,7 +3,7 @@ import { join } from 'path'; import Link from 'next/link'; import { DOCS, EXTENSION } from '@/constants/path'; -import { getDirTree } from '@/utils/dirTree'; +import { readDirTree } from '@/utils/dirTree'; /* Custom Declaration */ const { md, mdRegExp } = EXTENSION; @@ -35,7 +35,7 @@ function renderDirTree(dirTree, basePath = '') { /* React Declaration */ export default async function Categories() { - const dirTree = await getDirTree(DOCS); + const dirTree = await readDirTree(DOCS); return <>{renderDirTree(dirTree)}; } diff --git a/src/types/index.d.ts b/src/types/index.d.ts new file mode 100644 index 0000000..c25755e --- /dev/null +++ b/src/types/index.d.ts @@ -0,0 +1,9 @@ +/** + * Represents a node in a directory tree. + */ +export type DirTreeNode = { + // The name of the node. + name: string; + // The array of child nodes if the node is a directory. This is a recursive structure. + children?: DirTreeNode[]; +}; diff --git a/src/utils/dirTree.js b/src/utils/dirTree.js index 1b6ecaa..542f141 100644 --- a/src/utils/dirTree.js +++ b/src/utils/dirTree.js @@ -2,10 +2,7 @@ import { promises as fs } from 'fs'; import { join } from 'path'; /** - * @typedef {object} DirTreeNode - * - * @property {string} name The name of the node. - * @property {Array} [children] The array of child nodes if the node is a directory. This is a recursive structure. + * @typedef {import("@/types").DirTreeNode} DirTreeNode */ /** @@ -13,14 +10,13 @@ import { join } from 'path'; * * @async * @param {string} dirPath The path of the directory. - * @returns {Promise>} A promise that resolves to an array of `DirTreeNode`. - * + * @returns {Promise} A promise that resolves to an array of `DirTreeNode`. * @example - * // Get the directory tree structure - * const dirTree = await getDirTree('/path/to/dir'); + * // Read the directory tree structure + * const dirTree = await readDirTree('/path/to/dir'); * console.log(dirTree); */ -export async function getDirTree(dirPath) { +export async function readDirTree(dirPath) { // `readdir` automatically throws an error when `dirPath` is not a directory. const dirents = await fs.readdir(dirPath, { withFileTypes: true }); @@ -28,7 +24,7 @@ export async function getDirTree(dirPath) { dirents.map(async dirent => ({ name: dirent.name, ...(dirent.isDirectory() - ? { children: await getDirTree(join(dirPath, dirent.name)) } + ? { children: await readDirTree(join(dirPath, dirent.name)) } : {}), })), ); @@ -39,12 +35,11 @@ export async function getDirTree(dirPath) { * * @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: [...] }); + * const isDir = isDir({ name: 'folder', children: [...] }); * console.log(isDir); // true */ -export function isDirectory(dirTreeNode) { +export function isDir(dirTreeNode) { return Boolean(dirTreeNode.children); } From 84d076b76f2f52ea0d5695c26c875f077ea392dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 19:26:24 +0900 Subject: [PATCH 06/16] chore: install @types/node as devDep for a better dev env --- package-lock.json | 16 ++++++++++++++++ package.json | 1 + 2 files changed, 17 insertions(+) diff --git a/package-lock.json b/package-lock.json index 86471a5..38ebeee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "version": "0.0.0", "dependencies": { "@giscus/react": "^3.0.0", + "@types/node": "^22.7.4", "@vercel/analytics": "^1.3.1", "@vercel/speed-insights": "^1.0.12", "github-markdown-css": "^5.7.0", @@ -1130,6 +1131,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -9334,6 +9344,12 @@ "node": ">=18.17" } }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, "node_modules/unified": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz", diff --git a/package.json b/package.json index b7a5fe4..b302626 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "dependencies": { "@giscus/react": "^3.0.0", + "@types/node": "^22.7.4", "@vercel/analytics": "^1.3.1", "@vercel/speed-insights": "^1.0.12", "github-markdown-css": "^5.7.0", From efe38568d816fca048373ed02b44b9fd5f5e28de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 19:29:35 +0900 Subject: [PATCH 07/16] rename: move file system related utils to fs directory --- src/components/aside/Categories/Categories.jsx | 2 +- src/utils/{ => fs}/dirTree.js | 0 src/utils/{fs.js => fs/index.js} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename src/utils/{ => fs}/dirTree.js (100%) rename src/utils/{fs.js => fs/index.js} (100%) diff --git a/src/components/aside/Categories/Categories.jsx b/src/components/aside/Categories/Categories.jsx index 1cc8e01..242ce81 100644 --- a/src/components/aside/Categories/Categories.jsx +++ b/src/components/aside/Categories/Categories.jsx @@ -3,7 +3,7 @@ import { join } from 'path'; import Link from 'next/link'; import { DOCS, EXTENSION } from '@/constants/path'; -import { readDirTree } from '@/utils/dirTree'; +import { readDirTree } from '@/utils/fs/dirTree'; /* Custom Declaration */ const { md, mdRegExp } = EXTENSION; diff --git a/src/utils/dirTree.js b/src/utils/fs/dirTree.js similarity index 100% rename from src/utils/dirTree.js rename to src/utils/fs/dirTree.js diff --git a/src/utils/fs.js b/src/utils/fs/index.js similarity index 100% rename from src/utils/fs.js rename to src/utils/fs/index.js From ecf1f9b2642f727e220f91af37f22c99258cbfe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 19:51:40 +0900 Subject: [PATCH 08/16] rename: change function name from readMarkdown to readFileForMarkdown --- src/app/posts/[markdown]/page.jsx | 4 ++-- src/utils/fs/index.js | 2 +- src/utils/markdownToJsx.js | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/posts/[markdown]/page.jsx b/src/app/posts/[markdown]/page.jsx index de76804..e77daac 100644 --- a/src/app/posts/[markdown]/page.jsx +++ b/src/app/posts/[markdown]/page.jsx @@ -2,7 +2,7 @@ import { promises as fs } from 'fs'; import { join } from 'path'; import { DOCS, EXTENSION } from '@/constants/path'; -import { readMarkdown } from '@/utils/fs'; +import { readFileForMarkdown } from '@/utils/fs'; import markdownToJsx from '@/utils/markdownToJsx'; import markdownToText from '@/utils/markdownToText'; @@ -30,7 +30,7 @@ export async function generateStaticParams() { } export async function generateMetadata({ params }) { - const { title, description } = await readMarkdown(getFilePath(params), 'data'); + const { title, description } = await readFileForMarkdown(getFilePath(params), 'data'); return { title: markdownToText(title), diff --git a/src/utils/fs/index.js b/src/utils/fs/index.js index ee18fe4..23e7a1c 100644 --- a/src/utils/fs/index.js +++ b/src/utils/fs/index.js @@ -22,7 +22,7 @@ export async function readFile(filePath) { * @returns {Promise} The content or data(front matter) of the file. * @throws {TypeError} If the option is invalid. */ -export async function readMarkdown(filePath, option = 'content') { +export async function readFileForMarkdown(filePath, option = 'content') { const { content, data } = matter(await readFile(filePath)); switch (option) { diff --git a/src/utils/markdownToJsx.js b/src/utils/markdownToJsx.js index 51d50ba..2c2b5c1 100644 --- a/src/utils/markdownToJsx.js +++ b/src/utils/markdownToJsx.js @@ -1,7 +1,7 @@ import parse from 'html-react-parser'; import { REPOSITORY } from '@/constants/github'; -import { readMarkdown } from './fs'; +import { readFileForMarkdown } from './fs'; /** * Converts a markdown content to JSX. @@ -11,10 +11,10 @@ import { readMarkdown } from './fs'; * @returns {Promise} A promise that resolves to JSX. */ export default async function markdownToJsx(filePath) { - const { title } = await readMarkdown(filePath, 'data'); + const { title } = await readFileForMarkdown(filePath, 'data'); const markdownContent = writeTitleIntoMarkdown( title, - await readMarkdown(filePath, 'content'), + await readFileForMarkdown(filePath, 'content'), ); const html = await markdownToHtml(markdownContent); From 7a89a9e35b3d599978ca1710bd2b4f6911496825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 20:37:43 +0900 Subject: [PATCH 09/16] refactor: create readDirByExtension function --- src/app/posts/[markdown]/page.jsx | 17 ++++++----------- src/utils/fs/dirTree.js | 3 ++- src/utils/fs/index.js | 24 ++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/app/posts/[markdown]/page.jsx b/src/app/posts/[markdown]/page.jsx index e77daac..71adf04 100644 --- a/src/app/posts/[markdown]/page.jsx +++ b/src/app/posts/[markdown]/page.jsx @@ -1,8 +1,7 @@ -import { promises as fs } from 'fs'; import { join } from 'path'; import { DOCS, EXTENSION } from '@/constants/path'; -import { readFileForMarkdown } from '@/utils/fs'; +import { readFileForMarkdown, readDirByExtension } from '@/utils/fs'; import markdownToJsx from '@/utils/markdownToJsx'; import markdownToText from '@/utils/markdownToText'; @@ -18,15 +17,11 @@ function getFilePath(params) { export const dynamicParams = false; export async function generateStaticParams() { - const paths = await fs.readdir(DOCS, { - recursive: true, - }); - - return paths - .filter(path => path.endsWith(md)) - .map(path => ({ - markdown: path.replace(mdRegExp, ''), - })); + const paths = await readDirByExtension(DOCS, md, { recursive: true }); + + return paths.map(path => ({ + markdown: path.replace(mdRegExp, ''), + })); } export async function generateMetadata({ params }) { diff --git a/src/utils/fs/dirTree.js b/src/utils/fs/dirTree.js index 542f141..36a2cb9 100644 --- a/src/utils/fs/dirTree.js +++ b/src/utils/fs/dirTree.js @@ -1,8 +1,9 @@ +// @ts-check import { promises as fs } from 'fs'; import { join } from 'path'; /** - * @typedef {import("@/types").DirTreeNode} DirTreeNode + * @typedef {import('@/types').DirTreeNode} DirTreeNode */ /** diff --git a/src/utils/fs/index.js b/src/utils/fs/index.js index 23e7a1c..8c91a97 100644 --- a/src/utils/fs/index.js +++ b/src/utils/fs/index.js @@ -1,9 +1,14 @@ +// @ts-check import { promises as fs } from 'fs'; import matter from 'gray-matter'; /** - * Reads the contents of a file. + * @typedef {import('fs').ObjectEncodingOptions} ObjectEncodingOptions + */ + +/** + * Asynchronously reads the contents of a file. * * @async * @param {string} filePath The path to the file. @@ -14,7 +19,7 @@ export async function readFile(filePath) { } /** - * Reads a Markdown file and returns either the content or data(front matter). + * Asynchronously reads a Markdown file and returns either the content or data(front matter). * * @async * @param {string} filePath The path to the Markdown file. @@ -34,3 +39,18 @@ export async function readFileForMarkdown(filePath, option = 'content') { throw TypeError(); } } + +/** + * Asynchronously reads a directory and returns a list of file paths with the specified extension. + * + * @async + * @param {string} dirPath The path to the directory. + * @param {string} extension The file extension to filter by. `extension` cannot be a RegExp. It must be a string. + * @param {ObjectEncodingOptions & {withFileTypes?: false | undefined; recursive?: boolean | undefined;}} [options] Optional `readdir` options. + * @returns {Promise} An array of file paths. + */ +export async function readDirByExtension(dirPath, extension, options) { + const filePaths = await fs.readdir(dirPath, options); + + return filePaths.filter(filePath => filePath.endsWith(extension)); +} From 22df53dee252d416546ad892a748132fe7e46dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 22:38:51 +0900 Subject: [PATCH 10/16] refactor: update constants/github.js --- src/constants/github.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants/github.js b/src/constants/github.js index 57dfaa9..665f8fb 100644 --- a/src/constants/github.js +++ b/src/constants/github.js @@ -2,7 +2,7 @@ export const USER = Object.freeze({ login: 'lumirlumir', name: '루밀LuMir', - bio: 'ᗩᖇTIᔕT🎨『PLAY KEYBOARD, STRIKE A CODE』', + bio: 'PLAY KEYBOARD, STRIKE A CODE🎨', get htmlUrl() { return `https://github.com/${this.login}`; }, From 8494e4cd0e8e54aa20fcedc031335ee7a6a97181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Sun, 6 Oct 2024 23:23:58 +0900 Subject: [PATCH 11/16] refactor: create default value into readDirByExtension func --- src/app/posts/[markdown]/page.jsx | 2 +- src/utils/fs/index.js | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/app/posts/[markdown]/page.jsx b/src/app/posts/[markdown]/page.jsx index 71adf04..c051518 100644 --- a/src/app/posts/[markdown]/page.jsx +++ b/src/app/posts/[markdown]/page.jsx @@ -17,7 +17,7 @@ function getFilePath(params) { export const dynamicParams = false; export async function generateStaticParams() { - const paths = await readDirByExtension(DOCS, md, { recursive: true }); + const paths = await readDirByExtension(DOCS, md); return paths.map(path => ({ markdown: path.replace(mdRegExp, ''), diff --git a/src/utils/fs/index.js b/src/utils/fs/index.js index 8c91a97..23d280d 100644 --- a/src/utils/fs/index.js +++ b/src/utils/fs/index.js @@ -46,10 +46,14 @@ export async function readFileForMarkdown(filePath, option = 'content') { * @async * @param {string} dirPath The path to the directory. * @param {string} extension The file extension to filter by. `extension` cannot be a RegExp. It must be a string. - * @param {ObjectEncodingOptions & {withFileTypes?: false | undefined; recursive?: boolean | undefined;}} [options] Optional `readdir` options. + * @param {ObjectEncodingOptions & {withFileTypes?: false | undefined; recursive?: boolean | undefined;}} [options = { recursive: true }] Optional `readdir` options. * @returns {Promise} An array of file paths. */ -export async function readDirByExtension(dirPath, extension, options) { +export async function readDirByExtension( + dirPath, + extension, + options = { recursive: true }, +) { const filePaths = await fs.readdir(dirPath, options); return filePaths.filter(filePath => filePath.endsWith(extension)); From 5c3e918c53eed67d047c57e03508867c26124cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Mon, 7 Oct 2024 20:31:00 +0900 Subject: [PATCH 12/16] design: change the width of the Aside component --- src/components/layouts/Aside/Aside.module.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/layouts/Aside/Aside.module.scss b/src/components/layouts/Aside/Aside.module.scss index af7264b..5443a88 100644 --- a/src/components/layouts/Aside/Aside.module.scss +++ b/src/components/layouts/Aside/Aside.module.scss @@ -1,7 +1,7 @@ .aside { position: sticky; top: 0; - width: 300px; + width: 250px; height: 100vh; overflow-y: scroll; background-color: inherit; From e1e8e97cd49b9eaf9e9367940bd27f627a1989fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Mon, 7 Oct 2024 20:33:48 +0900 Subject: [PATCH 13/16] refactor: create archives folder and move an unused but useful code file --- archives/Categories.jsx | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 archives/Categories.jsx diff --git a/archives/Categories.jsx b/archives/Categories.jsx new file mode 100644 index 0000000..242ce81 --- /dev/null +++ b/archives/Categories.jsx @@ -0,0 +1,41 @@ +import { join } from 'path'; + +import Link from 'next/link'; + +import { DOCS, EXTENSION } from '@/constants/path'; +import { readDirTree } from '@/utils/fs/dirTree'; + +/* Custom Declaration */ +const { md, mdRegExp } = EXTENSION; + +function renderDirTree(dirTree, basePath = '') { + return ( +
      + {dirTree.map(dirTreeNode => { + const currPath = join(basePath, dirTreeNode.name); + + return ( +
    • + {dirTreeNode.name.endsWith(md) ? ( + + {dirTreeNode.name.replace(mdRegExp, '')} + + ) : ( + <> + {dirTreeNode.name} + {renderDirTree(dirTreeNode.children, currPath)} + + )} +
    • + ); + })} +
    + ); +} + +/* React Declaration */ +export default async function Categories() { + const dirTree = await readDirTree(DOCS); + + return <>{renderDirTree(dirTree)}; +} From aea66c8d69045eb840f8f911bfafa3c523b690bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Mon, 7 Oct 2024 20:40:22 +0900 Subject: [PATCH 14/16] refactor: update readFileFromMarkdown func in utils/fs/index.js added 'all' case. change option's default parameter to 'all' --- src/utils/fs/index.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/utils/fs/index.js b/src/utils/fs/index.js index 23d280d..26771bc 100644 --- a/src/utils/fs/index.js +++ b/src/utils/fs/index.js @@ -23,11 +23,11 @@ export async function readFile(filePath) { * * @async * @param {string} filePath The path to the Markdown file. - * @param {'content' | 'data'} [option='content'] The type of data to return. - * @returns {Promise} The content or data(front matter) of the file. + * @param {'content' | 'data' | 'all'} [option='all'] The type of data to return. + * @returns {Promise} The content or data(front matter) of the file. * @throws {TypeError} If the option is invalid. */ -export async function readFileForMarkdown(filePath, option = 'content') { +export async function readFileForMarkdown(filePath, option = 'all') { const { content, data } = matter(await readFile(filePath)); switch (option) { @@ -35,6 +35,11 @@ export async function readFileForMarkdown(filePath, option = 'content') { return content; case 'data': return data; + case 'all': + return { + content, + data, + }; default: throw TypeError(); } From 7043e89e8d79b1a858f1f6a3e8a3f5235b8f49cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Mon, 7 Oct 2024 23:01:44 +0900 Subject: [PATCH 15/16] refactor: create tagTree.js --- src/types/index.d.ts | 25 +++++++++++++++++++++---- src/utils/fs/tagTree.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 src/utils/fs/tagTree.js diff --git a/src/types/index.d.ts b/src/types/index.d.ts index c25755e..858956d 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,9 +1,26 @@ +/** + * Represents a Markdown file structure with its content and data(front matter). + */ +export type Markdown = { + content: string; + data: { + [key: string]: any; + }; +}; + /** * Represents a node in a directory tree. */ export type DirTreeNode = { - // The name of the node. - name: string; - // The array of child nodes if the node is a directory. This is a recursive structure. - children?: DirTreeNode[]; + name: string; // The name of the node. + children?: DirTreeNode[]; // The array of child nodes if the node is a directory. This is a recursive structure. +}; + +/** + * Represents a node in a tag tree. + */ +export type TagTreeNode = { + [key: string]: { + basename: string; + } & Markdown; }; diff --git a/src/utils/fs/tagTree.js b/src/utils/fs/tagTree.js new file mode 100644 index 0000000..38536f8 --- /dev/null +++ b/src/utils/fs/tagTree.js @@ -0,0 +1,36 @@ +import { join } from 'path'; + +import { EXTENSION } from '@/constants/path'; +import { readFileForMarkdown, readDirByExtension } from '@/utils/fs'; + +const { md } = EXTENSION; + +/** + * @typedef {import('@/types').TagTreeNode} TagTreeNode + */ + +/** + * Reads a directory and generates a tag tree from markdown files. + * + * @param {string} dirPath The path to the directory containing markdown files. + * @returns {Promise} A promise that resolves to an array of tag tree nodes. + */ +export async function readTagTree(dirPath) { + const tagTree = {}; // Initialize an empty object to store the tag tree + const markdownFilePaths = await readDirByExtension(dirPath, md); + + for (const markdownFilePath of markdownFilePaths) { + const { content, data } = await readFileForMarkdown(join(dirPath, markdownFilePath)); + + data.tags.forEach(tag => { + tagTree[tag] ??= []; + tagTree[tag].push({ + basename: markdownFilePath, + content, + data, + }); + }); + } + + return tagTree; +} From 29ad4be8aadbd56c768776914ab61b1f66caeac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A3=A8=EB=B0=80LuMir?= Date: Mon, 7 Oct 2024 23:11:42 +0900 Subject: [PATCH 16/16] feat: create categories --- src/app/categories/[tag]/page.jsx | 24 +++++++++++ .../aside/Categories/Categories.jsx | 43 +++++-------------- 2 files changed, 35 insertions(+), 32 deletions(-) create mode 100644 src/app/categories/[tag]/page.jsx diff --git a/src/app/categories/[tag]/page.jsx b/src/app/categories/[tag]/page.jsx new file mode 100644 index 0000000..19c228f --- /dev/null +++ b/src/app/categories/[tag]/page.jsx @@ -0,0 +1,24 @@ +import Link from 'next/link'; + +import { DOCS, EXTENSION } from '@/constants/path'; +import { readTagTree } from '@/utils/fs/tagTree'; +import markdownToText from '@/utils/markdownToText'; + +const { mdRegExp } = EXTENSION; + +export default async function Page({ params }) { + const tagTree = await readTagTree(DOCS); + + return tagTree[params.tag].map(({ basename, data: { title, description, tags } }) => ( +
    +

    + + {markdownToText(title)} + +

    +

    {markdownToText(description)}

    +

    {tags.join(', ')}

    +
    +
    + )); +} diff --git a/src/components/aside/Categories/Categories.jsx b/src/components/aside/Categories/Categories.jsx index 242ce81..c86d606 100644 --- a/src/components/aside/Categories/Categories.jsx +++ b/src/components/aside/Categories/Categories.jsx @@ -1,41 +1,20 @@ -import { join } from 'path'; - import Link from 'next/link'; -import { DOCS, EXTENSION } from '@/constants/path'; -import { readDirTree } from '@/utils/fs/dirTree'; +import { DOCS } from '@/constants/path'; +import { readTagTree } from '@/utils/fs/tagTree'; -/* Custom Declaration */ -const { md, mdRegExp } = EXTENSION; +/* React Declaration */ +export default async function Categories() { + const tagTree = await readTagTree(DOCS); -function renderDirTree(dirTree, basePath = '') { return (
      - {dirTree.map(dirTreeNode => { - const currPath = join(basePath, dirTreeNode.name); - - return ( -
    • - {dirTreeNode.name.endsWith(md) ? ( - - {dirTreeNode.name.replace(mdRegExp, '')} - - ) : ( - <> - {dirTreeNode.name} - {renderDirTree(dirTreeNode.children, currPath)} - - )} -
    • - ); - })} + {Object.keys(tagTree).map(key => ( +
    • + {key} +  ({tagTree[key].length}) +
    • + ))}
    ); } - -/* React Declaration */ -export default async function Categories() { - const dirTree = await readDirTree(DOCS); - - return <>{renderDirTree(dirTree)}; -}