Skip to content

Commit dd6b823

Browse files
committed
daisyuiのtooltipでtermを実装
1 parent cbd79ae commit dd6b823

3 files changed

Lines changed: 78 additions & 50 deletions

File tree

app/(docs)/@docs/[lang]/[pageId]/page.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import {
1111
getMarkdownSections,
1212
getPagesListForLang,
13+
getTermDefinitions,
1314
LangId,
1415
PagePath,
1516
PageSlug,
@@ -18,6 +19,7 @@ import { cacheLife, cacheTag } from "next/cache";
1819
import { isCloudflare } from "@/lib/detectCloudflare";
1920
import { DocsAutoRedirect } from "./autoRedirect";
2021
import { dateReviver } from "@/lib/dateReviver";
22+
import { TermDefinitionProvider } from "@/markdown/term";
2123

2224
export async function generateMetadata({
2325
params,
@@ -60,17 +62,21 @@ export default async function Page({
6062
const context = await initContext();
6163
const chatHistories = await getChatFromCache(path, context.userId);
6264

65+
const termDefinitions = await getTermDefinitions(lang);
66+
6367
return (
6468
<>
65-
<PageContent
66-
chatHistories={chatHistories}
67-
splitMdContent={sections}
68-
langEntry={langEntry}
69-
pageEntry={pageEntry}
70-
prevPage={prevPage}
71-
nextPage={nextPage}
72-
path={path}
73-
/>
69+
<TermDefinitionProvider termDefinitions={termDefinitions} lang={lang}>
70+
<PageContent
71+
chatHistories={chatHistories}
72+
splitMdContent={sections}
73+
langEntry={langEntry}
74+
pageEntry={pageEntry}
75+
prevPage={prevPage}
76+
nextPage={nextPage}
77+
path={path}
78+
/>
79+
</TermDefinitionProvider>
7480
<DocsAutoRedirect path={path} />
7581
</>
7682
);

app/lib/docs.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ export async function getTermDefinitions(
398398
}
399399
const terms: TermDefinition[] = [];
400400
const langEntry = await getPagesListForLang(langId);
401+
const headingRegex = /^#+(.*)$/m;
401402
const codeBlockRegex = /^(`{3,})(.*)\n([\s\S]*?)\n^\1/gm;
402403
for (const page of langEntry.pages) {
403404
const sections = await getMarkdownSections(langId, page.slug);
@@ -408,10 +409,9 @@ export async function getTermDefinitions(
408409
page: page.slug,
409410
id: section.id,
410411
title: section.title,
411-
rawContentWithoutCode: section.rawContent.replace(
412-
codeBlockRegex,
413-
""
414-
),
412+
rawContentWithoutCode: section.rawContent
413+
.replace(codeBlockRegex, "")
414+
.replace(headingRegex, ""),
415415
});
416416
}
417417
}

app/markdown/term.tsx

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,71 @@
1-
import { JSX } from "react";
1+
"use client";
2+
3+
import { createContext, JSX, ReactNode, useContext } from "react";
24
import { ExtraProps } from "react-markdown";
35
import { onlyText } from "react-children-utilities";
6+
import { LangId, TermDefinition } from "@/lib/docs";
7+
import Link from "next/link";
8+
import { StyledMarkdown } from "./markdown";
9+
10+
const TermDefinitionContext = createContext<{
11+
lang: LangId;
12+
termDefinitions: TermDefinition[];
13+
} | null>(null);
14+
export function TermDefinitionProvider({
15+
lang,
16+
termDefinitions,
17+
children,
18+
}: {
19+
lang: LangId;
20+
termDefinitions: TermDefinition[];
21+
children: ReactNode;
22+
}) {
23+
return (
24+
<TermDefinitionContext.Provider value={{ lang, termDefinitions }}>
25+
{children}
26+
</TermDefinitionContext.Provider>
27+
);
28+
}
429

530
/**
631
* https://github.com/ut-code/utcode-learn/blob/main/src/components/Term/index.tsx をもとに独自実装
732
* Copyright (c) 2023 ut.code();
833
*/
934
export default function Term(props: JSX.IntrinsicElements["q"] & ExtraProps) {
10-
// 動作確認用
11-
return <>[{props.children} → term:{onlyText(props.children)}]</>;
35+
// termDefinitionの取得がasync関数であり、clientコンポーネントから直接取得できないので、
36+
// @docs/lang/pageId/page.tsx で取得したものをcontextに渡してそれを取得する
37+
const { lang, termDefinitions } = useContext(TermDefinitionContext) ?? {};
38+
39+
if (!termDefinitions) {
40+
return props.children;
41+
}
1242

13-
// const term = props.id
14-
// ? terms.find((term) => term.id === props.id)
15-
// : terms.find(
16-
// (term) =>
17-
// term.name === onlyText(props.children) ||
18-
// term.aliases.includes(onlyText(props.children)),
19-
// );
20-
// if (!term)
21-
// throw new Error(
22-
// `${props.id ? props.id : onlyText(props.children)}という用語は定義されていません`,
23-
// );
43+
const termText = onlyText(props.children);
44+
const term = termDefinitions.find((t) => t.term.includes(termText));
45+
if (!term) {
46+
console.error(`'${termText}'という用語は定義されていません`);
47+
return props.children;
48+
}
2449

25-
// const wrap = (content: JSX.Element) => {
50+
// [{props.children} → term:{onlyText(props.children)}]
2651

27-
// return (
28-
// <Tippy
29-
// theme="material"
30-
// interactive={shouldLinkToReferencePage}
31-
// appendTo={window.document.body}
32-
// content={
33-
// <div className={styles.tooltipContent}>
34-
// <header className={styles.tooltipContentHeader}>{term.name}</header>
35-
// <div>{term.definition}</div>
36-
// {shouldLinkToReferencePage && (
37-
// <Link className={styles.tooltipLink} to={term.referencePage}>
38-
// <span>{referencePageTitle} へ</span>
39-
// <MdArrowForward size="1.2rem" />
40-
// </Link>
41-
// )}
42-
// </div>
43-
// }
44-
// >
45-
// {content}
46-
// </Tippy>
47-
// );
48-
// };
52+
return (
53+
<span className="tooltip tooltip-primary">
54+
<span className="tooltip-content bg-primary-content/60 border border-primary text-base-content backdrop-blur-xs">
55+
<span className="breadcrumbs text-info text-center text-base wrap-none mb-4">
56+
<ul className="">
57+
<li>{term.page}</li>
58+
<li>{term.title}</li>
59+
</ul>
60+
</span>
61+
<StyledMarkdown content={term.rawContentWithoutCode} />
62+
</span>
63+
<Link
64+
href={`/${lang}/${term.page}#${term.id}`}
65+
className="link link-info decoration-dotted underline-offset-[0.2rem]"
66+
>
67+
{props.children}
68+
</Link>
69+
</span>
70+
);
4971
}

0 commit comments

Comments
 (0)