Skip to content

Commit c09b9e0

Browse files
authored
Merge pull request #135 from apecloud/fix/code_with_wordwrap
fix: add mermaid
2 parents cc4e3cf + 8f27579 commit c09b9e0

File tree

13 files changed

+1338
-92
lines changed

13 files changed

+1338
-92
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@
3535
"hastscript": "^9.0.1",
3636
"highlight.js": "^11.11.1",
3737
"lodash": "^4.17.21",
38+
"mermaid": "^11.11.0",
3839
"minisearch": "^7.1.2",
3940
"moment": "^2.30.1",
4041
"mui-message": "^1.1.0",
4142
"next": "^15.4.5",
4243
"next-international": "^1.3.1",
4344
"next-themes": "^0.4.4",
45+
"panzoom": "^9.4.3",
4446
"react": "^19.0.0",
4547
"react-copy-to-clipboard": "^5.1.0",
4648
"react-dom": "^19.0.0",

scripts/generate-docs-index.mjs

Lines changed: 128 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,134 @@ const OUTPUT = path.join(ROOT_DIR, 'public/docs-index.json');
1313
function extractKeywords(text, minLength = 3, maxCount = 20) {
1414
// Common stop words
1515
const stopWords = new Set([
16-
'the', 'is', 'at', 'which', 'on', 'and', 'a', 'to', 'are', 'as', 'was', 'were',
17-
'been', 'be', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
18-
'should', 'may', 'might', 'can', 'must', 'shall', 'of', 'in', 'for', 'with', 'by',
19-
'from', 'up', 'about', 'into', 'through', 'during', 'before', 'after', 'above',
20-
'below', 'to', 'under', 'again', 'further', 'then', 'once', 'here', 'there',
21-
'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more',
22-
'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same',
23-
'so', 'than', 'too', 'very', 'can', 'just', 'now', 'also', 'if', 'this',
24-
'that', 'these', 'those', 'i', 'me', 'my', 'myself', 'we', 'our', 'ours',
25-
'ourselves', 'you', 'your', 'yours', 'yourself', 'yourselves', 'he', 'him',
26-
'his', 'himself', 'she', 'her', 'hers', 'herself', 'it', 'its', 'itself',
27-
'they', 'them', 'their', 'theirs', 'themselves'
16+
'the',
17+
'is',
18+
'at',
19+
'which',
20+
'on',
21+
'and',
22+
'a',
23+
'to',
24+
'are',
25+
'as',
26+
'was',
27+
'were',
28+
'been',
29+
'be',
30+
'have',
31+
'has',
32+
'had',
33+
'do',
34+
'does',
35+
'did',
36+
'will',
37+
'would',
38+
'could',
39+
'should',
40+
'may',
41+
'might',
42+
'can',
43+
'must',
44+
'shall',
45+
'of',
46+
'in',
47+
'for',
48+
'with',
49+
'by',
50+
'from',
51+
'up',
52+
'about',
53+
'into',
54+
'through',
55+
'during',
56+
'before',
57+
'after',
58+
'above',
59+
'below',
60+
'to',
61+
'under',
62+
'again',
63+
'further',
64+
'then',
65+
'once',
66+
'here',
67+
'there',
68+
'when',
69+
'where',
70+
'why',
71+
'how',
72+
'all',
73+
'any',
74+
'both',
75+
'each',
76+
'few',
77+
'more',
78+
'most',
79+
'other',
80+
'some',
81+
'such',
82+
'no',
83+
'nor',
84+
'not',
85+
'only',
86+
'own',
87+
'same',
88+
'so',
89+
'than',
90+
'too',
91+
'very',
92+
'can',
93+
'just',
94+
'now',
95+
'also',
96+
'if',
97+
'this',
98+
'that',
99+
'these',
100+
'those',
101+
'i',
102+
'me',
103+
'my',
104+
'myself',
105+
'we',
106+
'our',
107+
'ours',
108+
'ourselves',
109+
'you',
110+
'your',
111+
'yours',
112+
'yourself',
113+
'yourselves',
114+
'he',
115+
'him',
116+
'his',
117+
'himself',
118+
'she',
119+
'her',
120+
'hers',
121+
'herself',
122+
'it',
123+
'its',
124+
'itself',
125+
'they',
126+
'them',
127+
'their',
128+
'theirs',
129+
'themselves',
28130
]);
29131

30132
const words = text
31133
.toLowerCase()
32134
.replace(/[^\w\s]/g, ' ')
33135
.split(/\s+/)
34-
.filter(word =>
35-
word.length >= minLength &&
36-
!stopWords.has(word) &&
37-
!/^\d+$/.test(word)
136+
.filter(
137+
(word) =>
138+
word.length >= minLength && !stopWords.has(word) && !/^\d+$/.test(word),
38139
);
39140

40141
// Calculate word frequency
41142
const wordCounts = {};
42-
words.forEach(word => {
143+
words.forEach((word) => {
43144
wordCounts[word] = (wordCounts[word] || 0) + 1;
44145
});
45146

@@ -73,7 +174,7 @@ function generateSummary(content, maxLength = 200) {
73174
const lastSentenceEnd = Math.max(
74175
truncated.lastIndexOf('.'),
75176
truncated.lastIndexOf('!'),
76-
truncated.lastIndexOf('?')
177+
truncated.lastIndexOf('?'),
77178
);
78179

79180
if (lastSentenceEnd > maxLength * 0.7) {
@@ -96,7 +197,9 @@ function extractMetadata(filePath, frontmatter) {
96197
docType = 'documentation';
97198

98199
// 从路径中提取产品类别
99-
const productMatch = filePath.match(/docs\/en\/[^/]*\/kubeblocks-for-([^/]+)/);
200+
const productMatch = filePath.match(
201+
/docs\/en\/[^/]*\/kubeblocks-for-([^/]+)/,
202+
);
100203
if (productMatch) {
101204
category = productMatch[1];
102205
} else if (filePath.includes('user_docs')) {
@@ -129,7 +232,7 @@ async function main() {
129232
'blogs/en/**/*.mdx',
130233
'!docs/en/preview/**/cli/**',
131234
'!docs/en/preview/**/release_notes/**',
132-
'!docs/en/release-*/**', // 明确排除所有release版本目录
235+
'!docs/en/release-*/**', // 明确排除所有release版本目录
133236
],
134237
{ cwd: ROOT_DIR, absolute: true },
135238
);
@@ -172,7 +275,7 @@ async function main() {
172275
const headings = [];
173276
const headingMatches = content.match(/^#{1,6}\s+.+$/gm);
174277
if (headingMatches) {
175-
headingMatches.forEach(heading => {
278+
headingMatches.forEach((heading) => {
176279
const level = (heading.match(/^#+/) || [''])[0].length;
177280
const text = heading.replace(/^#+\s+/, '').trim();
178281
headings.push({ level, text });
@@ -181,7 +284,10 @@ async function main() {
181284

182285
return {
183286
id: relPath.replace(/\//g, '_').replace(/\.(md|mdx)$/, ''),
184-
title: data.title || data.sidebar_label || path.basename(file, path.extname(file)),
287+
title:
288+
data.title ||
289+
data.sidebar_label ||
290+
path.basename(file, path.extname(file)),
185291
content: fullContent,
186292
path: normPath,
187293
description: data.description || summary,

src/app/[locale]/ElevationScrollAppBar.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,13 @@ export const ElevationScrollAppBar = (props: AppBarProps) => {
140140
<Box sx={searchBarStyles.container}>
141141
<TextField
142142
size="small"
143-
placeholder={mobile ? "Search..." : "Search docs..."}
143+
placeholder={mobile ? 'Search...' : 'Search docs...'}
144144
variant="outlined"
145145
onClick={() => setShowSearch(true)}
146146
InputProps={{
147-
startAdornment: <SearchIcon sx={searchBarStyles.searchIcon} />,
147+
startAdornment: (
148+
<SearchIcon sx={searchBarStyles.searchIcon} />
149+
),
148150
endAdornment: !mobile && (
149151
<Box sx={searchBarStyles.shortcutContainer}>
150152
<Box component="kbd" sx={searchBarStyles.shortcutKey}>

src/app/api/search-index/route.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { readFileSync, readdirSync, existsSync } from 'fs';
1+
import { existsSync, readFileSync, readdirSync } from 'fs';
22
import matter from 'gray-matter';
33
import { NextResponse } from 'next/server';
44
import { join } from 'path';
55

6+
export const dynamic = 'force-static'; // force-dynamic | force-static
7+
68
interface SearchDocument {
79
id: string;
810
title: string;
@@ -68,15 +70,16 @@ function extractContent(filePath: string): SearchDocument {
6870
.trim();
6971

7072
// 生成摘要
71-
const summary = plainContent.length > 200 ?
72-
plainContent.substring(0, 200) + '...' :
73-
plainContent;
73+
const summary =
74+
plainContent.length > 200
75+
? plainContent.substring(0, 200) + '...'
76+
: plainContent;
7477

7578
// 提取关键词
7679
const keywords = plainContent
7780
.toLowerCase()
7881
.split(/\s+/)
79-
.filter(word => word.length > 3)
82+
.filter((word) => word.length > 3)
8083
.reduce((acc: string[], word) => {
8184
if (!acc.includes(word)) acc.push(word);
8285
return acc;
@@ -87,7 +90,7 @@ function extractContent(filePath: string): SearchDocument {
8790
const headings: Array<{ level: number; text: string }> = [];
8891
const headingMatches = markdownContent.match(/^#{1,6}\s+.+$/gm);
8992
if (headingMatches) {
90-
headingMatches.forEach(heading => {
93+
headingMatches.forEach((heading) => {
9194
const level = (heading.match(/^#+/) || [''])[0].length;
9295
const text = heading.replace(/^#+\s+/, '').trim();
9396
headings.push({ level, text });
@@ -142,19 +145,17 @@ export async function GET() {
142145
const previewDir = join(rootDir, 'docs', 'en', 'preview');
143146
if (existsSync(previewDir)) {
144147
const previewFiles = getAllMdxFiles(previewDir, 'docs/en/preview');
145-
allFiles.push(...previewFiles.map(file => join(rootDir, file)));
148+
allFiles.push(...previewFiles.map((file) => join(rootDir, file)));
146149
}
147150

148151
// 获取blogs/en下的文件
149152
const blogsEnDir = join(rootDir, 'blogs', 'en');
150153
if (existsSync(blogsEnDir)) {
151154
const blogFiles = getAllMdxFiles(blogsEnDir, 'blogs/en');
152-
allFiles.push(...blogFiles.map(file => join(rootDir, file)));
155+
allFiles.push(...blogFiles.map((file) => join(rootDir, file)));
153156
}
154157

155-
const documents = allFiles.map((filePath) =>
156-
extractContent(filePath),
157-
);
158+
const documents = allFiles.map((filePath) => extractContent(filePath));
158159

159160
return NextResponse.json(documents);
160161
} catch (error) {

src/app/sitemap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
3939
);
4040

4141
// ignore some category
42-
if(["release_notes"].includes(category)) {
42+
if (['release_notes'].includes(category)) {
4343
return;
4444
}
4545

0 commit comments

Comments
 (0)