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)}>;
+}
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",
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/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 51%
rename from src/app/docs/[...categories]/page.jsx
rename to src/app/posts/[markdown]/page.jsx
index 9ec3440..c051518 100644
--- a/src/app/docs/[...categories]/page.jsx
+++ b/src/app/posts/[markdown]/page.jsx
@@ -1,13 +1,15 @@
-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';
+import { DOCS, EXTENSION } from '@/constants/path';
+import { readFileForMarkdown, readDirByExtension } 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.categories.join(sep)}.md`);
+ return join(DOCS, `${params.markdown}${md}`);
}
/* Next.js Declaration */
@@ -15,21 +17,15 @@ 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 => ({
- categories: path.replace(/\.md$/, '').split(sep),
- }));
+ const paths = await readDirByExtension(DOCS, md);
+
+ return paths.map(path => ({
+ markdown: path.replace(mdRegExp, ''),
+ }));
}
export async function generateMetadata({ params }) {
- const {
- data: { title, description },
- } = await readMarkdownWithFrontMatter(getFilePath(params));
+ const { title, description } = await readFileForMarkdown(getFilePath(params), 'data');
return {
title: markdownToText(title),
diff --git a/src/components/aside/Categories/Categories.jsx b/src/components/aside/Categories/Categories.jsx
index 174ff6b..c86d606 100644
--- a/src/components/aside/Categories/Categories.jsx
+++ b/src/components/aside/Categories/Categories.jsx
@@ -1,37 +1,20 @@
-import { join } from 'path';
-
import Link from 'next/link';
import { DOCS } from '@/constants/path';
-import { getDirTree } from '@/utils/dirTree';
+import { readTagTree } from '@/utils/fs/tagTree';
+/* React Declaration */
export default async function Categories() {
- const dirTree = await getDirTree(DOCS);
-
- return <>{renderDirTree(dirTree)}>;
-}
+ 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('.md', '')}
-
- ) : (
- <>
- {dirTreeNode.name}
- {renderDirTree(dirTreeNode.children, currPath)}
- >
- )}
-
- );
- })}
+ {Object.keys(tagTree).map(key => (
+ -
+ {key}
+ ({tagTree[key].length})
+
+ ))}
);
}
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;
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}`;
},
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/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
diff --git a/src/types/index.d.ts b/src/types/index.d.ts
new file mode 100644
index 0000000..858956d
--- /dev/null
+++ b/src/types/index.d.ts
@@ -0,0 +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 = {
+ 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/dirTree.js b/src/utils/fs/dirTree.js
similarity index 57%
rename from src/utils/dirTree.js
rename to src/utils/fs/dirTree.js
index 1b6ecaa..36a2cb9 100644
--- a/src/utils/dirTree.js
+++ b/src/utils/fs/dirTree.js
@@ -1,11 +1,9 @@
+// @ts-check
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 +11,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 +25,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 +36,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);
}
diff --git a/src/utils/fs/index.js b/src/utils/fs/index.js
new file mode 100644
index 0000000..26771bc
--- /dev/null
+++ b/src/utils/fs/index.js
@@ -0,0 +1,65 @@
+// @ts-check
+import { promises as fs } from 'fs';
+
+import matter from 'gray-matter';
+
+/**
+ * @typedef {import('fs').ObjectEncodingOptions} ObjectEncodingOptions
+ */
+
+/**
+ * Asynchronously 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');
+}
+
+/**
+ * Asynchronously 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' | '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 = 'all') {
+ const { content, data } = matter(await readFile(filePath));
+
+ switch (option) {
+ case 'content':
+ return content;
+ case 'data':
+ return data;
+ case 'all':
+ return {
+ content,
+ data,
+ };
+ default:
+ 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 = { recursive: true }] Optional `readdir` options.
+ * @returns {Promise} An array of file paths.
+ */
+export async function readDirByExtension(
+ dirPath,
+ extension,
+ options = { recursive: true },
+) {
+ const filePaths = await fs.readdir(dirPath, options);
+
+ return filePaths.filter(filePath => filePath.endsWith(extension));
+}
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;
+}
diff --git a/src/utils/markdownToJsx.js b/src/utils/markdownToJsx.js
index 0c16534..2c2b5c1 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 { readFileForMarkdown } 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 readFileForMarkdown(filePath, 'data');
+ const markdownContent = writeTitleIntoMarkdown(
+ title,
+ await readFileForMarkdown(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,
}),