mn-docs-mcp 0.6.2 → 1.1.0

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.
Files changed (222) hide show
  1. package/.trae/documents/libmn_cleanup_plan.md +51 -0
  2. package/.trae/documents/libmn_doc_restructure_plan.md +140 -0
  3. package/.trae/documents/libmn_indentation_plan.md +116 -0
  4. package/.trae/documents/libmn_title_hierarchy_plan.md +91 -0
  5. package/README.md +9 -7
  6. package/next-env.d.ts +6 -0
  7. package/next.config.mjs +14 -0
  8. package/package.json +25 -10
  9. package/postcss.config.mjs +7 -0
  10. package/scripts/sync-definitions.mjs +33 -0
  11. package/source.config.ts +5 -0
  12. package/src/app/[[...slug]]/page.tsx +259 -0
  13. package/src/app/api/search/route.ts +6 -0
  14. package/src/app/global.css +81 -0
  15. package/src/app/layout.tsx +33 -0
  16. package/src/components/JsbApiFooter.tsx +251 -0
  17. package/src/content/docs/{guides/contributing.md → contributing.md} +31 -6
  18. package/src/content/docs/{guides/cookbook → cookbook}/addon-settings.md +2 -2
  19. package/src/content/docs/{guides/cookbook → cookbook}/embed-webview-panel.md +2 -2
  20. package/src/content/docs/cookbook/meta.json +13 -0
  21. package/src/content/docs/{guides/cookbook → cookbook}/network-api-call.md +2 -2
  22. package/src/content/docs/{guides/cookbook → cookbook}/webview-bidirectional-js.md +1 -1
  23. package/src/content/docs/guides/getting-started.md +2 -2
  24. package/src/content/docs/guides/lifecycle-and-window.md +4 -4
  25. package/src/content/docs/guides/meta.json +14 -0
  26. package/src/content/docs/guides/mindmap-and-selection.md +2 -2
  27. package/src/content/docs/guides/native-ui.md +4 -4
  28. package/src/content/docs/guides/network-requests.md +8 -9
  29. package/src/content/docs/guides/notes-and-database.md +2 -2
  30. package/src/content/docs/guides/shortcut-keys.md +9 -9
  31. package/src/content/docs/guides/storage-and-files.md +4 -4
  32. package/src/content/docs/guides/toolbar-and-commands.md +1 -1
  33. package/src/content/docs/index.mdx +13 -38
  34. package/src/content/docs/libmn/data-converter.md +1572 -0
  35. package/src/content/docs/libmn/frame.md +279 -0
  36. package/src/content/docs/libmn/headers.md +234 -0
  37. package/src/content/docs/libmn/index.md +60 -0
  38. package/src/content/docs/libmn/internal-exposed.md +46 -0
  39. package/src/content/docs/libmn/locale.md +307 -0
  40. package/src/content/docs/libmn/menu.md +77 -0
  41. package/src/content/docs/libmn/meta.json +27 -0
  42. package/src/content/docs/libmn/mnbutton.md +966 -0
  43. package/src/content/docs/libmn/mncomment.md +533 -0
  44. package/src/content/docs/libmn/mnconnection.md +717 -0
  45. package/src/content/docs/libmn/mndocument.md +309 -0
  46. package/src/content/docs/libmn/mnextension-panel.md +340 -0
  47. package/src/content/docs/libmn/mnnote.md +533 -0
  48. package/src/content/docs/libmn/mnnotebook.md +725 -0
  49. package/src/content/docs/libmn/mnutil.md +2936 -0
  50. package/src/content/docs/libmn/mnwebview.md +693 -0
  51. package/src/content/docs/libmn/mustache.md +65 -0
  52. package/src/content/docs/libmn/response.md +352 -0
  53. package/src/content/docs/libmn/runtime-assets.md +64 -0
  54. package/src/content/docs/libmn/runtime-web-view-host.md +77 -0
  55. package/src/content/docs/libmn/runtime.md +178 -0
  56. package/src/content/docs/libmn/vendor-globals.md +34 -0
  57. package/src/content/docs/meta.json +11 -0
  58. package/src/content/docs/reference/black-box.md +2 -2
  59. package/src/content/docs/reference/foundation/meta.json +4 -0
  60. package/src/content/docs/reference/foundation/ns-attributed-string.md +1 -1
  61. package/src/content/docs/reference/foundation/ns-counted-set.md +1 -1
  62. package/src/content/docs/reference/foundation/ns-date-components.md +2 -2
  63. package/src/content/docs/reference/foundation/ns-date-formatter.md +1 -3
  64. package/src/content/docs/reference/foundation/ns-decimal-number.md +1 -1
  65. package/src/content/docs/reference/foundation/ns-enumerator.md +1 -1
  66. package/src/content/docs/reference/foundation/ns-error.md +2 -2
  67. package/src/content/docs/reference/foundation/ns-file-manager.md +1 -1
  68. package/src/content/docs/reference/foundation/ns-formatter.md +2 -2
  69. package/src/content/docs/reference/foundation/ns-json-serialization.md +10 -2
  70. package/src/content/docs/reference/foundation/ns-mutable-attributed-string.md +1 -1
  71. package/src/content/docs/reference/foundation/ns-mutable-character-set.md +1 -1
  72. package/src/content/docs/reference/foundation/ns-mutable-dictionary.md +1 -1
  73. package/src/content/docs/reference/foundation/ns-mutable-index-set.md +1 -1
  74. package/src/content/docs/reference/foundation/ns-mutable-set.md +1 -1
  75. package/src/content/docs/reference/foundation/ns-mutable-string.md +1 -1
  76. package/src/content/docs/reference/foundation/ns-mutable-url-request.md +2 -3
  77. package/src/content/docs/reference/foundation/ns-null.md +1 -1
  78. package/src/content/docs/reference/foundation/ns-number-formatter.md +1 -1
  79. package/src/content/docs/reference/foundation/ns-operation.md +2 -2
  80. package/src/content/docs/reference/foundation/ns-pointer-array.md +1 -1
  81. package/src/content/docs/reference/foundation/ns-proxy.md +5 -3
  82. package/src/content/docs/reference/foundation/ns-scanner.md +7 -1
  83. package/src/content/docs/reference/foundation/ns-set.md +1 -1
  84. package/src/content/docs/reference/foundation/ns-simple-c-string.md +3 -4
  85. package/src/content/docs/reference/foundation/ns-time-zone.md +1 -1
  86. package/src/content/docs/reference/foundation/ns-ubiquitous-key-value-store.md +61 -0
  87. package/src/content/docs/reference/foundation/ns-url-connection.md +2 -2
  88. package/src/content/docs/reference/foundation/ns-url-request.md +2 -2
  89. package/src/content/docs/reference/foundation/ns-url-response.md +5 -5
  90. package/src/content/docs/reference/foundation/ns-url.md +1 -1
  91. package/src/content/docs/reference/foundation/ns-user-defaults.md +5 -5
  92. package/src/content/docs/reference/foundation/ns-value.md +15 -15
  93. package/src/content/docs/reference/global/agent-tools.md +91 -0
  94. package/src/content/docs/reference/global/application.md +4 -4
  95. package/src/content/docs/reference/global/builtin-commands.md +2 -2
  96. package/src/content/docs/reference/global/database.md +4 -4
  97. package/src/content/docs/reference/global/document.md +21 -0
  98. package/src/content/docs/reference/global/global-variables.md +22 -5
  99. package/src/content/docs/reference/global/jsb.md +6 -4
  100. package/src/content/docs/reference/global/meta.json +18 -0
  101. package/src/content/docs/reference/global/note.md +2 -2
  102. package/src/content/docs/reference/global/notebook.md +21 -0
  103. package/src/content/docs/reference/global/popup-menu-item.md +2 -2
  104. package/src/content/docs/reference/global/popup-menu.md +5 -6
  105. package/src/content/docs/reference/global/search-manager.md +12 -6
  106. package/src/content/docs/reference/global/self.md +1 -13
  107. package/src/content/docs/reference/js-runtime.md +5 -4
  108. package/src/content/docs/reference/marginnote/document-controller.md +37 -5
  109. package/src/content/docs/reference/marginnote/jsextension.md +7 -7
  110. package/src/content/docs/reference/marginnote/mb-book-note.md +162 -72
  111. package/src/content/docs/reference/marginnote/mb-book.md +3 -3
  112. package/src/content/docs/reference/marginnote/mb-model-tool.md +2 -2
  113. package/src/content/docs/reference/marginnote/mb-topic.md +13 -2
  114. package/src/content/docs/reference/marginnote/meta.json +18 -0
  115. package/src/content/docs/reference/marginnote/mindmap-node.md +2 -2
  116. package/src/content/docs/reference/marginnote/mindmap-view.md +2 -2
  117. package/src/content/docs/reference/marginnote/notebook-controller.md +1 -1
  118. package/src/content/docs/reference/marginnote/outline-view.md +2 -2
  119. package/src/content/docs/reference/marginnote/reader-controller.md +1 -1
  120. package/src/content/docs/reference/marginnote/study-controller.md +19 -19
  121. package/src/content/docs/reference/meta.json +14 -0
  122. package/src/content/docs/reference/quartzcore/caanimation-group.md +3 -3
  123. package/src/content/docs/reference/quartzcore/cabasic-animation.md +3 -3
  124. package/src/content/docs/reference/quartzcore/caemitter-layer.md +44 -0
  125. package/src/content/docs/reference/quartzcore/cagradient-layer.md +1 -1
  126. package/src/content/docs/reference/quartzcore/cakeyframe-animation.md +3 -3
  127. package/src/content/docs/reference/quartzcore/calayer.md +1 -1
  128. package/src/content/docs/reference/quartzcore/camedia-timing-function.md +1 -1
  129. package/src/content/docs/reference/quartzcore/caproperty-animation.md +1 -1
  130. package/src/content/docs/reference/quartzcore/careplicator-layer.md +2 -2
  131. package/src/content/docs/reference/quartzcore/cascroll-layer.md +1 -1
  132. package/src/content/docs/reference/quartzcore/cashape-layer.md +2 -2
  133. package/src/content/docs/reference/quartzcore/catext-layer.md +4 -4
  134. package/src/content/docs/reference/quartzcore/catransaction.md +5 -3
  135. package/src/content/docs/reference/quartzcore/catransform-layer.md +3 -3
  136. package/src/content/docs/reference/quartzcore/catransition.md +10 -6
  137. package/src/content/docs/reference/quartzcore/cavalue-function.md +1 -1
  138. package/src/content/docs/reference/quartzcore/meta.json +4 -0
  139. package/src/content/docs/reference/uikit/meta.json +4 -0
  140. package/src/content/docs/reference/uikit/ns-mutable-paragraph-style.md +3 -3
  141. package/src/content/docs/reference/uikit/ns-paragraph-style.md +3 -4
  142. package/src/content/docs/reference/uikit/ns-text-storage.md +4 -5
  143. package/src/content/docs/reference/uikit/uiactivity-indicator-view.md +2 -2
  144. package/src/content/docs/reference/uikit/uiapplication.md +1 -1
  145. package/src/content/docs/reference/uikit/uibar-button-item.md +3 -4
  146. package/src/content/docs/reference/uikit/uibar-item.md +2 -3
  147. package/src/content/docs/reference/uikit/uibezier-path.md +2 -2
  148. package/src/content/docs/reference/uikit/uibutton.md +1 -1
  149. package/src/content/docs/reference/uikit/uicollection-view-cell.md +5 -5
  150. package/src/content/docs/reference/uikit/uicollection-view-controller.md +22 -2
  151. package/src/content/docs/reference/uikit/uicollection-view-flow-layout.md +54 -0
  152. package/src/content/docs/reference/uikit/uicollection-view-layout.md +9 -2
  153. package/src/content/docs/reference/uikit/uicollection-view.md +13 -4
  154. package/src/content/docs/reference/uikit/uicolor.md +1 -1
  155. package/src/content/docs/reference/uikit/uicontrol.md +3 -5
  156. package/src/content/docs/reference/uikit/uidate-picker.md +1 -1
  157. package/src/content/docs/reference/uikit/uievent.md +2 -2
  158. package/src/content/docs/reference/uikit/uifont.md +1 -1
  159. package/src/content/docs/reference/uikit/uigesture-recognizer.md +1 -1
  160. package/src/content/docs/reference/uikit/uiimage-picker-controller.md +1 -1
  161. package/src/content/docs/reference/uikit/uiimage-view.md +2 -2
  162. package/src/content/docs/reference/uikit/uiimage.md +2 -2
  163. package/src/content/docs/reference/uikit/uikey-command.md +2 -2
  164. package/src/content/docs/reference/uikit/uilabel.md +3 -3
  165. package/src/content/docs/reference/uikit/uilocal-notification.md +2 -2
  166. package/src/content/docs/reference/uikit/uilong-press-gesture-recognizer.md +2 -2
  167. package/src/content/docs/reference/uikit/uinavigation-bar.md +2 -2
  168. package/src/content/docs/reference/uikit/uinavigation-controller.md +1 -1
  169. package/src/content/docs/reference/uikit/uinavigation-item.md +1 -1
  170. package/src/content/docs/reference/uikit/uipage-control.md +1 -1
  171. package/src/content/docs/reference/uikit/uipage-view-controller.md +1 -1
  172. package/src/content/docs/reference/uikit/uipan-gesture-recognizer.md +1 -1
  173. package/src/content/docs/reference/uikit/uipasteboard.md +1 -1
  174. package/src/content/docs/reference/uikit/uipicker-view.md +3 -3
  175. package/src/content/docs/reference/uikit/uipinch-gesture-recognizer.md +1 -1
  176. package/src/content/docs/reference/uikit/uipopover-controller.md +1 -1
  177. package/src/content/docs/reference/uikit/uiresponder.md +3 -4
  178. package/src/content/docs/reference/uikit/uirotation-gesture-recognizer.md +1 -1
  179. package/src/content/docs/reference/uikit/uiscreen-mode.md +2 -2
  180. package/src/content/docs/reference/uikit/uiscrollview.md +1 -1
  181. package/src/content/docs/reference/uikit/uisearch-bar.md +25 -2
  182. package/src/content/docs/reference/uikit/uisegmented-control.md +1 -1
  183. package/src/content/docs/reference/uikit/uislider.md +1 -1
  184. package/src/content/docs/reference/uikit/uiswipe-gesture-recognizer.md +1 -1
  185. package/src/content/docs/reference/uikit/uiswitch.md +2 -2
  186. package/src/content/docs/reference/uikit/uitab-bar-controller.md +2 -2
  187. package/src/content/docs/reference/uikit/uitab-bar-item.md +1 -1
  188. package/src/content/docs/reference/uikit/uitab-bar.md +1 -1
  189. package/src/content/docs/reference/uikit/uitable-view-cell.md +6 -6
  190. package/src/content/docs/reference/uikit/uitable-view-controller.md +1 -1
  191. package/src/content/docs/reference/uikit/uitable-view.md +3 -3
  192. package/src/content/docs/reference/uikit/uitap-gesture-recognizer.md +2 -2
  193. package/src/content/docs/reference/uikit/uitext-input-mode.md +7 -3
  194. package/src/content/docs/reference/uikit/uitext-position.md +5 -5
  195. package/src/content/docs/reference/uikit/uitext-range.md +4 -4
  196. package/src/content/docs/reference/uikit/uitext-view.md +2 -2
  197. package/src/content/docs/reference/uikit/uitextfield.md +3 -3
  198. package/src/content/docs/reference/uikit/uitoolbar.md +1 -1
  199. package/src/content/docs/reference/uikit/uitouch.md +3 -3
  200. package/src/content/docs/reference/uikit/uiview-controller.md +2 -2
  201. package/src/content/docs/reference/uikit/uiview.md +5 -5
  202. package/src/content/docs/reference/uikit/uiwebview.md +5 -5
  203. package/src/content/docs/reference/uikit/uiwindow.md +2 -2
  204. package/src/content/docs/reference/utility/menu-controller.md +1 -1
  205. package/src/content/docs/reference/utility/meta.json +4 -0
  206. package/src/content/docs/reference/utility/sqlite-result-set.md +1 -1
  207. package/src/content/docs/reference/utility/sqlite-statement.md +2 -2
  208. package/src/content/docs/reference/utility/zip-archive.md +13 -14
  209. package/src/content/docs/reference/value-sturct.md +105 -0
  210. package/src/lib/layout.tsx +31 -0
  211. package/src/lib/source.ts +7 -0
  212. package/tsconfig.json +42 -3
  213. package/astro.config.mjs +0 -126
  214. package/src/client/jsb-api-footer.ts +0 -242
  215. package/src/components/Footer.astro +0 -57
  216. package/src/components/Search.astro +0 -330
  217. package/src/content.config.ts +0 -7
  218. package/src/styles/starlight-overrides.css +0 -23
  219. /package/src/content/docs/{guides/cookbook → cookbook}/append-selection-as-comment.md +0 -0
  220. /package/src/content/docs/{guides/cookbook → cookbook}/batch-rename-notes.md +0 -0
  221. /package/src/content/docs/{guides/cookbook → cookbook}/export-notebook.md +0 -0
  222. /package/src/content/docs/{guides/cookbook → cookbook}/focus-note-in-mindmap.md +0 -0
@@ -0,0 +1,259 @@
1
+ import { notFound } from 'next/navigation';
2
+ import defaultMdxComponents from 'fumadocs-ui/mdx';
3
+ import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
4
+ import { DocsLayout } from 'fumadocs-ui/layouts/docs';
5
+ import type { Root, Folder, Item } from 'fumadocs-core/page-tree';
6
+ import { source } from '@/src/lib/source';
7
+ import { JsbApiFooter } from '@/src/components/JsbApiFooter';
8
+
9
+ import {
10
+ BookOpen,
11
+ Code2,
12
+ TerminalSquare,
13
+ Wrench,
14
+ ArrowRight,
15
+ Sparkles,
16
+ Library,
17
+ Compass,
18
+ } from 'lucide-react';
19
+ import Link from 'next/link';
20
+
21
+ type PageProps = {
22
+ params: Promise<{
23
+ slug?: string[];
24
+ }>;
25
+ };
26
+
27
+ function filterPageTree(tree: Root, slug: string[]): Root {
28
+ const section = slug[0];
29
+ const folder = tree.children.find(
30
+ (child): child is Folder =>
31
+ child.type === 'folder' &&
32
+ child.children.some(
33
+ (item): item is Item =>
34
+ item.type === 'page' && item.url.startsWith(`/${section}/`),
35
+ ),
36
+ );
37
+
38
+ if (folder) return { ...tree, children: [folder] };
39
+
40
+ const page = tree.children.find(
41
+ (child): child is Item =>
42
+ child.type === 'page' && child.url === `/${section}`,
43
+ );
44
+
45
+ if (page) return { ...tree, children: [page] };
46
+
47
+ return tree;
48
+ }
49
+
50
+ function HomePage() {
51
+ return (
52
+ <div className="relative min-h-screen overflow-hidden bg-fd-background flex flex-col">
53
+ <div className="absolute inset-0 z-0 h-full w-full bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] [background-size:16px_16px] [mask-image:radial-gradient(ellipse_50%_50%_at_50%_0%,#000_70%,transparent_100%)] dark:bg-[radial-gradient(#374151_1px,transparent_1px)]" />
54
+ <div className="absolute left-1/2 top-0 z-0 -ml-[40rem] h-[40rem] w-[80rem] rounded-full bg-gradient-to-b from-blue-500/10 to-transparent blur-[100px] dark:from-blue-600/10" />
55
+
56
+ <main className="relative z-10 flex-1">
57
+ {/* Hero */}
58
+ <section className="mx-auto flex max-w-5xl flex-col items-center px-6 pt-32 pb-24 text-center md:pt-40">
59
+ <div className="animate-in fade-in slide-in-from-bottom-4 duration-700 mb-6 inline-flex items-center gap-2 rounded-full border border-fd-border bg-fd-card/50 px-3 py-1 text-sm font-medium text-fd-muted-foreground backdrop-blur-md">
60
+ <Sparkles className="h-4 w-4 text-blue-500" />
61
+ <span>MarginNote 插件开发指南全新上线</span>
62
+ </div>
63
+
64
+ <h1 className="animate-in fade-in slide-in-from-bottom-6 duration-1000 text-balance text-5xl font-extrabold tracking-tight md:text-7xl">
65
+ 构建强大的 <br className="md:hidden" />
66
+ <span className="bg-gradient-to-br from-blue-500 via-indigo-500 to-purple-600 bg-clip-text text-transparent drop-shadow-sm">
67
+ MarginNote 插件
68
+ </span>
69
+ </h1>
70
+
71
+ <p className="animate-in fade-in slide-in-from-bottom-8 duration-1000 mx-auto mt-6 max-w-2xl text-balance text-lg text-fd-muted-foreground md:text-xl">
72
+ 探索完整的 API 参考、渐进式教程与 Cookbook 配方,赋予 MarginNote 前所未有的生产力与可能性。
73
+ </p>
74
+
75
+ <div className="animate-in fade-in slide-in-from-bottom-10 duration-1000 mt-10 flex flex-col items-center gap-4 sm:flex-row sm:gap-6">
76
+ <Link
77
+ href="/guides/getting-started/"
78
+ className="group relative inline-flex h-12 items-center justify-center gap-2 overflow-hidden rounded-full bg-fd-foreground px-8 text-base font-semibold text-fd-background transition-all hover:scale-105 hover:shadow-xl hover:shadow-fd-foreground/10 active:scale-95"
79
+ >
80
+ 快速开始
81
+ <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
82
+ </Link>
83
+ <Link
84
+ href="/reference/global/jsb/"
85
+ className="inline-flex h-12 items-center justify-center gap-2 rounded-full border border-fd-border bg-fd-card/50 px-8 text-base font-medium text-fd-foreground backdrop-blur-md transition-all hover:bg-fd-accent hover:text-fd-accent-foreground active:scale-95"
86
+ >
87
+ <TerminalSquare className="h-4 w-4" />
88
+ 浏览 API 参考
89
+ </Link>
90
+ </div>
91
+ </section>
92
+
93
+ {/* Bento Grid */}
94
+ <section className="mx-auto max-w-5xl px-6 pb-32">
95
+ <div className="mb-12 flex items-center justify-between">
96
+ <h2 className="text-2xl font-bold tracking-tight text-fd-foreground">
97
+ 探索文档
98
+ </h2>
99
+ </div>
100
+
101
+ <div className="grid grid-cols-1 gap-4 md:grid-cols-3 md:grid-rows-2">
102
+ {/* 教程 (占2列) */}
103
+ <Link
104
+ href="/guides/lifecycle-and-window/"
105
+ className="group relative col-span-1 flex flex-col justify-between overflow-hidden rounded-3xl border border-fd-border bg-gradient-to-br from-fd-card to-fd-card/50 p-8 transition-all hover:border-blue-500/50 hover:shadow-2xl hover:shadow-blue-500/10 md:col-span-2"
106
+ >
107
+ <div className="absolute right-0 top-0 -mt-8 -mr-8 h-40 w-40 rounded-full bg-blue-500/10 blur-3xl transition-all group-hover:bg-blue-500/20" />
108
+ <div>
109
+ <div className="mb-4 inline-flex rounded-xl bg-blue-500/10 p-3 text-blue-500">
110
+ <Compass className="h-6 w-6" />
111
+ </div>
112
+ <h3 className="mb-2 text-xl font-bold text-fd-foreground">
113
+ 核心教程与生命周期
114
+ </h3>
115
+ <p className="text-fd-muted-foreground">
116
+ 按合理的学习路径,全面掌握插件的生命周期、窗口管理、笔记与数据库操作等核心概念。
117
+ </p>
118
+ </div>
119
+ <div className="mt-8 flex items-center text-sm font-semibold text-blue-500">
120
+ 开始学习{' '}
121
+ <ArrowRight className="ml-1 h-4 w-4 transition-transform group-hover:translate-x-1" />
122
+ </div>
123
+ </Link>
124
+
125
+ {/* API 参考 */}
126
+ <Link
127
+ href="/reference/global/jsb/"
128
+ className="group relative col-span-1 flex flex-col justify-between overflow-hidden rounded-3xl border border-fd-border bg-fd-card p-8 transition-all hover:border-purple-500/50 hover:shadow-2xl hover:shadow-purple-500/10"
129
+ >
130
+ <div>
131
+ <div className="mb-4 inline-flex rounded-xl bg-purple-500/10 p-3 text-purple-500">
132
+ <BookOpen className="h-6 w-6" />
133
+ </div>
134
+ <h3 className="mb-2 text-xl font-bold text-fd-foreground">
135
+ API 参考
136
+ </h3>
137
+ <p className="text-sm text-fd-muted-foreground">
138
+ 查阅全局对象与核心 API 的完整技术说明。
139
+ </p>
140
+ </div>
141
+ </Link>
142
+
143
+ {/* LibMN */}
144
+ <Link
145
+ href="/libmn/"
146
+ className="group relative col-span-1 flex flex-col justify-between overflow-hidden rounded-3xl border border-fd-border bg-fd-card p-8 transition-all hover:border-indigo-500/50 hover:shadow-2xl hover:shadow-indigo-500/10"
147
+ >
148
+ <div>
149
+ <div className="mb-4 inline-flex rounded-xl bg-indigo-500/10 p-3 text-indigo-500">
150
+ <Library className="h-6 w-6" />
151
+ </div>
152
+ <h3 className="mb-2 text-xl font-bold text-fd-foreground">
153
+ LibMN 运行时
154
+ </h3>
155
+ <p className="text-sm text-fd-muted-foreground">
156
+ 深入了解 LibMN 运行时与插件开发的核心底层模块。
157
+ </p>
158
+ </div>
159
+ </Link>
160
+
161
+ {/* Cookbook (占2列) */}
162
+ <Link
163
+ href="/cookbook/batch-rename-notes/"
164
+ className="group relative col-span-1 flex flex-col justify-between overflow-hidden rounded-3xl border border-fd-border bg-fd-card p-8 transition-all hover:border-emerald-500/50 hover:shadow-2xl hover:shadow-emerald-500/10 md:col-span-2"
165
+ >
166
+ <div className="absolute right-0 top-0 -mt-8 -mr-8 h-40 w-40 rounded-full bg-emerald-500/10 blur-3xl transition-all group-hover:bg-emerald-500/20" />
167
+ <div>
168
+ <div className="mb-4 flex items-center gap-4">
169
+ <div className="inline-flex rounded-xl bg-emerald-500/10 p-3 text-emerald-500">
170
+ <Code2 className="h-6 w-6" />
171
+ </div>
172
+ <div className="inline-flex rounded-full border border-fd-border bg-fd-background/50 px-3 py-1 text-xs font-medium text-fd-muted-foreground backdrop-blur-md">
173
+ 开箱即用
174
+ </div>
175
+ </div>
176
+ <h3 className="mb-2 text-xl font-bold text-fd-foreground">
177
+ Cookbook 实践配方
178
+ </h3>
179
+ <p className="text-fd-muted-foreground">
180
+ 按任务查找完整、可运行的代码片段。从批量重命名笔记到自定义脑图节点,直接复制并在你的项目中运行。
181
+ </p>
182
+ </div>
183
+ </Link>
184
+ </div>
185
+ </section>
186
+
187
+ {/* Bottom CTA */}
188
+ <section className="relative overflow-hidden border-t border-fd-border bg-fd-card/50">
189
+ <div className="absolute inset-0 bg-[radial-gradient(circle_at_center,var(--tw-gradient-stops))] from-blue-500/5 via-transparent to-transparent" />
190
+ <div className="relative mx-auto max-w-4xl px-6 py-24 text-center">
191
+ <Wrench className="mx-auto mb-6 h-12 w-12 text-fd-muted-foreground/50" />
192
+ <h2 className="text-3xl font-bold tracking-tight text-fd-foreground sm:text-4xl">
193
+ 准备好开发你的第一个插件了吗?
194
+ </h2>
195
+ <p className="mx-auto mt-4 max-w-xl text-lg text-fd-muted-foreground">
196
+ 跟随我们的快速指南,只需几分钟,即可在 MarginNote 中创建并运行属于你的自定义插件。
197
+ </p>
198
+ <div className="mt-8 flex items-center justify-center gap-4">
199
+ <Link
200
+ href="/guides/getting-started/"
201
+ className="inline-flex h-12 items-center justify-center rounded-xl bg-fd-primary px-8 text-sm font-semibold text-fd-primary-foreground shadow-sm transition-all hover:brightness-110 active:scale-95"
202
+ >
203
+ 立即开始
204
+ </Link>
205
+ <Link
206
+ href="/contributing/"
207
+ className="inline-flex h-12 items-center justify-center rounded-xl border border-fd-border bg-transparent px-8 text-sm font-medium text-fd-foreground transition-all hover:bg-fd-accent active:scale-95"
208
+ >
209
+ 参与贡献
210
+ </Link>
211
+ </div>
212
+ </div>
213
+ </section>
214
+ </main>
215
+ </div>
216
+ );
217
+ }
218
+
219
+ export default async function Page({ params }: PageProps) {
220
+ const { slug = [] } = await params;
221
+ const page = source.getPage(slug);
222
+ if (!page) notFound();
223
+
224
+ const Mdx = page.data.body;
225
+
226
+ if (slug.length === 0) {
227
+ return <HomePage />;
228
+ }
229
+
230
+ const tree = filterPageTree(source.pageTree, slug);
231
+
232
+ return (
233
+ <DocsLayout tree={tree}>
234
+ <DocsPage toc={page.data.toc}>
235
+ <DocsTitle>{page.data.title}</DocsTitle>
236
+ <DocsDescription>{page.data.description}</DocsDescription>
237
+ <DocsBody>
238
+ <Mdx components={defaultMdxComponents} />
239
+ <JsbApiFooter slug={page.slugs.join('/')} title={page.data.title} />
240
+ </DocsBody>
241
+ </DocsPage>
242
+ </DocsLayout>
243
+ );
244
+ }
245
+
246
+ export function generateStaticParams() {
247
+ return source.generateParams();
248
+ }
249
+
250
+ export async function generateMetadata({ params }: PageProps) {
251
+ const { slug = [] } = await params;
252
+ const page = source.getPage(slug);
253
+ if (!page) notFound();
254
+
255
+ return {
256
+ title: page.data.title,
257
+ description: page.data.description,
258
+ };
259
+ }
@@ -0,0 +1,6 @@
1
+ import { source } from '@/src/lib/source';
2
+ import { createFromSource } from 'fumadocs-core/search/server';
3
+
4
+ export const revalidate = false;
5
+
6
+ export const GET = createFromSource(source).staticGET;
@@ -0,0 +1,81 @@
1
+ @import 'fumadocs-ui/css/style.css';
2
+
3
+ @source '../**/*.{ts,tsx,md,mdx}';
4
+
5
+ :root {
6
+ color-scheme: light dark;
7
+ }
8
+
9
+ .prose table {
10
+ display: table;
11
+ overflow: visible;
12
+ width: 100%;
13
+ table-layout: fixed;
14
+ }
15
+
16
+ .prose table:has(> thead > tr > :nth-child(2)):not(:has(> thead > tr > :nth-child(3))) {
17
+ --mn-table-cols: 2;
18
+ }
19
+
20
+ .prose table:has(> thead > tr > :nth-child(3)):not(:has(> thead > tr > :nth-child(4))) {
21
+ --mn-table-cols: 3;
22
+ }
23
+
24
+ .prose table:has(> thead > tr > :nth-child(4)):not(:has(> thead > tr > :nth-child(5))) {
25
+ --mn-table-cols: 4;
26
+ }
27
+
28
+ .prose table:has(> thead > tr > :nth-child(5)):not(:has(> thead > tr > :nth-child(6))) {
29
+ --mn-table-cols: 5;
30
+ }
31
+
32
+ .prose table:has(> thead > tr > :nth-child(6)):not(:has(> thead > tr > :nth-child(7))) {
33
+ --mn-table-cols: 6;
34
+ }
35
+
36
+ .prose table:has(> thead > tr > :nth-child(2)) :is(th, td) {
37
+ width: calc(100% / var(--mn-table-cols));
38
+ max-width: 50%;
39
+ }
40
+
41
+ .prose :is(th, td),
42
+ .prose :is(th, td) code {
43
+ white-space: normal;
44
+ overflow-wrap: anywhere;
45
+ word-break: break-word;
46
+ }
47
+
48
+ .jsb-api {
49
+ margin-top: 2rem;
50
+ }
51
+
52
+ .jsb-api__details {
53
+ border: 1px solid var(--color-fd-border);
54
+ border-radius: 0.75rem;
55
+ padding: 0.75rem 1rem;
56
+ background: color-mix(in srgb, var(--color-fd-muted), transparent 38%);
57
+ }
58
+
59
+ .jsb-api__summary {
60
+ cursor: pointer;
61
+ font-weight: 600;
62
+ }
63
+
64
+ .jsb-api__meta {
65
+ margin-top: 0.75rem;
66
+ color: var(--color-fd-muted-foreground);
67
+ font-size: 0.875rem;
68
+ }
69
+
70
+ .jsb-api__meta code {
71
+ word-break: break-all;
72
+ }
73
+
74
+ .jsb-api ul {
75
+ margin-top: 0.5rem;
76
+ }
77
+
78
+ .jsb-api table {
79
+ margin-top: 0.75rem;
80
+ width: 100%;
81
+ }
@@ -0,0 +1,33 @@
1
+ import type { Metadata } from 'next';
2
+ import { RootProvider } from 'fumadocs-ui/provider/next';
3
+ import { HomeLayout } from 'fumadocs-ui/layouts/home';
4
+ import { baseOptions } from '@/src/lib/layout';
5
+ import type { ReactNode } from 'react';
6
+ import './global.css';
7
+
8
+ export const metadata: Metadata = {
9
+ title: {
10
+ default: 'MarginNote插件开发文档',
11
+ template: '%s | MarginNote插件开发文档',
12
+ },
13
+ description: 'MarginNote插件开发的完整API参考与渐进式教程。',
14
+ metadataBase: new URL('https://mn-docs.museday.top'),
15
+ };
16
+
17
+ export default function RootLayout({ children }: { children: ReactNode }) {
18
+ return (
19
+ <html lang="zh-CN" suppressHydrationWarning>
20
+ <body>
21
+ <RootProvider
22
+ search={{
23
+ options: {
24
+ type: 'static',
25
+ },
26
+ }}
27
+ >
28
+ <HomeLayout {...baseOptions}>{children}</HomeLayout>
29
+ </RootProvider>
30
+ </body>
31
+ </html>
32
+ );
33
+ }
@@ -0,0 +1,251 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useMemo, useState } from 'react';
4
+
5
+ type JsbApi = {
6
+ protocol: string;
7
+ properties: string[];
8
+ instance_methods: string[];
9
+ class_methods: string[];
10
+ export_aliases: Record<string, string>;
11
+ };
12
+
13
+ type PageConfig = {
14
+ protocol: string;
15
+ only?: Array<'properties' | 'class' | 'instance' | 'aliases'>;
16
+ };
17
+
18
+ const GLOBAL_PAGE_PROTOCOL_MAP: Record<string, PageConfig> = {
19
+ 'reference/global/application': { protocol: 'JSBApplication' },
20
+ 'reference/global/database': { protocol: 'JSBMbModelTool' },
21
+ 'reference/global/note': { protocol: 'JSBMbBookNote', only: ['class'] },
22
+ 'reference/global/self': { protocol: 'JSBJSExtension' },
23
+ };
24
+
25
+ function protocolFromTitle(title: string): string {
26
+ return `JSB${title.replace(/\s+/g, '')}`;
27
+ }
28
+
29
+ function selectorGuessFromDecl(decl: string): string {
30
+ const stripped = decl.split('//', 1)[0].trim().replace(/;$/, '').trim();
31
+ const noPrefix = stripped.replace(/^[-+]\s*\([^)]*\)\s*/, '').trim();
32
+ if (!noPrefix.includes(':')) return noPrefix.split(/\s|\(/, 1)[0].trim();
33
+ const parts = noPrefix.split(':');
34
+ const labels = parts.slice(0, -1).map((p) => {
35
+ const tokens = p.match(/[A-Za-z_][A-Za-z0-9_]*/g);
36
+ return tokens && tokens.length ? tokens[tokens.length - 1] : '';
37
+ });
38
+ return `${labels.join(':')}:`;
39
+ }
40
+
41
+ function jsNameFromObjcDecl(decl: string): string {
42
+ const stripped = decl.split('//', 1)[0].trim().replace(/;$/, '').trim();
43
+ const noPrefix = stripped.replace(/^[-+]\s*\([^)]*\)\s*/, '').trim();
44
+ if (!noPrefix.includes(':')) return noPrefix.split(/\s|\(/, 1)[0].trim();
45
+ const parts = noPrefix.split(':');
46
+ const labels = parts.slice(0, -1).map((p) => {
47
+ const tokens = p.match(/[A-Za-z_][A-Za-z0-9_]*/g);
48
+ return tokens && tokens.length ? tokens[tokens.length - 1] : '';
49
+ });
50
+ if (!labels.length) return '';
51
+ let js = labels[0];
52
+ for (const lab of labels.slice(1)) {
53
+ if (!lab) continue;
54
+ js += lab[0].toUpperCase() + lab.slice(1);
55
+ }
56
+ return js;
57
+ }
58
+
59
+ function parseProtocolFromHeader(headerText: string, protocolName: string): JsbApi {
60
+ const lines = headerText.split(/\r?\n/);
61
+ let inProtocol = false;
62
+ const properties: string[] = [];
63
+ const instanceMethods: string[] = [];
64
+ const classMethods: string[] = [];
65
+ const exportAliases: Record<string, string> = {};
66
+ let pendingExportAs: string | null = null;
67
+
68
+ for (const raw of lines) {
69
+ const line = raw.trim();
70
+ if (!line || line.startsWith('#') || line.startsWith('//')) continue;
71
+ const start = line.match(/^@protocol\s+(\w+)\b/);
72
+ if (start) {
73
+ inProtocol = start[1] === protocolName;
74
+ pendingExportAs = null;
75
+ continue;
76
+ }
77
+ if (!inProtocol) continue;
78
+ if (line === '@end') break;
79
+
80
+ if (line.startsWith('JSExportAs(')) {
81
+ const m = line.match(/^JSExportAs\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*,/);
82
+ if (m) pendingExportAs = m[1];
83
+ continue;
84
+ }
85
+ if (line.startsWith('@property')) {
86
+ const m = line.match(/([A-Za-z_][A-Za-z0-9_]*)\s*;\s*(?:(?:\/\/).*)?$/);
87
+ if (m) properties.push(m[1]);
88
+ continue;
89
+ }
90
+ if (line.startsWith('- (') || line.startsWith('+ (')) {
91
+ const jsName = pendingExportAs || jsNameFromObjcDecl(line);
92
+ const selector = selectorGuessFromDecl(line);
93
+ if (pendingExportAs) exportAliases[jsName] = selector;
94
+ pendingExportAs = null;
95
+ if (line.startsWith('+ (')) classMethods.push(jsName);
96
+ else instanceMethods.push(jsName);
97
+ continue;
98
+ }
99
+ }
100
+
101
+ const uniq = (arr: string[]) => Array.from(new Set(arr.filter(Boolean))).sort();
102
+ const sortedAliases = Object.fromEntries(
103
+ Object.entries(exportAliases).sort(([a], [b]) => a.localeCompare(b)),
104
+ ) as Record<string, string>;
105
+
106
+ return {
107
+ protocol: protocolName,
108
+ properties: uniq(properties),
109
+ instance_methods: uniq(instanceMethods),
110
+ class_methods: uniq(classMethods),
111
+ export_aliases: sortedAliases,
112
+ };
113
+ }
114
+
115
+ async function loadHeaderText(protocol: string): Promise<{ source: string; text: string } | null> {
116
+ const response = await fetch('/definitions-manifest.json');
117
+ if (!response.ok) throw new Error(`manifest HTTP ${response.status}`);
118
+ const manifest = (await response.json()) as Record<string, string>;
119
+ const source = manifest[protocol];
120
+ if (!source) return null;
121
+
122
+ const headerResponse = await fetch(`/definitions/${source}`);
123
+ if (!headerResponse.ok) throw new Error(`header HTTP ${headerResponse.status}`);
124
+ return { source, text: await headerResponse.text() };
125
+ }
126
+
127
+ function ApiList({
128
+ title,
129
+ items,
130
+ suffix = '',
131
+ }: {
132
+ title: string;
133
+ items: string[];
134
+ suffix?: string;
135
+ }) {
136
+ if (!items.length) return null;
137
+ return (
138
+ <>
139
+ <h3>{title}</h3>
140
+ <ul>
141
+ {items.map((item) => (
142
+ <li key={item}>
143
+ <code>
144
+ {item}
145
+ {suffix}
146
+ </code>
147
+ </li>
148
+ ))}
149
+ </ul>
150
+ </>
151
+ );
152
+ }
153
+
154
+ export function JsbApiFooter({ slug, title }: { slug: string; title: string }) {
155
+ const config = GLOBAL_PAGE_PROTOCOL_MAP[slug];
156
+ const protocol = useMemo(() => config?.protocol ?? protocolFromTitle(title), [config?.protocol, title]);
157
+ const [state, setState] = useState<
158
+ | { status: 'loading' }
159
+ | { status: 'hidden' }
160
+ | { status: 'ready'; api: JsbApi; source: string }
161
+ >({ status: 'loading' });
162
+
163
+ useEffect(() => {
164
+ if (!slug.startsWith('reference/')) {
165
+ setState({ status: 'hidden' });
166
+ return;
167
+ }
168
+
169
+ let cancelled = false;
170
+ setState({ status: 'loading' });
171
+ loadHeaderText(protocol)
172
+ .then((loaded) => {
173
+ if (cancelled) return;
174
+ if (!loaded) {
175
+ setState({ status: 'hidden' });
176
+ return;
177
+ }
178
+ setState({
179
+ status: 'ready',
180
+ api: parseProtocolFromHeader(loaded.text, protocol),
181
+ source: loaded.source,
182
+ });
183
+ })
184
+ .catch((error: unknown) => {
185
+ console.error('Failed to load JSB API footer', {
186
+ protocol,
187
+ slug,
188
+ error,
189
+ });
190
+ if (!cancelled) setState({ status: 'hidden' });
191
+ });
192
+
193
+ return () => {
194
+ cancelled = true;
195
+ };
196
+ }, [protocol, slug]);
197
+
198
+ if (state.status === 'hidden') return null;
199
+
200
+ const only = new Set(config?.only ?? ['properties', 'class', 'instance', 'aliases']);
201
+ const aliasKeys = state.status === 'ready' ? Object.keys(state.api.export_aliases) : [];
202
+
203
+ return (
204
+ <section className="jsb-api" data-jsb-api>
205
+ <details className="jsb-api__details">
206
+ <summary className="jsb-api__summary">头文件API清单</summary>
207
+ <p className="jsb-api__meta">
208
+ {state.status === 'loading' ? '正在加载...' : ''}
209
+ </p>
210
+ <p className="jsb-api__meta">
211
+ 协议:<code>{protocol}</code>,来源:
212
+ <code>{state.status === 'ready' ? state.source : '-'}</code>
213
+ </p>
214
+ {state.status === 'ready' ? (
215
+ <div>
216
+ {only.has('properties') ? <ApiList title="属性" items={state.api.properties} /> : null}
217
+ {only.has('class') ? <ApiList title="类方法" items={state.api.class_methods} suffix="()" /> : null}
218
+ {only.has('instance') ? (
219
+ <ApiList title="实例方法" items={state.api.instance_methods} suffix="()" />
220
+ ) : null}
221
+ {only.has('aliases') && aliasKeys.length ? (
222
+ <>
223
+ <h3>JSExportAs别名</h3>
224
+ <table>
225
+ <thead>
226
+ <tr>
227
+ <th>JS名</th>
228
+ <th>ObjC selector(推断)</th>
229
+ </tr>
230
+ </thead>
231
+ <tbody>
232
+ {aliasKeys.map((jsName) => (
233
+ <tr key={jsName}>
234
+ <td>
235
+ <code>{jsName}</code>
236
+ </td>
237
+ <td>
238
+ <code>{state.api.export_aliases[jsName]}</code>
239
+ </td>
240
+ </tr>
241
+ ))}
242
+ </tbody>
243
+ </table>
244
+ </>
245
+ ) : null}
246
+ </div>
247
+ ) : null}
248
+ </details>
249
+ </section>
250
+ );
251
+ }