Skip to content

Commit 58825e9

Browse files
committed
embedContentとmdSectionをリファクタリングしました
1 parent bfaf9f3 commit 58825e9

File tree

14 files changed

+312
-335
lines changed

14 files changed

+312
-335
lines changed

app/[docs_id]/chatForm.tsx

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,33 @@ import { type Message } from "../hooks/useChathistory";
66
import useSWR from "swr";
77
import { getQuestionExample } from "../actions/questionExample";
88
import { getLanguageName } from "../pagesList";
9-
import { MarkdownSection } from "./splitMarkdown";
10-
import { useEmbed } from "./embedContext";
11-
import { useFile } from "../terminal/file";
9+
import { DynamicMarkdownSection } from "./pageContent";
10+
import { useEmbedContext } from "../terminal/embedContext";
1211

1312
interface ChatFormProps {
1413
docs_id: string;
1514
documentContent: string;
16-
splitMdContent: MarkdownSection[];
17-
sectionInView: boolean[];
18-
onClose: () => void;
15+
sectionContent: DynamicMarkdownSection[];
16+
close: () => void;
1917
}
2018

2119
export function ChatForm({
2220
docs_id,
2321
documentContent,
24-
splitMdContent,
25-
sectionInView,
26-
onClose,
22+
sectionContent,
23+
close,
2724
}: ChatFormProps) {
2825
// const [messages, updateChatHistory] = useChatHistory(sectionId);
2926
const [inputValue, setInputValue] = useState("");
3027
const [isLoading, setIsLoading] = useState(false);
3128

3229
const lang = getLanguageName(docs_id);
3330

34-
const { replOutputs, execResults } = useEmbed()!;
35-
const { files } = useFile();
31+
const { files, replOutputs, execResults } = useEmbedContext();
3632

37-
const documentContentInView = splitMdContent
38-
.filter((_, index) => sectionInView[index])
39-
.map(
40-
(section) =>
41-
`${"#".repeat(section.level)} ${section.title}\n${section.content}`
42-
)
33+
const documentContentInView = sectionContent
34+
.filter((s) => s.inView)
35+
.map((s) => s.rawContent)
4336
.join("\n\n");
4437
const { data: exampleData, error: exampleError } = useSWR(
4538
// 質問フォームを開いたときだけで良い
@@ -68,7 +61,7 @@ export function ChatForm({
6861
e.preventDefault();
6962
setIsLoading(true);
7063

71-
const userMessage: Message = { sender: "user", text: inputValue };
64+
// const userMessage: Message = { sender: "user", text: inputValue };
7265
// updateChatHistory([userMessage]);
7366

7467
let userQuestion = inputValue;
@@ -82,8 +75,7 @@ export function ChatForm({
8275
const result = await askAI({
8376
userQuestion,
8477
documentContent,
85-
splitMdContent,
86-
sectionInView,
78+
sectionContent,
8779
replOutputs,
8880
files,
8981
execResults,
@@ -147,7 +139,7 @@ export function ChatForm({
147139
<div className="left-icons">
148140
<button
149141
className="btn btn-soft btn-secondary rounded-full"
150-
onClick={onClose}
142+
onClick={close}
151143
type="button"
152144
>
153145
閉じる

app/[docs_id]/embedContext.tsx

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

app/[docs_id]/page.tsx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { join } from "node:path";
55
import { MarkdownSection, splitMarkdown } from "./splitMarkdown";
66
import pyodideLock from "pyodide/pyodide-lock.json";
77
import { PageContent } from "./pageContent";
8-
import { EmbedContextProvider } from "./embedContext";
98

109
export default async function Page({
1110
params,
@@ -42,15 +41,13 @@ export default async function Page({
4241
String(pyodideLock.info.python)
4342
);
4443

45-
const splitMdContent: MarkdownSection[] = await splitMarkdown(mdContent);
44+
const splitMdContent: MarkdownSection[] = splitMarkdown(mdContent);
4645

4746
return (
48-
<EmbedContextProvider>
49-
<PageContent
50-
documentContent={mdContent}
51-
splitMdContent={splitMdContent}
52-
docs_id={docs_id}
53-
/>
54-
</EmbedContextProvider>
47+
<PageContent
48+
documentContent={mdContent}
49+
splitMdContent={splitMdContent}
50+
docs_id={docs_id}
51+
/>
5552
);
5653
}

app/[docs_id]/pageContent.tsx

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,59 @@ import { useEffect, useRef, useState } from "react";
44
import { Section } from "./section";
55
import { MarkdownSection } from "./splitMarkdown";
66
import { ChatForm } from "./chatForm";
7-
import { useEmbed } from "./embedContext";
7+
8+
// MarkdownSectionに追加で、ユーザーが今そのセクションを読んでいるかどうか、などの動的な情報を持たせる
9+
export type DynamicMarkdownSection = MarkdownSection & {
10+
inView: boolean;
11+
sectionId: string;
12+
};
813

914
interface PageContentProps {
1015
documentContent: string;
1116
splitMdContent: MarkdownSection[];
1217
docs_id: string;
1318
}
1419
export function PageContent(props: PageContentProps) {
15-
// 各セクションが画面内にあるかどうかを調べる
16-
const [sectionInView, setSectionInView] = useState<boolean[]>([]);
20+
const [dynamicMdContent, setDynamicMdContent] = useState<
21+
DynamicMarkdownSection[]
22+
>(
23+
// useEffectで更新するのとは別に、SSRのための初期値
24+
props.splitMdContent.map((section, i) => ({
25+
...section,
26+
inView: false,
27+
sectionId: `${props.docs_id}-${i}`,
28+
}))
29+
);
30+
useEffect(() => {
31+
// props.splitMdContentが変わったときにdynamicMdContentを更新
32+
setDynamicMdContent(
33+
props.splitMdContent.map((section, i) => ({
34+
...section,
35+
inView: false,
36+
sectionId: `${props.docs_id}-${i}`,
37+
}))
38+
);
39+
}, [props.splitMdContent, props.docs_id]);
40+
1741
const sectionRefs = useRef<Array<HTMLDivElement | null>>([]);
1842
// sectionRefsの長さをsplitMdContentに合わせる
1943
while (sectionRefs.current.length < props.splitMdContent.length) {
2044
sectionRefs.current.push(null);
2145
}
22-
sectionRefs.current = sectionRefs.current.slice(
23-
0,
24-
props.splitMdContent.length
25-
);
2646

2747
useEffect(() => {
2848
const handleScroll = () => {
29-
const newSectionInView = sectionRefs.current.map((sectionRef) => {
30-
if (sectionRef) {
31-
const rect = sectionRef.getBoundingClientRect();
32-
return rect.top < window.innerHeight && rect.bottom >= 0;
49+
setDynamicMdContent((prevDynamicMdContent) => {
50+
const dynMdContent = prevDynamicMdContent.slice(); // Reactの変更検知のために新しい配列を作成
51+
for (let i = 0; i < sectionRefs.current.length; i++) {
52+
if (sectionRefs.current.at(i) && dynMdContent.at(i)) {
53+
const rect = sectionRefs.current.at(i)!.getBoundingClientRect();
54+
dynMdContent.at(i)!.inView =
55+
rect.top < window.innerHeight && rect.bottom >= 0;
56+
}
3357
}
34-
return false;
58+
return dynMdContent;
3559
});
36-
setSectionInView(newSectionInView);
3760
};
3861
window.addEventListener("scroll", handleScroll);
3962
handleScroll();
@@ -46,28 +69,24 @@ export function PageContent(props: PageContentProps) {
4669

4770
return (
4871
<div className="p-4">
49-
{props.splitMdContent.map((section, index) => {
50-
const sectionId = `${props.docs_id}-${index}`;
51-
return (
72+
{dynamicMdContent.map((section, index) =>
5273
<div
5374
key={index}
5475
id={`${index}`} // 目次からaタグで飛ぶために必要
5576
ref={(el) => {
5677
sectionRefs.current[index] = el;
5778
}}
5879
>
59-
<Section section={section} sectionId={sectionId} />
80+
<Section section={section} sectionId={section.sectionId} />
6081
</div>
61-
);
62-
})}
82+
)}
6383
{isFormVisible ? (
6484
<div className="fixed bottom-4 inset-x-4 z-50">
6585
<ChatForm
6686
documentContent={props.documentContent}
67-
splitMdContent={props.splitMdContent}
68-
sectionInView={sectionInView}
87+
sectionContent={dynamicMdContent}
6988
docs_id={props.docs_id}
70-
onClose={() => setIsFormVisible(false)}
89+
close={() => setIsFormVisible(false)}
7190
/>
7291
</div>
7392
) : (

app/[docs_id]/splitMarkdown.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export interface MarkdownSection {
66
level: number;
77
title: string;
88
content: string;
9+
rawContent: string; // 見出しも含めたもとのmarkdownの内容
910
}
1011
/**
1112
* Markdownコンテンツを見出しごとに分割し、
@@ -36,6 +37,10 @@ export function splitMarkdown(content: string): MarkdownSection[] {
3637
.join("\n")
3738
.trim(),
3839
level: headingNodes.at(i)!.depth,
40+
rawContent: splitContent
41+
.slice(startLine - 1, endLine ? endLine - 1 : undefined)
42+
.join("\n")
43+
.trim(),
3944
});
4045
}
4146
return sections;

0 commit comments

Comments
 (0)