Skip to content

Commit

Permalink
add read markdown
Browse files Browse the repository at this point in the history
  • Loading branch information
woohm402 committed Aug 16, 2024
1 parent 491adb3 commit 789d297
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 11 deletions.
1 change: 1 addition & 0 deletions react/lecture/contents/lecture0/1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# test
1 change: 1 addition & 0 deletions react/lecture/contents/lecture0/2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# test 2
1 change: 1 addition & 0 deletions react/lecture/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"react-router-dom": "6.26.0"
},
"devDependencies": {
"@types/node": "22.3.0",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"@vitejs/plugin-react-swc": "3.7.0",
Expand Down
31 changes: 27 additions & 4 deletions react/lecture/src/app/pages/Lecture/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,42 @@
import { useEffect, useState } from 'react';
import Markdown from 'react-markdown';

import { UsecaseContext } from '@/app/contexts/UsecaseContext';
import { PageComponent } from '@/app/page';
import { useGlobalContext } from '@/app/utils/useGlobalContext';
import { Page } from '@/entities/page';
import { LectureUsecase } from '@/usecases/LectureUsecase';

export const Lecture: PageComponent<Page.LECTURE> = ({ params }) => {
const { markdown } = useGlobalContext(
UsecaseContext,
).lectureUsecase.showLecture(params.lectureIndex);
const [sections, setSections] =
useState<Awaited<ReturnType<LectureUsecase['showLecture']>>['sections']>();

const { lectureUsecase } = useGlobalContext(UsecaseContext);

useEffect(() => {
let ignore = false;

lectureUsecase
.showLecture(params.lectureIndex)
.then((result) => {
if (ignore) return;
setSections(result.sections);
})
.catch(() => {
console.error('Failed to load lecture');
});

return () => {
ignore = true;
};
}, [lectureUsecase, params.lectureIndex]);

return (
<div>
<h1>Lecture {params.lectureIndex}</h1>
<Markdown>{markdown}</Markdown>
{sections?.map((section, index) => (
<Markdown key={index}>{section.markdown}</Markdown>
))}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { contents } from 'virtual:lecture-contents';

import { implLectureUsecase } from '@/usecases/LectureUsecase';

export const implViteVirtualModuleLectureContentRepository = (): Parameters<
typeof implLectureUsecase
>[0]['lectureContentRepository'] => {
return {
loadLectureMarkdowns: ({ lectureIndex }) => {
const found = contents.find(
(c) => c.folder === `lecture${lectureIndex}`,
)?.markdowns;

if (found === undefined) throw new Error('Lecture not found');

return Promise.resolve(found);
},
};
};
5 changes: 4 additions & 1 deletion react/lecture/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

import { implBrowserThemeController } from '@/infrastructures/implBrowserThemeController';
import { implViteVirtualModuleLectureContentRepository } from '@/infrastructures/implViteVirtualModuleLectureContentRepository';
import { implLectureUsecase } from '@/usecases/LectureUsecase';
import { implThemeUsecase } from '@/usecases/ThemeUsecase';

Expand All @@ -14,7 +15,9 @@ const root = document.getElementById('root');
if (root === null) throw new Error('Root element not found');

const sidebarUsecase = implSidebarUsecase();
const lectureUsecase = implLectureUsecase();
const lectureUsecase = implLectureUsecase({
lectureContentRepository: implViteVirtualModuleLectureContentRepository(),
});
const themeUsecase = implThemeUsecase({
themeController: implBrowserThemeController(),
});
Expand Down
23 changes: 19 additions & 4 deletions react/lecture/src/usecases/LectureUsecase/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
import { Lecture } from '@/entities/lecture';

export type LectureUsecase = {
showLecture: (lectureIndex: number) => { markdown: string };
showLecture: (lectureIndex: Lecture['lectureIndex']) => Promise<{
sections: { markdown: string }[];
}>;
};

export const implLectureUsecase = (): LectureUsecase => {
export const implLectureUsecase = ({
lectureContentRepository: lectureContentRepository,
}: {
lectureContentRepository: {
loadLectureMarkdowns: (_: {
lectureIndex: Lecture['lectureIndex'];
}) => Promise<string[]>;
};
}): LectureUsecase => {
return {
showLecture: (lectureIndex) => {
showLecture: async (lectureIndex) => {
const markdowns = await lectureContentRepository.loadLectureMarkdowns({
lectureIndex,
});
return {
markdown: `- Lecture ${lectureIndex}`,
sections: markdowns.map((markdown) => ({ markdown })),
};
},
};
Expand Down
4 changes: 4 additions & 0 deletions react/lecture/src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
/// <reference types="vite/client" />

declare module 'virtual:lecture-contents' {
export const contents: { folder: string; markdowns: string[] }[];
}
46 changes: 44 additions & 2 deletions react/lecture/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,51 @@
import react from '@vitejs/plugin-react-swc';
import { defineConfig } from 'vite';
import fs from 'fs/promises';
import { defineConfig, Plugin } from 'vite';

const lecturePlugin = (): Plugin => {
const virtualModuleId = 'virtual:lecture-contents';

return {
name: 'lecture-plugin',
resolveId(id) {
if (id === virtualModuleId) return virtualModuleId;
},
async load(id) {
if (id === virtualModuleId) {
const folders = await fs.readdir('./contents').catch(() => []);

const foldersWithFiles = await Promise.all(
folders.map(async (folder) => {
const files = (
await fs.readdir(`./contents/${folder}`).catch(() => [])
)
.filter((file) => file.endsWith('.md'))
.sort();

const markdowns = await Promise.all(
files.map(async (file) => {
const markdown = await fs.readFile(
`./contents/${folder}/${file}`,
'utf-8',
);
return markdown;
}),
);

return { folder, markdowns };
}),
);

return `export const contents = ${JSON.stringify(foldersWithFiles)};`;
}
},
};
};

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
plugins: [react(), lecturePlugin()],
server: { port: 3025 },
resolve: { alias: { '@': '/src' } },
assetsInclude: ['**/*.md'],
});
17 changes: 17 additions & 0 deletions react/lecture/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,15 @@ __metadata:
languageName: node
linkType: hard

"@types/node@npm:22.3.0":
version: 22.3.0
resolution: "@types/node@npm:22.3.0"
dependencies:
undici-types: "npm:~6.18.2"
checksum: 10/c31a798ed722a7417727f018ea6d621db038a613c626da643174cc6f3dcf4ce2fc9933a010aec289103d9564da2c2f9b054c9aa398828f00e17269a78c64d4ec
languageName: node
linkType: hard

"@types/prop-types@npm:*":
version: 15.7.12
resolution: "@types/prop-types@npm:15.7.12"
Expand Down Expand Up @@ -2652,6 +2661,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "lecture@workspace:."
dependencies:
"@types/node": "npm:22.3.0"
"@types/react": "npm:18.3.3"
"@types/react-dom": "npm:18.3.0"
"@vitejs/plugin-react-swc": "npm:3.7.0"
Expand Down Expand Up @@ -4294,6 +4304,13 @@ __metadata:
languageName: node
linkType: hard

"undici-types@npm:~6.18.2":
version: 6.18.2
resolution: "undici-types@npm:6.18.2"
checksum: 10/5c863f3cc65d012498cf0f8562b9d81e785c2b8b8a8d66343b9f4351ff40a3a29b500fbaea10667626fd91a32433d4c876810aafa5ab561369de702b62d4b323
languageName: node
linkType: hard

"unified@npm:^11.0.0":
version: 11.0.5
resolution: "unified@npm:11.0.5"
Expand Down

0 comments on commit 789d297

Please sign in to comment.