Skip to content

Commit 0274253

Browse files
committed
Merge branch 'content-navigation-setup'
2 parents ea31fd7 + b913b85 commit 0274253

24 files changed

+2079
-66
lines changed

app/components/mdx.tsx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { MDXRemote, MDXRemoteProps } from "next-mdx-remote/rsc";
2+
import { Heading } from "@chakra-ui/react";
3+
import { MDXComponents } from "mdx/types";
4+
const components: MDXComponents = {
5+
// chakra-ui overrides heading styles so we need to use the Heading component
6+
// see https://github.com/chakra-ui/chakra-ui/issues/107 for more info
7+
8+
h1: ({ children }) => {
9+
return (
10+
<Heading as="h1" lineHeight={"tall"}>
11+
{children}
12+
</Heading>
13+
);
14+
},
15+
h2: ({ children }) => {
16+
return (
17+
<Heading as="h2" size="lg">
18+
{children}
19+
</Heading>
20+
);
21+
},
22+
h3: ({ children }) => {
23+
return (
24+
<Heading as="h3" size="md">
25+
{children}
26+
</Heading>
27+
);
28+
},
29+
h4: ({ children }) => {
30+
return (
31+
<Heading as="h4" size="sm">
32+
{children}
33+
</Heading>
34+
);
35+
},
36+
h5: ({ children }) => {
37+
return (
38+
<Heading as="h5" size="xs">
39+
{children}
40+
</Heading>
41+
);
42+
},
43+
};
44+
export function CustomMDX(props: MDXRemoteProps) {
45+
return (
46+
<MDXRemote
47+
{...props}
48+
components={{ ...components, ...(props.components || {}) }}
49+
/>
50+
);
51+
}

app/styles/theme.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
"use client";
2-
import { theme as chakraTheme, extendTheme } from "@chakra-ui/react";
2+
import {
3+
background,
4+
theme as chakraTheme,
5+
extendTheme,
6+
} from "@chakra-ui/react";
37

48
const Button = {
59
variants: {
@@ -33,6 +37,7 @@ const Button = {
3337
},
3438
},
3539
};
40+
3641
export const theme = extendTheme({
3742
styles: {
3843
global: {},

app/test/page.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from "react";
2+
// import Page1, {
3+
// metadata,
4+
// } from "@/content/01-introduction/01-why-json-schema.mdx";
5+
import ContentManager from "@/lib/contentManager";
6+
import { CustomMDX } from "../components/mdx";
7+
import { MDXRemote } from "next-mdx-remote/rsc";
8+
9+
export default function Test() {
10+
const cm = new ContentManager();
11+
const { metadata, Page } = cm.parseMdxFile(
12+
"01-introduction/01-why-json-schema.mdx"
13+
);
14+
15+
return (
16+
<div>
17+
<Page />
18+
</div>
19+
);
20+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title : "Demo"
3+
author: "Author Name"
4+
---
5+
6+
7+
# Welcome!
8+
This is the demo content.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

content/01-introduction/index.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
title: introduction
3+
---
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

content/02-types/index.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
title: types
3+
---

content/Chapter 1/1/contentMetaData.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

content/Chapter 1/1/instructions.md

Lines changed: 0 additions & 6 deletions
This file was deleted.

content/Chapter 1/2/contentMetaData.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

content/Chapter 1/2/instructions.md

Lines changed: 0 additions & 6 deletions
This file was deleted.

content/Chapter 2/1/contentMetaData.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

content/Chapter 2/1/instructions.md

Lines changed: 0 additions & 6 deletions
This file was deleted.

content/Chapter 2/2/contentMetaData.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

content/Chapter 2/2/instructions.md

Lines changed: 0 additions & 6 deletions
This file was deleted.

lib/contentManager.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { CustomMDX } from "@/app/components/mdx";
2+
import { ContentOutline } from "./types";
3+
import fs from "fs";
4+
import matter from "gray-matter";
5+
6+
/*
7+
8+
- the content is stored in the content folder
9+
- this contentManager object will generate a outline of type ContentOutline
10+
- it will keep track of the active chapter and step
11+
- return full path of the active step
12+
- return the next step
13+
- return the previous step
14+
- return the next chapter
15+
- return the previous chapter
16+
- change the active chapter
17+
- change the active step
18+
- parse a mdx file and return component and metadata using gray-matter
19+
20+
21+
The content folder follows this structure:
22+
23+
├── 01-introduction
24+
| ├── index.mdx
25+
│ ├── 01-welcome.mdx
26+
│ ├── 02-what-is-react.mdx
27+
├── 02-types
28+
│ ├── index.mdx
29+
│ ├── 01-primitive-types.mdx
30+
│ ├── 02-arrays.mdx
31+
├─
32+
33+
*/
34+
35+
export default class ContentManager {
36+
private contentFolderPath: string = "./content";
37+
public outline: ContentOutline;
38+
public activeChapterIndex: number = 0;
39+
public activeStepIndex: number = 0;
40+
41+
constructor() {
42+
this.outline = this.generateOutline();
43+
}
44+
45+
public parseMdxFile(relativeFilePath: string) {
46+
const file = fs.readFileSync(
47+
this.contentFolderPath + "/" + relativeFilePath,
48+
"utf-8"
49+
);
50+
const { content, data } = matter(file);
51+
const Page = () => CustomMDX({ source: content });
52+
return { Page, metadata: data };
53+
}
54+
55+
private generateOutline(): ContentOutline {
56+
const contentOutline: ContentOutline = { chapters: [] };
57+
const files = fs.readdirSync(this.contentFolderPath, {
58+
withFileTypes: true,
59+
});
60+
61+
files.forEach((file) => {
62+
if (file.isDirectory()) {
63+
const chapter = { title: file.name, folderName: file.name, steps: [] };
64+
const chapterPath = `${this.contentFolderPath}/${file.name}`;
65+
const chapterFiles = fs.readdirSync(chapterPath, {
66+
withFileTypes: true,
67+
});
68+
contentOutline.chapters.push(chapter);
69+
}
70+
});
71+
72+
return contentOutline;
73+
}
74+
}

lib/fileUtils.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import fs from "fs";
2+
import path from "path";
3+
4+
export function listFiles(directoryPath: string) {
5+
// Initialize an empty array to store file paths
6+
let fileList: any[] = [];
7+
8+
// Get the contents of the directory
9+
const files = fs.readdirSync(directoryPath);
10+
// console.log(files);
11+
// Iterate through each file/directory in the directory
12+
files.forEach((file) => {
13+
// Get the full path of the file/directory
14+
const filePath = path.join(directoryPath, file);
15+
16+
// Check if it's a file or directory
17+
const isFile = fs.statSync(filePath).isFile();
18+
19+
if (isFile) {
20+
// If it's a file, add it to the file list
21+
fileList.push(filePath);
22+
} else {
23+
// If it's a directory, recursively list files in that directory
24+
fileList = fileList.concat(listFiles(filePath));
25+
}
26+
});
27+
28+
return fileList;
29+
}
30+
31+
export function traverseDirectory(dirPath: string) {
32+
const files = fs.readdirSync(dirPath, { withFileTypes: true });
33+
const fileTree: any[] = [];
34+
35+
files.forEach((file) => {
36+
const fullPath = path.join(dirPath, file.name);
37+
if (file.isDirectory()) {
38+
const children = traverseDirectory(fullPath);
39+
fileTree.push({ name: file.name, isDirectory: true, children });
40+
} else {
41+
fileTree.push({ name: file.name, isDirectory: false });
42+
}
43+
});
44+
45+
return fileTree;
46+
}

lib/types.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
type ChapterStep = {
2+
title: string;
3+
fileName: string;
4+
fullPath: string;
5+
};
6+
7+
type Chapter = {
8+
title: string;
9+
folderName: string;
10+
steps: ChapterStep[];
11+
};
12+
13+
export type ContentOutline = {
14+
chapters: Chapter[];
15+
};
16+
17+
export type metadata = {
18+
title: string;
19+
};

mdx-components.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Heading } from "@chakra-ui/react";
2+
import type { MDXComponents } from "mdx/types";
3+
4+
export function useMDXComponents(components: MDXComponents): MDXComponents {
5+
return {
6+
...components,
7+
// chakra-ui overrides heading styles so we need to use the Heading component
8+
// see https://github.com/chakra-ui/chakra-ui/issues/107 for more info
9+
10+
h1: ({ children }) => {
11+
return (
12+
<Heading as="h1" lineHeight={"tall"}>
13+
{children}
14+
</Heading>
15+
);
16+
},
17+
h2: ({ children }) => {
18+
return (
19+
<Heading as="h2" size="lg">
20+
{children}
21+
</Heading>
22+
);
23+
},
24+
h3: ({ children }) => {
25+
return (
26+
<Heading as="h3" size="md">
27+
{children}
28+
</Heading>
29+
);
30+
},
31+
h4: ({ children }) => {
32+
return (
33+
<Heading as="h4" size="sm">
34+
{children}
35+
</Heading>
36+
);
37+
},
38+
h5: ({ children }) => {
39+
return (
40+
<Heading as="h5" size="xs">
41+
{children}
42+
</Heading>
43+
);
44+
},
45+
};
46+
}

0 commit comments

Comments
 (0)