mcp-probe-kit 3.0.5 → 3.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +458 -431
- package/build/index.js +875 -141
- package/build/lib/gitnexus-bridge.d.ts +58 -0
- package/build/lib/gitnexus-bridge.js +379 -0
- package/build/lib/template-loader.js +317 -317
- package/build/lib/tool-execution-context.d.ts +8 -0
- package/build/lib/tool-execution-context.js +20 -0
- package/build/lib/toolset-manager.d.ts +1 -1
- package/build/lib/toolset-manager.js +7 -5
- package/build/schemas/code-analysis-tools.d.ts +46 -0
- package/build/schemas/code-analysis-tools.js +47 -0
- package/build/schemas/git-tools.js +16 -16
- package/build/schemas/index.d.ts +46 -0
- package/build/tools/__tests__/code_insight.unit.test.d.ts +1 -0
- package/build/tools/__tests__/code_insight.unit.test.js +35 -0
- package/build/tools/__tests__/start_bugfix.unit.test.js +14 -14
- package/build/tools/__tests__/start_ui.unit.test.js +11 -11
- package/build/tools/add_feature.js +79 -79
- package/build/tools/ask_user.js +5 -5
- package/build/tools/code_insight.d.ts +8 -0
- package/build/tools/code_insight.js +129 -0
- package/build/tools/index.d.ts +1 -0
- package/build/tools/index.js +1 -0
- package/build/tools/interview.js +9 -9
- package/build/tools/start_bugfix.d.ts +2 -1
- package/build/tools/start_bugfix.js +170 -126
- package/build/tools/start_feature.d.ts +2 -1
- package/build/tools/start_feature.js +156 -112
- package/build/tools/start_onboard.d.ts +2 -1
- package/build/tools/start_onboard.js +57 -51
- package/build/tools/start_product.d.ts +2 -1
- package/build/tools/start_product.js +9 -1
- package/build/tools/start_ralph.d.ts +2 -1
- package/build/tools/start_ralph.js +9 -3
- package/build/tools/start_ui.d.ts +2 -1
- package/build/tools/start_ui.js +102 -88
- package/build/tools/ui-ux-tools.d.ts +2 -1
- package/build/tools/ui-ux-tools.js +19 -3
- package/build/utils/ui-sync.d.ts +6 -2
- package/build/utils/ui-sync.js +125 -29
- package/docs/assets/font/MaterialSymbolsOutlined.codepoints +4102 -0
- package/docs/assets/font/MaterialSymbolsOutlined.ttf +0 -0
- package/docs/assets/font/noto-sans-sc-400.ttf +0 -0
- package/docs/assets/font/noto-sans-sc-700.ttf +0 -0
- package/docs/assets/font/noto-sans-sc-900.ttf +0 -0
- package/docs/assets/js/i18n.js +122 -21
- package/docs/assets/js/tailwind.js +83 -83
- package/docs/data/tools.js +419 -399
- package/docs/debug-i18n.html +163 -0
- package/docs/i18n/all-tools/en.json +157 -0
- package/docs/i18n/all-tools/ja.json +157 -0
- package/docs/i18n/all-tools/ko.json +157 -0
- package/docs/i18n/all-tools/zh-CN.json +157 -0
- package/docs/pages/all-tools.html +514 -352
- package/docs/pages/examples.html +689 -689
- package/docs/pages/getting-started.html +589 -589
- package/docs/pages/migration.html +298 -298
- package/docs/specs/user-auth/design.md +82 -0
- package/docs/specs/user-auth/requirements.md +52 -0
- package/docs/specs/user-auth/tasks.md +55 -0
- package/package.json +5 -5
- package/docs/project-context/architecture.md +0 -0
- package/docs/project-context/how-to-develop.md +0 -313
- package/docs/project-context/how-to-test.md +0 -457
- package/docs/project-context/tech-stack.md +0 -96
- package/docs/project-context.md +0 -53
- package/docs/specs/git-work-report/design.md +0 -568
- package/docs/specs/git-work-report/requirements.md +0 -131
- package/docs/specs/git-work-report/tasks.md +0 -197
|
@@ -1,352 +1,514 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>所有工具 - 20个AI研发工具完整列表 | MCP Probe Kit</title>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<meta name="
|
|
10
|
-
<meta name="
|
|
11
|
-
<meta name="
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<script>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.sidebar-drawer
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
.backdrop
|
|
46
|
-
|
|
47
|
-
</
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<span
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<a href="
|
|
77
|
-
<span
|
|
78
|
-
<span
|
|
79
|
-
</a>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
<div class="flex items-center gap-2">
|
|
90
|
-
<span
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<a href="./
|
|
108
|
-
<span
|
|
109
|
-
<span
|
|
110
|
-
</a>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
<span
|
|
121
|
-
<span
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
<
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
<span
|
|
161
|
-
<span
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
<span
|
|
165
|
-
<span>·</span>
|
|
166
|
-
<span
|
|
167
|
-
<span>·</span>
|
|
168
|
-
<
|
|
169
|
-
<span>·</span>
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
</
|
|
352
|
-
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>所有工具 - 20个AI研发工具完整列表 | MCP Probe Kit</title>
|
|
7
|
+
<meta name="i18n-title" content="所有工具 - 21个AI研发工具完整列表 | MCP Probe Kit">
|
|
8
|
+
|
|
9
|
+
<meta name="description" content="MCP Probe Kit 完整工具列表:6个工作流编排工具、3个代码分析工具、1个Git工具、1个生成工具、7个项目管理工具、3个UI/UX工具。">
|
|
10
|
+
<meta name="keywords" content="AI 开发工具, 代码生成工具, 代码审查工具, Git 自动化, UI 生成, 代码重构, 性能优化, 安全扫描">
|
|
11
|
+
<meta name="author" content="小墨 (Kyle) - ByteZoneX">
|
|
12
|
+
<meta name="robots" content="index, follow">
|
|
13
|
+
|
|
14
|
+
<script src="../assets/js/tailwind.js" data-cfasync="false"></script>
|
|
15
|
+
<script>
|
|
16
|
+
tailwind.config = {
|
|
17
|
+
theme: {
|
|
18
|
+
extend: {
|
|
19
|
+
colors: {
|
|
20
|
+
primary: { DEFAULT: '#2563EB', hover: '#1D4ED8' },
|
|
21
|
+
text: { primary: '#0F172A', secondary: '#475569', tertiary: '#64748B' },
|
|
22
|
+
bg: { page: '#F8FAFC', card: '#FFFFFF', hover: '#F1F5F9' },
|
|
23
|
+
border: '#E2E8F0',
|
|
24
|
+
},
|
|
25
|
+
fontFamily: {
|
|
26
|
+
sans: ['-apple-system', 'BlinkMacSystemFont', '"PingFang SC"', '"Microsoft YaHei"', '"Segoe UI"', 'Roboto', '"Helvetica Neue"', 'Arial', '"Noto Sans CJK SC"', 'sans-serif'],
|
|
27
|
+
mono: ['ui-monospace', '"SF Mono"', '"Cascadia Code"', '"Consolas"', 'Menlo', 'Monaco', '"PingFang SC"', '"Microsoft YaHei"', '"Courier New"', 'monospace']
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
<style>
|
|
34
|
+
html {
|
|
35
|
+
scroll-behavior: smooth;
|
|
36
|
+
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans CJK SC", sans-serif;
|
|
37
|
+
}
|
|
38
|
+
code, kbd, pre, samp { font-family: ui-monospace, "SF Mono", "Cascadia Code", "Consolas", Menlo, Monaco, "PingFang SC", "Microsoft YaHei", "Courier New", monospace; }
|
|
39
|
+
.code-block { overflow-x: auto; -webkit-overflow-scrolling: touch; }
|
|
40
|
+
.sidebar-drawer { transition: transform 0.3s ease; }
|
|
41
|
+
@media (max-width: 767px) {
|
|
42
|
+
.sidebar-drawer { transform: translateX(-100%); }
|
|
43
|
+
.sidebar-drawer.open { transform: translateX(0); }
|
|
44
|
+
}
|
|
45
|
+
.backdrop { opacity: 0; pointer-events: none; transition: opacity 0.3s ease; }
|
|
46
|
+
.backdrop.active { opacity: 1; pointer-events: auto; }
|
|
47
|
+
</style>
|
|
48
|
+
</head>
|
|
49
|
+
<body>
|
|
50
|
+
<!-- A. 顶部导航栏 -->
|
|
51
|
+
<nav class="fixed top-0 left-0 right-0 h-14 bg-white/95 backdrop-blur-md border-b border-border z-50">
|
|
52
|
+
<div class="h-full px-4 flex items-center justify-between">
|
|
53
|
+
<a href="../index.html" class="flex items-center gap-2 text-base font-semibold text-text-primary no-underline">
|
|
54
|
+
<span>🚀</span>
|
|
55
|
+
<span class="sm:inline hidden">MCP Probe Kit</span>
|
|
56
|
+
</a>
|
|
57
|
+
<div class="flex items-center gap-3">
|
|
58
|
+
<div id="lang-switcher-container"></div>
|
|
59
|
+
<button onclick="toggleSidebar()" class="md:hidden p-2 text-text-secondary hover:text-primary transition-colors">
|
|
60
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
61
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
|
62
|
+
</svg>
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</nav>
|
|
67
|
+
|
|
68
|
+
<!-- 侧边栏遮罩 -->
|
|
69
|
+
<div class="fixed inset-0 bg-black/50 z-40 backdrop opacity-0 pointer-events-none transition-opacity duration-300 md:hidden" onclick="toggleSidebar()" id="backdrop"></div>
|
|
70
|
+
|
|
71
|
+
<!-- B. 侧边栏 -->
|
|
72
|
+
<aside class="fixed left-0 top-14 bottom-0 w-64 bg-white border-r border-border z-50 sidebar-drawer overflow-y-auto md:translate-x-0 md:block" id="sidebar">
|
|
73
|
+
<div class="p-4">
|
|
74
|
+
<div class="mb-4">
|
|
75
|
+
<div class="text-xs font-semibold text-text-tertiary uppercase tracking-wider mb-2 px-2" data-i18n="sidebar.quickStart">快速开始</div>
|
|
76
|
+
<a href="../index.html" class="flex items-center gap-2 px-3 py-2 rounded-md text-sm text-text-secondary hover:bg-bg-page hover:text-primary transition-colors no-underline">
|
|
77
|
+
<span>🏠</span>
|
|
78
|
+
<span data-i18n="sidebar.home">文档首页</span>
|
|
79
|
+
</a>
|
|
80
|
+
<a href="./getting-started.html" class="flex items-center gap-2 px-3 py-2 rounded-md text-sm text-text-secondary hover:bg-bg-page hover:text-primary transition-colors no-underline">
|
|
81
|
+
<span>📖</span>
|
|
82
|
+
<span data-i18n="sidebar.installation">安装配置</span>
|
|
83
|
+
</a>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div class="mb-4">
|
|
87
|
+
<div class="text-xs font-semibold text-text-tertiary uppercase tracking-wider mb-2 px-2" data-i18n="sidebar.toolsDocs">工具文档</div>
|
|
88
|
+
<button onclick="toggleToolsMenu()" class="w-full flex items-center justify-between px-3 py-2 rounded-md text-sm font-medium bg-blue-50 text-primary border-l-3 border-primary hover:bg-bg-page transition-colors">
|
|
89
|
+
<div class="flex items-center gap-2">
|
|
90
|
+
<span>🛠️</span>
|
|
91
|
+
<span data-i18n="sidebar.allTools">所有工具</span>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="flex items-center gap-2">
|
|
94
|
+
<span class="bg-bg-page text-xs px-2 py-0.5 rounded-full">21</span>
|
|
95
|
+
<svg class="w-4 h-4 transition-transform" id="tools-menu-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
96
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
97
|
+
</svg>
|
|
98
|
+
</div>
|
|
99
|
+
</button>
|
|
100
|
+
<div id="tools-submenu" class="hidden mt-1 ml-4 space-y-1">
|
|
101
|
+
<!-- 工具列表将通过 JavaScript 动态生成 -->
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<div class="mb-4">
|
|
106
|
+
<div class="text-xs font-semibold text-text-tertiary uppercase tracking-wider mb-2 px-2" data-i18n="sidebar.guides">指南</div>
|
|
107
|
+
<a href="./migration.html" class="flex items-center gap-2 px-3 py-2 rounded-md text-sm text-text-secondary hover:bg-bg-page hover:text-primary transition-colors no-underline">
|
|
108
|
+
<span>🚀</span>
|
|
109
|
+
<span data-i18n="sidebar.migration">迁移指南</span>
|
|
110
|
+
</a>
|
|
111
|
+
<a href="./examples.html" class="flex items-center gap-2 px-3 py-2 rounded-md text-sm text-text-secondary hover:bg-bg-page hover:text-primary transition-colors no-underline">
|
|
112
|
+
<span>💡</span>
|
|
113
|
+
<span data-i18n="sidebar.examples">最佳实践</span>
|
|
114
|
+
</a>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div class="pt-4 border-t border-border">
|
|
118
|
+
<a href="https://github.com/mybolide/mcp-probe-kit" target="_blank" rel="noopener" class="flex items-center gap-2 px-3 py-2 rounded-md text-sm text-text-secondary hover:bg-bg-page hover:text-primary transition-colors no-underline">
|
|
119
|
+
<span>💻</span>
|
|
120
|
+
<span>GitHub</span>
|
|
121
|
+
<span class="ml-auto text-xs">↗</span>
|
|
122
|
+
</a>
|
|
123
|
+
<a href="https://www.npmjs.com/package/mcp-probe-kit" target="_blank" rel="noopener" class="flex items-center gap-2 px-3 py-2 rounded-md text-sm text-text-secondary hover:bg-bg-page hover:text-primary transition-colors no-underline">
|
|
124
|
+
<span>📦</span>
|
|
125
|
+
<span>npm</span>
|
|
126
|
+
<span class="ml-auto text-xs">↗</span>
|
|
127
|
+
</a>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<!-- QR Code -->
|
|
131
|
+
<div class="mt-4 pt-4 border-t border-border">
|
|
132
|
+
<div class="text-center">
|
|
133
|
+
<div class="text-xs font-semibold text-text-tertiary mb-2" data-i18n="sidebar.followUs">关注公众号</div>
|
|
134
|
+
<img src="https://oss.bolzjb.com/wx_qrcode.jpg" alt="微信公众号" class="w-[100px] h-[100px] mx-auto rounded-lg border border-border" />
|
|
135
|
+
<div class="text-xs text-text-tertiary mt-2" data-i18n="sidebar.getTechSharing">获取更多技术分享</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</aside>
|
|
140
|
+
|
|
141
|
+
<!-- C. 主内容区 -->
|
|
142
|
+
<main class="flex-1 mt-14 min-h-screen md:ml-64">
|
|
143
|
+
<div class="max-w-5xl mx-auto p-4 sm:p-6 lg:p-8">
|
|
144
|
+
|
|
145
|
+
<!-- 面包屑 -->
|
|
146
|
+
<nav class="flex items-center gap-1 text-sm text-text-secondary mb-4 overflow-x-auto whitespace-nowrap">
|
|
147
|
+
<a href="../index.html" class="hover:text-primary transition-colors no-underline flex-shrink-0" data-i18n="sidebar.home">文档首页</a>
|
|
148
|
+
<span class="text-text-tertiary">/</span>
|
|
149
|
+
<span class="text-text-primary flex-shrink-0" data-i18n="sidebar.toolsDocs">工具文档</span>
|
|
150
|
+
<span class="text-text-tertiary">/</span>
|
|
151
|
+
<span class="text-text-primary flex-shrink-0" data-i18n="sidebar.allTools">所有工具</span>
|
|
152
|
+
</nav>
|
|
153
|
+
|
|
154
|
+
<!-- 页面标题 -->
|
|
155
|
+
<div class="mb-6">
|
|
156
|
+
<h1 class="text-2xl sm:text-3xl font-bold text-text-primary mb-2" data-i18n="sidebar.allTools">所有工具</h1>
|
|
157
|
+
<p class="text-sm sm:text-base text-text-secondary" id="page-subtitle">MCP Probe Kit 提供 21 个实用工具,核心与编排工具支持结构化输出</p>
|
|
158
|
+
<div class="flex flex-wrap items-center gap-2 mt-3 text-xs text-text-tertiary">
|
|
159
|
+
<span class="bg-blue-100 text-blue-700 px-2 py-0.5 rounded">v3.0.5</span>
|
|
160
|
+
<span>MCP 2025-11-25</span>
|
|
161
|
+
<span>SDK 1.27.1</span>
|
|
162
|
+
</div>
|
|
163
|
+
<div class="flex flex-wrap items-center gap-2 mt-2 text-xs text-text-tertiary">
|
|
164
|
+
<span>📦 v3.0.5</span>
|
|
165
|
+
<span>·</span>
|
|
166
|
+
<span><span data-i18n="footer.lastUpdate">最后更新</span>:2026-02-04</span>
|
|
167
|
+
<span>·</span>
|
|
168
|
+
<span><span data-i18n="footer.protocol">协议</span>:MCP 2025-11-25</span>
|
|
169
|
+
<span>·</span>
|
|
170
|
+
<span><span data-i18n="footer.sdk">SDK</span>:@modelcontextprotocol/sdk 1.27.1</span>
|
|
171
|
+
<span>·</span>
|
|
172
|
+
<a href="https://github.com/mybolide/mcp-probe-kit/edit/main/docs/pages/all-tools.html" target="_blank" rel="noopener" class="text-primary hover:underline"><span data-i18n="footer.editPage">编辑此页</span> ↗</a>
|
|
173
|
+
<span>·</span>
|
|
174
|
+
<a href="https://github.com/mybolide/mcp-probe-kit/issues/new" target="_blank" rel="noopener" class="text-primary hover:underline"><span data-i18n="footer.reportIssue">反馈问题</span> ↗</a>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
|
|
178
|
+
<!-- 搜索框 -->
|
|
179
|
+
<div class="mb-6">
|
|
180
|
+
<input
|
|
181
|
+
type="text"
|
|
182
|
+
id="searchInput"
|
|
183
|
+
placeholder="🔍 搜索工具名称或描述..."
|
|
184
|
+
autocomplete="off"
|
|
185
|
+
class="w-full px-4 py-2.5 border border-border rounded-lg text-sm text-text-primary bg-white placeholder-text-tertiary focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
|
|
186
|
+
/>
|
|
187
|
+
<div id="searchResults" class="mt-2 text-sm text-text-tertiary"></div>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
<!-- 工具列表容器 -->
|
|
191
|
+
<div id="tools-container"></div>
|
|
192
|
+
|
|
193
|
+
<!-- Footer -->
|
|
194
|
+
<footer class="text-center text-sm text-text-tertiary py-4 border-t border-border mt-8">
|
|
195
|
+
<p>Made with ❤️ by <a href="https://www.bytezonex.com/" target="_blank" rel="noopener" class="text-primary hover:underline">小墨 (Kyle)</a></p>
|
|
196
|
+
<p class="mt-1">© 2024-2026 MCP Probe Kit · <a href="https://github.com/mybolide/mcp-probe-kit" target="_blank" rel="noopener" class="text-primary hover:underline">GitHub ↗</a></p>
|
|
197
|
+
</footer>
|
|
198
|
+
</div>
|
|
199
|
+
</main>
|
|
200
|
+
|
|
201
|
+
<!-- 引入工具数据 -->
|
|
202
|
+
<script src="../data/tools.js"></script>
|
|
203
|
+
<script src="../assets/js/i18n.js?v=20260204-3"></script>
|
|
204
|
+
<script>
|
|
205
|
+
// 应用翻译到工具数据(使用 i18n.js 加载的翻译)
|
|
206
|
+
function applyTranslationsToTools() {
|
|
207
|
+
const currentLang = window.currentLang || 'zh-CN';
|
|
208
|
+
const translations = window.translations && window.translations[currentLang] || {};
|
|
209
|
+
|
|
210
|
+
console.log('[all-tools] Applying translations for language:', currentLang);
|
|
211
|
+
console.log('[all-tools] Translations data:', translations);
|
|
212
|
+
|
|
213
|
+
// 更新页面标题
|
|
214
|
+
if (translations.meta && translations.meta.title) {
|
|
215
|
+
document.title = translations.meta.title;
|
|
216
|
+
console.log('[all-tools] Updated title:', translations.meta.title);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 更新 meta 标签
|
|
220
|
+
if (translations.meta) {
|
|
221
|
+
const descMeta = document.querySelector('meta[name="description"]');
|
|
222
|
+
const keywordsMeta = document.querySelector('meta[name="keywords"]');
|
|
223
|
+
if (descMeta && translations.meta.description) descMeta.content = translations.meta.description;
|
|
224
|
+
if (keywordsMeta && translations.meta.keywords) keywordsMeta.content = translations.meta.keywords;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 更新页面副标题(使用 ID 选择器)
|
|
228
|
+
if (translations.page) {
|
|
229
|
+
const subtitleEl = document.getElementById('page-subtitle');
|
|
230
|
+
if (subtitleEl && translations.page.subtitle) {
|
|
231
|
+
subtitleEl.textContent = translations.page.subtitle;
|
|
232
|
+
console.log('[all-tools] Updated subtitle:', translations.page.subtitle);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// 更新搜索框占位符
|
|
237
|
+
const searchInput = document.getElementById('searchInput');
|
|
238
|
+
if (searchInput && translations.search && translations.search.placeholder) {
|
|
239
|
+
searchInput.placeholder = translations.search.placeholder;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// 更新分类标题
|
|
243
|
+
if (translations.categories) {
|
|
244
|
+
for (const catKey in toolsData.categories) {
|
|
245
|
+
if (translations.categories[catKey]) {
|
|
246
|
+
toolsData.categories[catKey].title = translations.categories[catKey].title || toolsData.categories[catKey].title;
|
|
247
|
+
console.log(`[all-tools] Updated category ${catKey}:`, toolsData.categories[catKey].title);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// 更新 toolsData 中的工具描述和参数
|
|
253
|
+
const toolsTrans = translations.toolsData || {};
|
|
254
|
+
for (const categoryKey in toolsData) {
|
|
255
|
+
if (categoryKey === 'categories') continue;
|
|
256
|
+
|
|
257
|
+
toolsData[categoryKey].forEach(tool => {
|
|
258
|
+
const toolTrans = toolsTrans[tool.name];
|
|
259
|
+
if (toolTrans) {
|
|
260
|
+
tool.description = toolTrans.description || tool.description;
|
|
261
|
+
if (toolTrans.usage) tool.usage = toolTrans.usage;
|
|
262
|
+
if (toolTrans.example) tool.example = toolTrans.example;
|
|
263
|
+
|
|
264
|
+
// 更新参数描述
|
|
265
|
+
if (toolTrans.params && tool.params) {
|
|
266
|
+
tool.params.forEach(param => {
|
|
267
|
+
const paramTrans = toolTrans.params.find(p => p.name === param.name);
|
|
268
|
+
if (paramTrans && paramTrans.desc) {
|
|
269
|
+
param.desc = paramTrans.desc;
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// 重置 allTools 数组
|
|
278
|
+
allTools = [];
|
|
279
|
+
for (const [categoryKey, tools] of Object.entries(toolsData)) {
|
|
280
|
+
if (categoryKey === 'categories') continue;
|
|
281
|
+
tools.forEach(tool => { allTools.push({ ...tool, category: categoryKey }); });
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// 调用 i18n.js 的 applyTranslations() 来处理 data-i18n 属性
|
|
285
|
+
if (typeof window.applyTranslations === 'function') {
|
|
286
|
+
window.applyTranslations();
|
|
287
|
+
console.log('[all-tools] Applied i18n translations to sidebar');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
console.log('[all-tools] Translation applied successfully');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
let toolsMenuExpanded = true;
|
|
294
|
+
|
|
295
|
+
function toggleSidebar() {
|
|
296
|
+
const sidebar = document.getElementById('sidebar');
|
|
297
|
+
const backdrop = document.getElementById('backdrop');
|
|
298
|
+
const isOpen = sidebar.classList.contains('open');
|
|
299
|
+
if (isOpen) {
|
|
300
|
+
sidebar.classList.remove('open');
|
|
301
|
+
backdrop.classList.remove('active');
|
|
302
|
+
} else {
|
|
303
|
+
sidebar.classList.add('open');
|
|
304
|
+
backdrop.classList.add('active');
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function toggleToolsMenu() {
|
|
309
|
+
toolsMenuExpanded = !toolsMenuExpanded;
|
|
310
|
+
const submenu = document.getElementById('tools-submenu');
|
|
311
|
+
const icon = document.getElementById('tools-menu-icon');
|
|
312
|
+
if (toolsMenuExpanded) {
|
|
313
|
+
submenu.classList.remove('hidden');
|
|
314
|
+
icon.style.transform = 'rotate(180deg)';
|
|
315
|
+
} else {
|
|
316
|
+
submenu.classList.add('hidden');
|
|
317
|
+
icon.style.transform = '';
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
let allTools = [];
|
|
322
|
+
|
|
323
|
+
function generateSidebarTools() {
|
|
324
|
+
const submenu = document.getElementById('tools-submenu');
|
|
325
|
+
const currentLang = window.currentLang || 'zh-CN';
|
|
326
|
+
|
|
327
|
+
// 从 window.translations 读取当前语言的翻译
|
|
328
|
+
const currentTranslations = window.translations && window.translations[currentLang] || {};
|
|
329
|
+
const toolShortDesc = currentTranslations.toolShortDesc || {};
|
|
330
|
+
|
|
331
|
+
console.log('[all-tools] Generating sidebar tools');
|
|
332
|
+
console.log('[all-tools] Current language:', currentLang);
|
|
333
|
+
console.log('[all-tools] Current translations keys:', Object.keys(currentTranslations));
|
|
334
|
+
console.log('[all-tools] toolShortDesc:', toolShortDesc);
|
|
335
|
+
|
|
336
|
+
let html = '';
|
|
337
|
+
for (const [categoryKey, categoryInfo] of Object.entries(toolsData.categories)) {
|
|
338
|
+
const tools = toolsData[categoryKey];
|
|
339
|
+
if (!tools || tools.length === 0) continue;
|
|
340
|
+
|
|
341
|
+
// 使用翻译后的分类标题
|
|
342
|
+
const categoryTitle = categoryInfo.title;
|
|
343
|
+
html += `<div class="text-xs font-semibold text-text-tertiary uppercase tracking-wider px-2 py-1 mt-2">${categoryInfo.icon} ${categoryTitle}</div>`;
|
|
344
|
+
|
|
345
|
+
tools.forEach(tool => {
|
|
346
|
+
const toolId = tool.name.replace(/_/g, '-');
|
|
347
|
+
// 使用翻译后的工具备注
|
|
348
|
+
const desc = toolShortDesc[tool.name] || '';
|
|
349
|
+
console.log(`[all-tools] Tool: ${tool.name}, desc: ${desc}`);
|
|
350
|
+
const displayText = desc ? `${tool.name} (${desc})` : tool.name;
|
|
351
|
+
html += `<a href="#${toolId}" class="block px-2 py-1.5 text-xs text-text-secondary hover:bg-bg-page hover:text-primary rounded transition-colors">${displayText}</a>`;
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
submenu.innerHTML = html;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function scrollToTool(toolId) {
|
|
358
|
+
const element = document.getElementById(toolId);
|
|
359
|
+
if (element) {
|
|
360
|
+
const headerHeight = 100;
|
|
361
|
+
const elementPosition = element.getBoundingClientRect().top + window.pageYOffset;
|
|
362
|
+
window.scrollTo({ top: elementPosition - headerHeight, behavior: 'smooth' });
|
|
363
|
+
element.style.transition = 'background 0.3s';
|
|
364
|
+
element.style.background = 'rgba(37, 99, 235, 0.05)';
|
|
365
|
+
setTimeout(() => { element.style.background = ''; }, 2000);
|
|
366
|
+
}
|
|
367
|
+
if (window.innerWidth < 768) toggleSidebar();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function handleHashChange() {
|
|
371
|
+
const hash = window.location.hash.slice(1);
|
|
372
|
+
if (hash) {
|
|
373
|
+
setTimeout(() => scrollToTool(hash), 100);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function renderTools(filteredTools = null) {
|
|
378
|
+
const container = document.getElementById('tools-container');
|
|
379
|
+
const currentLang = window.currentLang || 'zh-CN';
|
|
380
|
+
const translations = window.translations && window.translations[currentLang] || {};
|
|
381
|
+
const searchTrans = translations.search || {};
|
|
382
|
+
|
|
383
|
+
let html = '';
|
|
384
|
+
if (filteredTools && filteredTools.length === 0) {
|
|
385
|
+
const noResultsMsg = searchTrans.noResults || '未找到匹配的工具';
|
|
386
|
+
html = `<div class="text-center py-8 text-text-secondary"><div class="text-4xl mb-2">🔍</div><p>${noResultsMsg}</p></div>`;
|
|
387
|
+
} else if (filteredTools) {
|
|
388
|
+
html += '<div class="space-y-6">';
|
|
389
|
+
filteredTools.forEach(tool => { html += renderToolCard(tool); });
|
|
390
|
+
html += '</div>';
|
|
391
|
+
} else {
|
|
392
|
+
for (const [categoryKey, categoryInfo] of Object.entries(toolsData.categories)) {
|
|
393
|
+
const tools = toolsData[categoryKey];
|
|
394
|
+
if (!tools || tools.length === 0) continue;
|
|
395
|
+
|
|
396
|
+
// 使用翻译后的分类标题
|
|
397
|
+
const categoryTitle = categoryInfo.title;
|
|
398
|
+
const countText = currentLang === 'zh-CN' ? '个' : '';
|
|
399
|
+
html += `<section class="bg-white rounded-xl border border-border p-4 sm:p-6 mb-6 shadow-sm"><div class="flex items-center gap-3 mb-4 pb-4 border-b border-border"><span class="text-2xl">${categoryInfo.icon}</span><h2 class="text-lg sm:text-xl font-semibold text-text-primary">${categoryTitle}</h2><span class="ml-auto bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full text-xs font-medium">${tools.length}${countText ? ' ' + countText : ''}</span></div><div class="space-y-4">`;
|
|
400
|
+
tools.forEach(tool => { html += renderToolCard({ ...tool, category: categoryKey }); });
|
|
401
|
+
html += `</div></section>`;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
container.innerHTML = html;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function renderToolCard(tool) {
|
|
408
|
+
const hasDetails = tool.params || tool.usage || tool.example;
|
|
409
|
+
let detailsHTML = '';
|
|
410
|
+
if (hasDetails) {
|
|
411
|
+
detailsHTML = `<div class="mt-4 pt-4 border-t border-border">
|
|
412
|
+
${tool.usage ? `<div class="mb-3"><h4 class="text-sm font-medium text-text-primary mb-2">📖 使用说明</h4><p class="text-sm text-text-secondary">${tool.usage}</p></div>` : ''}
|
|
413
|
+
${tool.params ? `<div class="mb-3"><h4 class="text-sm font-medium text-text-primary mb-2">⚙️ 参数说明</h4><ul class="space-y-1 text-sm text-text-secondary">${tool.params.map(p => `<li class="flex items-start gap-2"><code class="bg-gray-200 px-1.5 py-0.5 rounded text-xs flex-shrink-0">${p.name}</code><span class="text-xs text-text-tertiary">(${p.type}${p.required ? ', 必填' : ', 可选'})</span><span class="text-sm text-text-secondary">- ${p.desc}</span></li>`).join('')}</ul></div>` : ''}
|
|
414
|
+
${tool.example ? `<div><h4 class="text-sm font-medium text-text-primary mb-2">💡 使用示例</h4><div class="bg-slate-900 rounded-lg overflow-hidden"><div class="flex items-center justify-between px-3 py-2 bg-slate-800"><span class="text-xs text-slate-300 font-medium">Example</span></div><pre class="code-block p-4 text-sm text-slate-200 overflow-x-auto"><code>${tool.example.replace(/</g, '<').replace(/>/g, '>')}</code></pre></div></div>` : ''}
|
|
415
|
+
</div>`;
|
|
416
|
+
}
|
|
417
|
+
return `<div class="tool-card" id="${tool.name.replace(/_/g, '-')}"><div class="flex items-start gap-3"><div class="flex-1"><div class="flex items-center gap-2 mb-2"><code class="text-sm font-medium text-text-primary bg-gray-100 px-2 py-1 rounded">${tool.name}</code><span class="bg-green-100 text-green-700 px-2 py-0.5 rounded-full text-xs font-medium">✓ 结构化</span></div><p class="text-sm text-text-secondary mb-2">${tool.description}</p><p class="text-xs text-text-tertiary font-mono">Schema: ${tool.schema}</p></div></div>${detailsHTML}</div>`;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function searchTools(query) {
|
|
421
|
+
const currentLang = window.currentLang || 'zh-CN';
|
|
422
|
+
const translations = window.translations && window.translations[currentLang] || {};
|
|
423
|
+
const searchTrans = translations.search || {};
|
|
424
|
+
|
|
425
|
+
if (!query.trim()) {
|
|
426
|
+
document.getElementById('searchResults').textContent = '';
|
|
427
|
+
renderTools();
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const lowerQuery = query.toLowerCase();
|
|
432
|
+
const results = allTools.filter(tool => tool.name.toLowerCase().includes(lowerQuery) || tool.description.toLowerCase().includes(lowerQuery));
|
|
433
|
+
|
|
434
|
+
// 使用翻译后的搜索结果消息
|
|
435
|
+
const foundMsg = searchTrans.found || '找到 {count} 个匹配的工具';
|
|
436
|
+
const noResultsMsg = searchTrans.noResults || '未找到匹配的工具';
|
|
437
|
+
document.getElementById('searchResults').textContent = results.length > 0
|
|
438
|
+
? foundMsg.replace('{count}', results.length)
|
|
439
|
+
: noResultsMsg;
|
|
440
|
+
|
|
441
|
+
renderTools(results);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
let isInitialized = false;
|
|
445
|
+
|
|
446
|
+
function init() {
|
|
447
|
+
console.log('[all-tools] Initializing page...');
|
|
448
|
+
|
|
449
|
+
// 初始化 allTools 数组
|
|
450
|
+
allTools = [];
|
|
451
|
+
for (const [categoryKey, tools] of Object.entries(toolsData)) {
|
|
452
|
+
if (categoryKey === 'categories') continue;
|
|
453
|
+
tools.forEach(tool => { allTools.push({ ...tool, category: categoryKey }); });
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// 设置侧边栏(等待翻译加载后再生成)
|
|
457
|
+
// generateSidebarTools(); // 移除这里的调用
|
|
458
|
+
document.getElementById('tools-submenu').classList.remove('hidden');
|
|
459
|
+
document.getElementById('tools-menu-icon').style.transform = 'rotate(180deg)';
|
|
460
|
+
|
|
461
|
+
// 渲染工具列表(等待翻译加载后再渲染)
|
|
462
|
+
// renderTools(); // 移除这里的调用
|
|
463
|
+
|
|
464
|
+
// 添加搜索监听
|
|
465
|
+
document.getElementById('searchInput').addEventListener('input', (e) => { searchTools(e.target.value); });
|
|
466
|
+
|
|
467
|
+
// 监听 hash 变化
|
|
468
|
+
window.addEventListener('hashchange', handleHashChange);
|
|
469
|
+
|
|
470
|
+
// 页面加载时处理 hash
|
|
471
|
+
handleHashChange();
|
|
472
|
+
|
|
473
|
+
isInitialized = true;
|
|
474
|
+
console.log('[all-tools] Page initialized (waiting for i18n)');
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// 监听 i18n 初始化完成事件
|
|
478
|
+
window.addEventListener('i18nReady', () => {
|
|
479
|
+
console.log('[all-tools] i18n ready, applying translations...');
|
|
480
|
+
if (isInitialized) {
|
|
481
|
+
applyTranslationsToTools();
|
|
482
|
+
generateSidebarTools();
|
|
483
|
+
renderTools();
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// 语言切换时更新工具数据
|
|
488
|
+
document.addEventListener('languageChanged', () => {
|
|
489
|
+
console.log('[all-tools] Language changed event received');
|
|
490
|
+
|
|
491
|
+
// 保存当前搜索状态
|
|
492
|
+
const searchInput = document.getElementById('searchInput');
|
|
493
|
+
const currentSearch = searchInput ? searchInput.value : '';
|
|
494
|
+
const scrollPosition = window.pageYOffset;
|
|
495
|
+
|
|
496
|
+
// 应用翻译
|
|
497
|
+
applyTranslationsToTools();
|
|
498
|
+
generateSidebarTools();
|
|
499
|
+
|
|
500
|
+
// 恢复搜索状态
|
|
501
|
+
if (currentSearch) {
|
|
502
|
+
searchTools(currentSearch);
|
|
503
|
+
} else {
|
|
504
|
+
renderTools();
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// 恢复滚动位置
|
|
508
|
+
window.scrollTo(0, scrollPosition);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
document.addEventListener('DOMContentLoaded', init);
|
|
512
|
+
</script>
|
|
513
|
+
</body>
|
|
514
|
+
</html>
|