fumapress 0.3.0 → 0.4.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.
- package/css/generated.css +15 -0
- package/dist/adapters/mdx.js +7 -5
- package/dist/components/openapi.js +6 -0
- package/dist/components/openapi.payload.js +21 -0
- package/dist/config.d.ts +10 -9
- package/dist/config.js +18 -9
- package/dist/index.d.ts +3 -3
- package/dist/layouts/blog.d.ts +1 -1
- package/dist/layouts/blog.js +1 -4
- package/dist/layouts/docs.js +1 -4
- package/dist/layouts/home.js +2 -5
- package/dist/layouts/notebook.js +1 -4
- package/dist/layouts/switch.js +3 -7
- package/dist/lib/shared.d.ts +4 -15
- package/dist/lib/shared.js +23 -4
- package/dist/lib/types.d.ts +32 -9
- package/dist/plugins/blog.d.ts +1 -0
- package/dist/plugins/blog.js +127 -120
- package/dist/plugins/flexsearch.js +4 -3
- package/dist/plugins/internal/disable-search.js +15 -0
- package/dist/plugins/llms.txt.d.ts +1 -1
- package/dist/plugins/llms.txt.js +6 -5
- package/dist/plugins/openapi.d.ts +20 -0
- package/dist/plugins/openapi.js +102 -0
- package/dist/plugins/orama-search.js +4 -3
- package/dist/plugins/takumi.js +1 -0
- package/dist/router.d.ts +6 -4
- package/dist/router.js +29 -29
- package/dist/vite.d.ts +11 -3
- package/dist/vite.js +3 -4
- package/package.json +13 -7
package/css/generated.css
CHANGED
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
@source inline("createBlogLayoutPage");
|
|
40
40
|
@source inline("createBlogTagPage");
|
|
41
41
|
@source inline("createBlogTagsPage");
|
|
42
|
+
@source inline("createClientAPIPage");
|
|
43
|
+
@source inline("createContext");
|
|
42
44
|
@source inline("createDocsLayoutPage");
|
|
43
45
|
@source inline("createHomeLayout");
|
|
44
46
|
@source inline("createHomeLayoutPage");
|
|
@@ -53,10 +55,13 @@
|
|
|
53
55
|
@source inline("data");
|
|
54
56
|
@source inline("data-version");
|
|
55
57
|
@source inline("date");
|
|
58
|
+
@source inline("decoded");
|
|
56
59
|
@source inline("decoration-fd-primary");
|
|
57
60
|
@source inline("default");
|
|
61
|
+
@source inline("defined");
|
|
58
62
|
@source inline("detect");
|
|
59
63
|
@source inline("detector");
|
|
64
|
+
@source inline("do");
|
|
60
65
|
@source inline("duration-150");
|
|
61
66
|
@source inline("else");
|
|
62
67
|
@source inline("empty");
|
|
@@ -66,6 +71,7 @@
|
|
|
66
71
|
@source inline("export");
|
|
67
72
|
@source inline("extends");
|
|
68
73
|
@source inline("false");
|
|
74
|
+
@source inline("find");
|
|
69
75
|
@source inline("fixed");
|
|
70
76
|
@source inline("flex");
|
|
71
77
|
@source inline("flex-1");
|
|
@@ -106,7 +112,9 @@
|
|
|
106
112
|
@source inline("inherit");
|
|
107
113
|
@source inline("inline-flex");
|
|
108
114
|
@source inline("interface");
|
|
115
|
+
@source inline("is");
|
|
109
116
|
@source inline("isLoading");
|
|
117
|
+
@source inline("it");
|
|
110
118
|
@source inline("item");
|
|
111
119
|
@source inline("items");
|
|
112
120
|
@source inline("items-center");
|
|
@@ -164,6 +172,7 @@
|
|
|
164
172
|
@source inline("page");
|
|
165
173
|
@source inline("pageProps");
|
|
166
174
|
@source inline("panelButtonVariants");
|
|
175
|
+
@source inline("payload");
|
|
167
176
|
@source inline("pb-20");
|
|
168
177
|
@source inline("pb-6");
|
|
169
178
|
@source inline("posts");
|
|
@@ -196,6 +205,7 @@
|
|
|
196
205
|
@source inline("rounded-lg");
|
|
197
206
|
@source inline("rounded-xl");
|
|
198
207
|
@source inline("schema");
|
|
208
|
+
@source inline("schemaId");
|
|
199
209
|
@source inline("search");
|
|
200
210
|
@source inline("setOpen");
|
|
201
211
|
@source inline("shadow-inner");
|
|
@@ -215,6 +225,7 @@
|
|
|
215
225
|
@source inline("static");
|
|
216
226
|
@source inline("string");
|
|
217
227
|
@source inline("styles");
|
|
228
|
+
@source inline("sure");
|
|
218
229
|
@source inline("tags");
|
|
219
230
|
@source inline("tagsPath");
|
|
220
231
|
@source inline("text-2xl");
|
|
@@ -227,6 +238,7 @@
|
|
|
227
238
|
@source inline("text-xs");
|
|
228
239
|
@source inline("the");
|
|
229
240
|
@source inline("this");
|
|
241
|
+
@source inline("throw");
|
|
230
242
|
@source inline("title");
|
|
231
243
|
@source inline("to");
|
|
232
244
|
@source inline("toc");
|
|
@@ -244,12 +256,15 @@
|
|
|
244
256
|
@source inline("useCopyButton");
|
|
245
257
|
@source inline("useDocsSearch");
|
|
246
258
|
@source inline("useI18n");
|
|
259
|
+
@source inline("useMemo");
|
|
247
260
|
@source inline("useState");
|
|
248
261
|
@source inline("useTOCItems");
|
|
262
|
+
@source inline("value");
|
|
249
263
|
@source inline("variant");
|
|
250
264
|
@source inline("w-full");
|
|
251
265
|
@source inline("waku");
|
|
252
266
|
@source inline("xl:grid-cols-4");
|
|
253
267
|
@source inline("xl:grid-cols-6");
|
|
268
|
+
@source inline("you");
|
|
254
269
|
@source inline("z-2");
|
|
255
270
|
@source inline("z-20");
|
package/dist/adapters/mdx.js
CHANGED
|
@@ -3,7 +3,12 @@ import defaultMdxComponents, { createRelativeLink } from "fumadocs-ui/mdx";
|
|
|
3
3
|
import { z } from "zod/mini";
|
|
4
4
|
//#region src/adapters/mdx.ts
|
|
5
5
|
function fumadocsMdx(options) {
|
|
6
|
-
const getMdxComponents = options?.getMdxComponents
|
|
6
|
+
const getMdxComponents = options?.getMdxComponents ?? async function(page) {
|
|
7
|
+
return {
|
|
8
|
+
...defaultMdxComponents,
|
|
9
|
+
a: createRelativeLink(await this.getLoader(), page)
|
|
10
|
+
};
|
|
11
|
+
};
|
|
7
12
|
return {
|
|
8
13
|
async "core:get-text"(page) {
|
|
9
14
|
if (isAsyncEntry(page.data) || isSyncEntry(page.data)) return page.data.getText("processed");
|
|
@@ -17,10 +22,7 @@ function fumadocsMdx(options) {
|
|
|
17
22
|
if (isSyncEntry(page.data)) body = page.data.body;
|
|
18
23
|
else if (isAsyncEntry(page.data)) body = (await page.data.load()).body;
|
|
19
24
|
else return;
|
|
20
|
-
return createElement(body,
|
|
21
|
-
...defaultMdxComponents,
|
|
22
|
-
a: createRelativeLink(await this.getLoader(), page)
|
|
23
|
-
} });
|
|
25
|
+
return createElement(body, { components: await getMdxComponents.call(this, page) });
|
|
24
26
|
},
|
|
25
27
|
async "core:render-toc"(page) {
|
|
26
28
|
if (isSyncEntry(page.data)) return page.data.toc;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, use, useMemo } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/openapi.payload.tsx
|
|
5
|
+
const Context = createContext(null);
|
|
6
|
+
function PayloadProvider({ payload, children }) {
|
|
7
|
+
return /* @__PURE__ */ jsx(Context, {
|
|
8
|
+
value: useMemo(() => JSON.parse(payload), [payload]),
|
|
9
|
+
children
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function WithPayload({ schemaId, Comp, props }) {
|
|
13
|
+
const payload = use(Context)?.[schemaId];
|
|
14
|
+
if (!payload) throw new Error(`[Fumapress] Failed to find OpenAPI payload for schema "${schemaId}", do you sure it is defined in createOpenAPI()?`);
|
|
15
|
+
return /* @__PURE__ */ jsx(Comp, {
|
|
16
|
+
payload,
|
|
17
|
+
...props
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { PayloadProvider, WithPayload };
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppContext } from "./lib/shared.js";
|
|
2
|
-
import { Adapter, Awaitable,
|
|
2
|
+
import { Adapter, Awaitable, ServerPluginOption } from "./lib/types.js";
|
|
3
3
|
import { ComponentType, ReactNode } from "react";
|
|
4
4
|
import { TranslationsOption } from "fumadocs-ui/contexts/i18n";
|
|
5
5
|
import { LoaderConfig, LoaderOutput } from "fumadocs-core/source";
|
|
@@ -22,12 +22,8 @@ interface Config<C extends ConfigContext = ConfigContext> {
|
|
|
22
22
|
/** the default content loader */
|
|
23
23
|
loader: LoaderOutput<C["loaderConfig"]> | (() => Awaitable<LoaderOutput<C["loaderConfig"]>>);
|
|
24
24
|
site?: SiteConfig;
|
|
25
|
-
layouts?: Partial<Layouts>;
|
|
26
|
-
plugins?: ServerPlugin[];
|
|
27
|
-
/** adapter for content sources, use `fumadocs-mdx` if not specified */
|
|
28
|
-
adapters?: Adapter[];
|
|
29
25
|
i18n?: I18nConfig$1<C["lang"]>;
|
|
30
|
-
meta?: MetaConfig<C
|
|
26
|
+
meta?: MetaConfig<NoInfer<C>>;
|
|
31
27
|
}
|
|
32
28
|
interface Layouts<C extends ConfigContext = ConfigContext> {
|
|
33
29
|
root: ComponentType<{
|
|
@@ -37,8 +33,9 @@ interface Layouts<C extends ConfigContext = ConfigContext> {
|
|
|
37
33
|
}>;
|
|
38
34
|
page: ComponentType<{
|
|
39
35
|
lang?: string;
|
|
40
|
-
ctx: AppContext<C>;
|
|
41
36
|
slugs: string[];
|
|
37
|
+
ctx: AppContext<C>;
|
|
38
|
+
page: C["loaderConfig"]["page"];
|
|
42
39
|
}>;
|
|
43
40
|
notFound: ComponentType<{
|
|
44
41
|
lang?: string;
|
|
@@ -80,9 +77,13 @@ interface I18nConfigBuilder<Lang extends string> extends I18nConfig$1<Lang> {
|
|
|
80
77
|
toCore: () => I18nConfig<Lang>;
|
|
81
78
|
}
|
|
82
79
|
interface ConfigBuilder<C extends ConfigContext> extends Config<C> {
|
|
83
|
-
|
|
80
|
+
getPlugins: () => ServerPluginOption<C>[];
|
|
81
|
+
getLayouts: () => Partial<Layouts<C>>;
|
|
82
|
+
getAdapters: () => Adapter<C>[];
|
|
83
|
+
usePlugins: (...plugins: ServerPluginOption<C>[]) => ConfigBuilder<C>;
|
|
84
84
|
useLayouts: (layouts: Partial<Layouts<C>>) => ConfigBuilder<C>;
|
|
85
|
-
|
|
85
|
+
/** Add adapter for content sources, use `fumadocs-mdx` if not specified */
|
|
86
|
+
useAdapters: (...adapters: Adapter<C>[]) => ConfigBuilder<C>;
|
|
86
87
|
}
|
|
87
88
|
declare function defineConfig<C extends LoaderConfig, L extends string = string>(config: Config<{
|
|
88
89
|
loaderConfig: C;
|
package/dist/config.js
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
//#region src/config.ts
|
|
2
2
|
function defineConfig(config) {
|
|
3
|
+
const plugins = [];
|
|
4
|
+
const layouts = {};
|
|
5
|
+
const adapters = [];
|
|
3
6
|
return {
|
|
4
7
|
...config,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
getPlugins() {
|
|
9
|
+
return plugins;
|
|
10
|
+
},
|
|
11
|
+
getAdapters() {
|
|
12
|
+
return adapters;
|
|
13
|
+
},
|
|
14
|
+
getLayouts() {
|
|
15
|
+
return layouts;
|
|
16
|
+
},
|
|
17
|
+
useAdapters(...values) {
|
|
18
|
+
adapters.push(...values);
|
|
8
19
|
return this;
|
|
9
20
|
},
|
|
10
|
-
useLayouts(
|
|
11
|
-
|
|
12
|
-
Object.assign(this.layouts, layouts);
|
|
21
|
+
useLayouts(overrides) {
|
|
22
|
+
Object.assign(layouts, overrides);
|
|
13
23
|
return this;
|
|
14
24
|
},
|
|
15
|
-
usePlugins(...
|
|
16
|
-
|
|
17
|
-
this.plugins.push(...plugins);
|
|
25
|
+
usePlugins(...values) {
|
|
26
|
+
plugins.push(...values);
|
|
18
27
|
return this;
|
|
19
28
|
}
|
|
20
29
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppContext
|
|
1
|
+
import { AppContext } from "./lib/shared.js";
|
|
2
2
|
import { BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, MetaConfig, SiteConfig, defineConfig, defineI18nConfig } from "./config.js";
|
|
3
|
-
import { Adapter, RouteFns, ServerPlugin } from "./lib/types.js";
|
|
4
|
-
export { type Adapter, type AppContext, type AppContextData, BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, MetaConfig, type RouteFns, type ServerPlugin, SiteConfig, defineConfig, defineI18nConfig };
|
|
3
|
+
import { Adapter, AppContextData, RouteFns, ServerPlugin, ServerPluginOption } from "./lib/types.js";
|
|
4
|
+
export { type Adapter, type AppContext, type AppContextData, BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, MetaConfig, type RouteFns, type ServerPlugin, type ServerPluginOption, SiteConfig, defineConfig, defineI18nConfig };
|
package/dist/layouts/blog.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { HomeLayoutOptions } from "./home.js";
|
|
2
1
|
import { AppContext } from "../lib/shared.js";
|
|
3
2
|
import { ConfigContext } from "../config.js";
|
|
3
|
+
import { HomeLayoutOptions } from "./home.js";
|
|
4
4
|
import { Awaitable } from "../lib/types.js";
|
|
5
5
|
import { BlogLayout, BlogLayoutPage } from "../plugins/blog.js";
|
|
6
6
|
import { ReactNode } from "react";
|
package/dist/layouts/blog.js
CHANGED
|
@@ -6,7 +6,6 @@ import { BlogPanel, BlogProvider } from "../components/blog-panel.js";
|
|
|
6
6
|
import { createHomeLayout } from "./home.js";
|
|
7
7
|
import { Link } from "waku";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { unstable_notFound } from "waku/router/server";
|
|
10
9
|
import { TagIcon } from "lucide-react";
|
|
11
10
|
//#region src/layouts/blog.tsx
|
|
12
11
|
function createBlogLayout(options) {
|
|
@@ -24,9 +23,7 @@ function createBlogLayout(options) {
|
|
|
24
23
|
}
|
|
25
24
|
function createBlogLayoutPage(options = {}) {
|
|
26
25
|
const { render } = options;
|
|
27
|
-
return async function BlogLayoutPage({
|
|
28
|
-
const page = (await ctx.getLoader()).getPage(slugs, lang);
|
|
29
|
-
if (!page) unstable_notFound();
|
|
26
|
+
return async function BlogLayoutPage({ ctx, page, blog, lang }) {
|
|
30
27
|
const tags = await getTags(ctx, page);
|
|
31
28
|
const _raw = await render?.call(ctx, page);
|
|
32
29
|
const result = {
|
package/dist/layouts/docs.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { baseLayoutProps, createTransformChildren, getGitHubFileUrl, getLastModifiedDate, mergeLayoutConfigs, renderBody, renderPageMeta, renderToc } from "../lib/shared.js";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { unstable_notFound } from "waku/router/server";
|
|
4
3
|
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
|
5
4
|
import { DocsBody, DocsDescription, DocsPage, DocsTitle, MarkdownCopyButton, PageLastUpdate, ViewOptionsPopover } from "fumadocs-ui/layouts/docs/page";
|
|
6
5
|
//#region src/layouts/docs.tsx
|
|
7
6
|
function createDocsLayoutPage({ render } = {}) {
|
|
8
7
|
const TDocsLayout = createTransformChildren(DocsLayout);
|
|
9
8
|
const TDocsPage = createTransformChildren(DocsPage);
|
|
10
|
-
return async function Layout({
|
|
9
|
+
return async function Layout({ lang, page, ctx }) {
|
|
11
10
|
const { getLoader, layouts, data: { "core:docs-layout": layoutData } } = ctx;
|
|
12
11
|
const source = await getLoader();
|
|
13
|
-
const page = source.getPage(slugs, lang);
|
|
14
|
-
if (!page) unstable_notFound();
|
|
15
12
|
async function getLayoutProps(overrides) {
|
|
16
13
|
const inherit = await layouts.defaultProps?.call(ctx, { lang });
|
|
17
14
|
return mergeLayoutConfigs({ tree: source.getPageTree(lang) }, baseLayoutProps(ctx), inherit, overrides);
|
package/dist/layouts/home.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { baseLayoutProps, createTransformChildren, mergeLayoutConfigs, renderBody, renderPageMeta } from "../lib/shared.js";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { unstable_notFound } from "waku/router/server";
|
|
4
3
|
import { HomeLayout } from "fumadocs-ui/layouts/home";
|
|
5
4
|
//#region src/layouts/home.tsx
|
|
6
5
|
function createHomeLayoutPage({ render } = {}) {
|
|
7
6
|
const THomeLayout = createTransformChildren(HomeLayout);
|
|
8
|
-
return async function Layout({
|
|
9
|
-
const {
|
|
10
|
-
const page = (await getLoader()).getPage(slugs, lang);
|
|
11
|
-
if (!page) unstable_notFound();
|
|
7
|
+
return async function Layout({ lang, page, ctx }) {
|
|
8
|
+
const { layouts, data: { "core:home-layout": layoutData } } = ctx;
|
|
12
9
|
async function getLayoutProps(overrides) {
|
|
13
10
|
const inherit = await layouts.defaultProps?.call(ctx, { lang });
|
|
14
11
|
return mergeLayoutConfigs(baseLayoutProps(ctx), inherit, overrides);
|
package/dist/layouts/notebook.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { baseLayoutProps, createTransformChildren, getGitHubFileUrl, getLastModifiedDate, mergeLayoutConfigs, renderBody, renderPageMeta, renderToc } from "../lib/shared.js";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { unstable_notFound } from "waku/router/server";
|
|
4
3
|
import { DocsLayout } from "fumadocs-ui/layouts/notebook";
|
|
5
4
|
import { DocsBody, DocsDescription, DocsPage, DocsTitle, MarkdownCopyButton, PageLastUpdate, ViewOptionsPopover } from "fumadocs-ui/layouts/notebook/page";
|
|
6
5
|
//#region src/layouts/notebook.tsx
|
|
7
6
|
function createNotebookLayoutPage({ render } = {}) {
|
|
8
7
|
const TDocsLayout = createTransformChildren(DocsLayout);
|
|
9
8
|
const TDocsPage = createTransformChildren(DocsPage);
|
|
10
|
-
return async function Layout({
|
|
9
|
+
return async function Layout({ lang, page, ctx }) {
|
|
11
10
|
const { getLoader, layouts, data: { "core:notebook-layout": layoutData } } = ctx;
|
|
12
11
|
const source = await getLoader();
|
|
13
|
-
const page = source.getPage(slugs, lang);
|
|
14
|
-
if (!page) unstable_notFound();
|
|
15
12
|
async function getLayoutProps(overrides) {
|
|
16
13
|
const inherit = await layouts.defaultProps?.call(ctx, { lang });
|
|
17
14
|
return mergeLayoutConfigs({ tree: source.getPageTree(lang) }, baseLayoutProps(ctx), inherit, overrides);
|
package/dist/layouts/switch.js
CHANGED
|
@@ -3,9 +3,8 @@ import { unstable_notFound } from "waku/router/server";
|
|
|
3
3
|
//#region src/layouts/switch.tsx
|
|
4
4
|
function createLayoutSwitchAuto(layouts) {
|
|
5
5
|
return async function(props) {
|
|
6
|
-
const {
|
|
7
|
-
|
|
8
|
-
if (!page?.type) unstable_notFound();
|
|
6
|
+
const { page } = props;
|
|
7
|
+
if (!page.type) unstable_notFound();
|
|
9
8
|
const Layout = layouts[page.type];
|
|
10
9
|
if (!Layout) unstable_notFound();
|
|
11
10
|
return /* @__PURE__ */ jsx(Layout, { ...props });
|
|
@@ -13,10 +12,7 @@ function createLayoutSwitchAuto(layouts) {
|
|
|
13
12
|
}
|
|
14
13
|
function createLayoutSwitch(detector, layouts) {
|
|
15
14
|
return async function(props) {
|
|
16
|
-
const
|
|
17
|
-
const page = (await ctx.getLoader()).getPage(slugs, lang);
|
|
18
|
-
if (!page) unstable_notFound();
|
|
19
|
-
const Layout = layouts[detector.call(ctx, page)];
|
|
15
|
+
const Layout = layouts[detector.call(props.ctx, props.page)];
|
|
20
16
|
if (!Layout) unstable_notFound();
|
|
21
17
|
return /* @__PURE__ */ jsx(Layout, { ...props });
|
|
22
18
|
};
|
package/dist/lib/shared.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import { DocsLayoutContextData } from "../layouts/docs.js";
|
|
2
|
-
import { HomeLayoutContextData } from "../layouts/home.js";
|
|
3
|
-
import { NotebookLayoutContextData } from "../layouts/notebook.js";
|
|
4
1
|
import { BuildMode, ConfigContext, I18nConfig, Layouts, MetaConfig } from "../config.js";
|
|
5
|
-
import { Adapter, Awaitable, ServerPlugin } from "./types.js";
|
|
2
|
+
import { Adapter, AppContextData, Awaitable, ServerPlugin } from "./types.js";
|
|
6
3
|
import { ComponentType, ReactNode } from "react";
|
|
7
|
-
import {
|
|
8
|
-
import { LoaderOutput, Page } from "fumadocs-core/source";
|
|
4
|
+
import { LoaderOutput } from "fumadocs-core/source";
|
|
9
5
|
|
|
10
6
|
//#region src/lib/shared.d.ts
|
|
11
7
|
interface AppContext<C extends ConfigContext = ConfigContext> {
|
|
@@ -13,7 +9,7 @@ interface AppContext<C extends ConfigContext = ConfigContext> {
|
|
|
13
9
|
getLoader: () => Awaitable<LoaderOutput<C["loaderConfig"]>>;
|
|
14
10
|
plugins: ServerPlugin<C>[];
|
|
15
11
|
adapters: Adapter<C>[];
|
|
16
|
-
layouts:
|
|
12
|
+
layouts: Layouts<C>;
|
|
17
13
|
/** always `undefined`, easier way to infer types */
|
|
18
14
|
$context: C;
|
|
19
15
|
/**
|
|
@@ -33,15 +29,8 @@ interface AppContext<C extends ConfigContext = ConfigContext> {
|
|
|
33
29
|
};
|
|
34
30
|
};
|
|
35
31
|
}
|
|
36
|
-
interface AppContextData {
|
|
37
|
-
"core:page-meta"?: ((page: Page) => ReactNode)[];
|
|
38
|
-
"core:notebook-layout"?: NotebookLayoutContextData;
|
|
39
|
-
"core:docs-layout"?: DocsLayoutContextData;
|
|
40
|
-
"core:home-layout"?: HomeLayoutContextData;
|
|
41
|
-
"core:provider"?: ((props: RootProviderProps) => Awaitable<RootProviderProps>)[];
|
|
42
|
-
}
|
|
43
32
|
type TransformChildren<T> = Omit<T, "children"> & {
|
|
44
33
|
children?: ((nodes: ReactNode) => ReactNode)[];
|
|
45
34
|
};
|
|
46
35
|
//#endregion
|
|
47
|
-
export { AppContext,
|
|
36
|
+
export { AppContext, TransformChildren };
|
package/dist/lib/shared.js
CHANGED
|
@@ -2,20 +2,39 @@ import { __toESM } from "../_virtual/_rolldown/runtime.js";
|
|
|
2
2
|
import { getGitRootDir } from "./fs.js";
|
|
3
3
|
import { fumadocsMdx } from "../adapters/mdx.js";
|
|
4
4
|
import { require_deepmerge } from "../node_modules/.pnpm/@fastify_deepmerge@3.2.1/node_modules/@fastify/deepmerge/index.js";
|
|
5
|
+
import { disableSearchPlugin } from "../plugins/internal/disable-search.js";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import { Fragment, isValidElement } from "react";
|
|
7
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
9
|
//#region src/lib/shared.tsx
|
|
9
10
|
var import_deepmerge = /* @__PURE__ */ __toESM(require_deepmerge());
|
|
10
|
-
function parseConfig(config) {
|
|
11
|
+
async function parseConfig(config) {
|
|
12
|
+
let adapters = config.getAdapters();
|
|
13
|
+
if (adapters.length === 0) adapters = [fumadocsMdx()];
|
|
14
|
+
const ORDER = {
|
|
15
|
+
pre: -1,
|
|
16
|
+
post: 1,
|
|
17
|
+
_: 0
|
|
18
|
+
};
|
|
19
|
+
function resolvePlugins(plugins) {
|
|
20
|
+
const flat = plugins.flat(Infinity);
|
|
21
|
+
flat.push(disableSearchPlugin());
|
|
22
|
+
return flat.sort((a, b) => ORDER[a.enforce ?? "_"] - ORDER[b.enforce ?? "_"]);
|
|
23
|
+
}
|
|
24
|
+
const layouts = config.getLayouts();
|
|
11
25
|
return {
|
|
12
26
|
getLoader() {
|
|
13
27
|
if (typeof config.loader === "function") return config.loader();
|
|
14
28
|
return config.loader;
|
|
15
29
|
},
|
|
16
|
-
layouts:
|
|
17
|
-
|
|
18
|
-
|
|
30
|
+
layouts: {
|
|
31
|
+
...layouts,
|
|
32
|
+
root: layouts.root ?? (await import("../layouts/root.js")).createRootLayout(),
|
|
33
|
+
page: layouts.page ?? (await import("../layouts/docs.js")).createDocsLayoutPage(),
|
|
34
|
+
notFound: layouts.notFound ?? (await import("fumadocs-ui/layouts/home/not-found")).DefaultNotFound
|
|
35
|
+
},
|
|
36
|
+
plugins: resolvePlugins(config.getPlugins()),
|
|
37
|
+
adapters,
|
|
19
38
|
$context: void 0,
|
|
20
39
|
data: {},
|
|
21
40
|
i18nConfig: config.i18n,
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { AppContext } from "./shared.js";
|
|
2
2
|
import { ConfigContext } from "../config.js";
|
|
3
|
+
import { DocsLayoutContextData } from "../layouts/docs.js";
|
|
4
|
+
import { HomeLayoutContextData } from "../layouts/home.js";
|
|
5
|
+
import { NotebookLayoutContextData } from "../layouts/notebook.js";
|
|
3
6
|
import { ReactNode } from "react";
|
|
4
7
|
import { CreateApi, CreateLayout, CreatePage, CreateRoot, CreateSlice } from "waku/router/server";
|
|
5
8
|
import { TOCItemType } from "fumadocs-core/toc";
|
|
9
|
+
import { Page } from "fumadocs-core/source";
|
|
6
10
|
import { StructuredData } from "fumadocs-core/mdx-plugins";
|
|
11
|
+
import { RootProviderProps } from "fumadocs-ui/provider/base";
|
|
7
12
|
|
|
8
13
|
//#region src/lib/types.d.ts
|
|
9
14
|
type Awaitable<T> = T | Promise<T>;
|
|
@@ -17,29 +22,47 @@ interface Adapter<C extends ConfigContext = ConfigContext> {
|
|
|
17
22
|
"core:get-modified-date"?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => Awaitable<Date | undefined>;
|
|
18
23
|
"blog:get-tags"?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => Awaitable<string[] | undefined>;
|
|
19
24
|
}
|
|
20
|
-
interface CreatePagesContext<C extends ConfigContext = ConfigContext> extends AppContext<C> {
|
|
21
|
-
/** call this function if the page's route is already created by your plugin */
|
|
22
|
-
markResolved: (page: C["loaderConfig"]["page"]) => void;
|
|
23
|
-
}
|
|
24
25
|
interface ServerPlugin<C extends ConfigContext = ConfigContext> {
|
|
26
|
+
name?: string;
|
|
27
|
+
/** force change the order of plugin */
|
|
28
|
+
enforce?: "pre" | "post";
|
|
25
29
|
/** receive & modify context */
|
|
26
|
-
init?: (this: AppContext<C>) => void
|
|
27
|
-
createPages?: (this:
|
|
30
|
+
init?: (this: AppContext<C>) => Awaitable<void>;
|
|
31
|
+
createPages?: (this: AppContext<C>, fns: RouteFns) => Awaitable<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the given page before passing to the **default** page renderer:
|
|
34
|
+
*
|
|
35
|
+
* - `object`: replace the page object.
|
|
36
|
+
* - `false`: render not found (will also exclude from static pre-rendering).
|
|
37
|
+
* - `undefined`: fallback to default.
|
|
38
|
+
*/
|
|
39
|
+
resolvePage?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => Awaitable<C["loaderConfig"]["page"] | false | undefined>;
|
|
28
40
|
}
|
|
29
|
-
interface
|
|
41
|
+
interface BaseRouteFns {
|
|
30
42
|
createPage: CreatePage;
|
|
31
43
|
createLayout: CreateLayout;
|
|
32
44
|
createRoot: CreateRoot;
|
|
33
45
|
createApi: CreateApi;
|
|
34
46
|
createSlice: CreateSlice;
|
|
47
|
+
}
|
|
48
|
+
interface RouteFns extends BaseRouteFns {
|
|
35
49
|
createApiIsomorphic: (config: {
|
|
36
50
|
render: "static" | "dynamic";
|
|
37
51
|
path: string;
|
|
38
|
-
staticPaths?: string[][];
|
|
52
|
+
staticPaths?: string[] | string[][];
|
|
39
53
|
handler: (req: Request, ctx: {
|
|
40
54
|
params: Record<string, string | string[]>;
|
|
41
55
|
}) => Promise<Response>;
|
|
42
56
|
}) => void;
|
|
43
57
|
}
|
|
58
|
+
type ServerPluginOption<C extends ConfigContext = ConfigContext> = ServerPlugin<C> | ServerPluginOption<C>[];
|
|
59
|
+
/** can be extended from other libraries */
|
|
60
|
+
interface AppContextData {
|
|
61
|
+
"core:page-meta"?: ((page: Page) => ReactNode)[];
|
|
62
|
+
"core:notebook-layout"?: NotebookLayoutContextData;
|
|
63
|
+
"core:docs-layout"?: DocsLayoutContextData;
|
|
64
|
+
"core:home-layout"?: HomeLayoutContextData;
|
|
65
|
+
"core:provider"?: ((props: RootProviderProps) => Awaitable<RootProviderProps>)[];
|
|
66
|
+
}
|
|
44
67
|
//#endregion
|
|
45
|
-
export { Adapter, Awaitable, RouteFns, ServerPlugin };
|
|
68
|
+
export { Adapter, AppContextData, Awaitable, RouteFns, ServerPlugin, ServerPluginOption };
|
package/dist/plugins/blog.d.ts
CHANGED
package/dist/plugins/blog.js
CHANGED
|
@@ -4,6 +4,7 @@ import { groupTags, groupTagsI18n } from "../lib/shared/blog.js";
|
|
|
4
4
|
import { createBlogTagPage, createBlogTagsPage } from "../layouts/blog.tags.js";
|
|
5
5
|
import { createBlogLayout, createBlogLayoutPage } from "../layouts/blog.js";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import { unstable_notFound } from "waku/router/server";
|
|
7
8
|
//#region src/plugins/blog.tsx
|
|
8
9
|
function blogPlugin({ paths = {}, isBlog = (page) => page.type === "blog", layouts = {} } = {}) {
|
|
9
10
|
const blogCtx = {
|
|
@@ -11,158 +12,164 @@ function blogPlugin({ paths = {}, isBlog = (page) => page.type === "blog", layou
|
|
|
11
12
|
tagsPath: paths.tags ?? "/blog/tags",
|
|
12
13
|
isBlog
|
|
13
14
|
};
|
|
14
|
-
return {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
this.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
createLayout({
|
|
27
|
-
render: renderMode,
|
|
28
|
-
path: "/[lang]/(blog)",
|
|
29
|
-
component: ({ lang, children }) => {
|
|
30
|
-
return /* @__PURE__ */ jsx(Layout, {
|
|
31
|
-
lang,
|
|
32
|
-
blog: blogCtx,
|
|
33
|
-
ctx: this,
|
|
34
|
-
children
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
createPage({
|
|
39
|
-
render: renderMode,
|
|
40
|
-
path: "/[lang]/(blog)/[...slugs]",
|
|
41
|
-
staticPaths: blogPages.map((page) => [page.locale, ...page.slugs]),
|
|
42
|
-
component: ({ slugs, lang }) => {
|
|
43
|
-
return /* @__PURE__ */ jsx(Page, {
|
|
44
|
-
lang,
|
|
45
|
-
slugs,
|
|
46
|
-
blog: blogCtx,
|
|
47
|
-
ctx: this
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
if (blogCtx.indexPath !== false) {
|
|
52
|
-
const IndexPage = layouts.index ?? createBlogIndexPage();
|
|
53
|
-
createPage({
|
|
15
|
+
return {
|
|
16
|
+
name: "core:blog",
|
|
17
|
+
resolvePage(page) {
|
|
18
|
+
if (isBlog.call(this, page)) return false;
|
|
19
|
+
},
|
|
20
|
+
async createPages({ createPage, createLayout }) {
|
|
21
|
+
const renderMode = this.mode === "dynamic" ? "dynamic" : "static";
|
|
22
|
+
const blogPages = (await this.getLoader()).getPages().filter((page) => isBlog.call(this, page));
|
|
23
|
+
const Layout = layouts.layout ?? createBlogLayout();
|
|
24
|
+
const Page = layouts.page ?? createBlogLayoutPage();
|
|
25
|
+
if (this.i18nConfig) {
|
|
26
|
+
createLayout({
|
|
54
27
|
render: renderMode,
|
|
55
|
-
path:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return /* @__PURE__ */ jsx(IndexPage, {
|
|
28
|
+
path: "/[lang]/(blog)",
|
|
29
|
+
component: ({ lang, children }) => {
|
|
30
|
+
return /* @__PURE__ */ jsx(Layout, {
|
|
59
31
|
lang,
|
|
60
32
|
blog: blogCtx,
|
|
61
|
-
ctx: this
|
|
33
|
+
ctx: this,
|
|
34
|
+
children
|
|
62
35
|
});
|
|
63
36
|
}
|
|
64
37
|
});
|
|
65
|
-
}
|
|
66
|
-
if (blogCtx.tagsPath !== false) {
|
|
67
|
-
const TagsPage = layouts.tags ?? createBlogTagsPage();
|
|
68
|
-
const TagPage = layouts.tag ?? createBlogTagPage();
|
|
69
38
|
createPage({
|
|
70
|
-
path: joinPathname("/[lang]/(blog)", blogCtx.tagsPath),
|
|
71
39
|
render: renderMode,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
40
|
+
path: "/[lang]/(blog)/[...slugs]",
|
|
41
|
+
staticPaths: blogPages.map((page) => [page.locale, ...page.slugs]),
|
|
42
|
+
component: async ({ slugs, lang }) => {
|
|
43
|
+
const page = (await this.getLoader()).getPage(slugs, lang);
|
|
44
|
+
if (!page || !isBlog.call(this, page)) unstable_notFound();
|
|
45
|
+
return /* @__PURE__ */ jsx(Page, {
|
|
75
46
|
lang,
|
|
47
|
+
slugs,
|
|
76
48
|
blog: blogCtx,
|
|
49
|
+
page,
|
|
77
50
|
ctx: this
|
|
78
51
|
});
|
|
79
52
|
}
|
|
80
53
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
createLayout({
|
|
100
|
-
render: renderMode,
|
|
101
|
-
path: "/(blog)",
|
|
102
|
-
component: ({ children }) => {
|
|
103
|
-
return /* @__PURE__ */ jsx(Layout, {
|
|
104
|
-
blog: blogCtx,
|
|
105
|
-
ctx: this,
|
|
106
|
-
children
|
|
54
|
+
if (blogCtx.indexPath !== false) {
|
|
55
|
+
const IndexPage = layouts.index ?? createBlogIndexPage();
|
|
56
|
+
createPage({
|
|
57
|
+
render: renderMode,
|
|
58
|
+
path: joinPathname("/[lang]/(blog)", blogCtx.indexPath),
|
|
59
|
+
staticPaths: Object.keys(this.i18nConfig.languages),
|
|
60
|
+
component: ({ lang }) => {
|
|
61
|
+
return /* @__PURE__ */ jsx(IndexPage, {
|
|
62
|
+
lang,
|
|
63
|
+
blog: blogCtx,
|
|
64
|
+
ctx: this
|
|
65
|
+
});
|
|
66
|
+
}
|
|
107
67
|
});
|
|
108
68
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
69
|
+
if (blogCtx.tagsPath !== false) {
|
|
70
|
+
const TagsPage = layouts.tags ?? createBlogTagsPage();
|
|
71
|
+
const TagPage = layouts.tag ?? createBlogTagPage();
|
|
72
|
+
createPage({
|
|
73
|
+
path: joinPathname("/[lang]/(blog)", blogCtx.tagsPath),
|
|
74
|
+
render: renderMode,
|
|
75
|
+
staticPaths: Object.keys(this.i18nConfig.languages),
|
|
76
|
+
component: ({ lang }) => {
|
|
77
|
+
return /* @__PURE__ */ jsx(TagsPage, {
|
|
78
|
+
lang,
|
|
79
|
+
blog: blogCtx,
|
|
80
|
+
ctx: this
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
const groupedTags = await groupTagsI18n(this, blogPages);
|
|
85
|
+
const staticPaths = [];
|
|
86
|
+
for (const [locale, tags] of groupedTags) for (const tag of tags.keys()) staticPaths.push([locale, tag]);
|
|
87
|
+
createPage({
|
|
88
|
+
path: joinPathname("/[lang]/(blog)", blogCtx.tagsPath, "[tag]"),
|
|
89
|
+
render: renderMode,
|
|
90
|
+
staticPaths,
|
|
91
|
+
component: ({ lang, tag }) => {
|
|
92
|
+
return /* @__PURE__ */ jsx(TagPage, {
|
|
93
|
+
lang,
|
|
94
|
+
tag,
|
|
95
|
+
blog: blogCtx,
|
|
96
|
+
ctx: this
|
|
97
|
+
});
|
|
98
|
+
}
|
|
119
99
|
});
|
|
120
100
|
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const IndexPage = layouts.index ?? createBlogIndexPage();
|
|
124
|
-
createPage({
|
|
101
|
+
} else {
|
|
102
|
+
createLayout({
|
|
125
103
|
render: renderMode,
|
|
126
|
-
path:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return /* @__PURE__ */ jsx(IndexPage, {
|
|
104
|
+
path: "/(blog)",
|
|
105
|
+
component: ({ children }) => {
|
|
106
|
+
return /* @__PURE__ */ jsx(Layout, {
|
|
130
107
|
blog: blogCtx,
|
|
131
|
-
ctx: this
|
|
108
|
+
ctx: this,
|
|
109
|
+
children
|
|
132
110
|
});
|
|
133
111
|
}
|
|
134
112
|
});
|
|
135
|
-
}
|
|
136
|
-
if (blogCtx.tagsPath !== false) {
|
|
137
|
-
const TagsPage = layouts.tags ?? createBlogTagsPage();
|
|
138
|
-
const TagPage = layouts.tag ?? createBlogTagPage();
|
|
139
113
|
createPage({
|
|
140
|
-
path: joinPathname("/(blog)", blogCtx.tagsPath),
|
|
141
114
|
render: renderMode,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
const grouped = await groupTags(this, blogPages);
|
|
151
|
-
createPage({
|
|
152
|
-
path: joinPathname("/(blog)", blogCtx.tagsPath, "[tag]"),
|
|
153
|
-
render: renderMode,
|
|
154
|
-
staticPaths: grouped ? Array.from(grouped.keys()) : [],
|
|
155
|
-
component: ({ tag }) => {
|
|
156
|
-
return /* @__PURE__ */ jsx(TagPage, {
|
|
157
|
-
tag,
|
|
115
|
+
path: "/(blog)/[...slugs]",
|
|
116
|
+
staticPaths: blogPages.map((page) => page.slugs),
|
|
117
|
+
component: async ({ slugs }) => {
|
|
118
|
+
const page = (await this.getLoader()).getPage(slugs);
|
|
119
|
+
if (!page || !isBlog.call(this, page)) unstable_notFound();
|
|
120
|
+
return /* @__PURE__ */ jsx(Page, {
|
|
158
121
|
blog: blogCtx,
|
|
122
|
+
slugs,
|
|
123
|
+
page,
|
|
159
124
|
ctx: this
|
|
160
125
|
});
|
|
161
126
|
}
|
|
162
127
|
});
|
|
128
|
+
if (blogCtx.indexPath !== false) {
|
|
129
|
+
const IndexPage = layouts.index ?? createBlogIndexPage();
|
|
130
|
+
createPage({
|
|
131
|
+
render: renderMode,
|
|
132
|
+
path: joinPathname("/(blog)", blogCtx.indexPath),
|
|
133
|
+
staticPaths: [],
|
|
134
|
+
component: () => {
|
|
135
|
+
return /* @__PURE__ */ jsx(IndexPage, {
|
|
136
|
+
blog: blogCtx,
|
|
137
|
+
ctx: this
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (blogCtx.tagsPath !== false) {
|
|
143
|
+
const TagsPage = layouts.tags ?? createBlogTagsPage();
|
|
144
|
+
const TagPage = layouts.tag ?? createBlogTagPage();
|
|
145
|
+
createPage({
|
|
146
|
+
path: joinPathname("/(blog)", blogCtx.tagsPath),
|
|
147
|
+
render: renderMode,
|
|
148
|
+
staticPaths: [],
|
|
149
|
+
component: () => {
|
|
150
|
+
return /* @__PURE__ */ jsx(TagsPage, {
|
|
151
|
+
blog: blogCtx,
|
|
152
|
+
ctx: this
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
const grouped = await groupTags(this, blogPages);
|
|
157
|
+
createPage({
|
|
158
|
+
path: joinPathname("/(blog)", blogCtx.tagsPath, "[tag]"),
|
|
159
|
+
render: renderMode,
|
|
160
|
+
staticPaths: Array.from(grouped.keys()),
|
|
161
|
+
component: ({ tag }) => {
|
|
162
|
+
return /* @__PURE__ */ jsx(TagPage, {
|
|
163
|
+
tag,
|
|
164
|
+
blog: blogCtx,
|
|
165
|
+
ctx: this
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
163
170
|
}
|
|
164
171
|
}
|
|
165
|
-
}
|
|
172
|
+
};
|
|
166
173
|
}
|
|
167
174
|
//#endregion
|
|
168
175
|
export { blogPlugin };
|
|
@@ -13,10 +13,11 @@ function flexsearchPlugin({ buildIndex = async function buildIndexDefault(page)
|
|
|
13
13
|
throw new Error("[Fumapress] Please specify the `buildIndex` option to flexsearchPlugin()");
|
|
14
14
|
} } = {}) {
|
|
15
15
|
return {
|
|
16
|
+
name: "core:flexsearch",
|
|
16
17
|
init() {
|
|
17
|
-
|
|
18
|
-
props.search ??= {};
|
|
19
|
-
props.search.SearchDialog ??= (await import("../components/flexsearch-static.js")).default;
|
|
18
|
+
(this.data["core:provider"] ??= []).push(async (props) => {
|
|
19
|
+
props.search ??= { enabled: true };
|
|
20
|
+
if (this.mode === "static") props.search.SearchDialog ??= (await import("../components/flexsearch-static.js")).default;
|
|
20
21
|
return props;
|
|
21
22
|
});
|
|
22
23
|
},
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/plugins/internal/disable-search.ts
|
|
2
|
+
function disableSearchPlugin() {
|
|
3
|
+
return {
|
|
4
|
+
name: "core:disable-search-if-needed",
|
|
5
|
+
enforce: "post",
|
|
6
|
+
init() {
|
|
7
|
+
(this.data["core:provider"] ??= []).push((data) => {
|
|
8
|
+
data.search ??= { enabled: false };
|
|
9
|
+
return data;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { disableSearchPlugin };
|
|
@@ -4,7 +4,7 @@ import { Awaitable, ServerPlugin } from "../lib/types.js";
|
|
|
4
4
|
|
|
5
5
|
//#region src/plugins/llms.txt.d.ts
|
|
6
6
|
interface LLMsOptions<C extends ConfigContext = ConfigContext> {
|
|
7
|
-
getLLMText?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => Awaitable<string>;
|
|
7
|
+
getLLMText?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => Awaitable<string | undefined>;
|
|
8
8
|
}
|
|
9
9
|
declare function llmsPlugin<C extends ConfigContext = ConfigContext>(options?: LLMsOptions<NoInfer<C>>): ServerPlugin<C>;
|
|
10
10
|
//#endregion
|
package/dist/plugins/llms.txt.js
CHANGED
|
@@ -7,9 +7,9 @@ function llmsPlugin(options = {}) {
|
|
|
7
7
|
const txt = await adapter["core:get-text"]?.call(this, page);
|
|
8
8
|
if (txt !== void 0) return `# ${page.data.title} (${page.url})\n\n${txt}`;
|
|
9
9
|
}
|
|
10
|
-
throw new Error("[Fumapress] Please specify the `getLLMText()` option in llmsPlugin()");
|
|
11
10
|
} } = options;
|
|
12
11
|
return {
|
|
12
|
+
name: "core:llms.txt",
|
|
13
13
|
init() {
|
|
14
14
|
this.data["core:docs-layout"] ??= {};
|
|
15
15
|
this.data["core:docs-layout"].renderers ??= [];
|
|
@@ -33,9 +33,9 @@ function llmsPlugin(options = {}) {
|
|
|
33
33
|
render: defaultRenderMode,
|
|
34
34
|
path: "/llms-full.txt",
|
|
35
35
|
handler: async () => {
|
|
36
|
-
const
|
|
37
|
-
const scanned = await Promise.all(
|
|
38
|
-
return new Response(scanned.join("\n\n"));
|
|
36
|
+
const source = await this.getLoader();
|
|
37
|
+
const scanned = await Promise.all(source.getPages().map(getLLMText));
|
|
38
|
+
return new Response(scanned.filter((item) => item !== void 0).join("\n\n"));
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
41
|
createApiIsomorphic({
|
|
@@ -45,7 +45,8 @@ function llmsPlugin(options = {}) {
|
|
|
45
45
|
handler: async (_req, { params }) => {
|
|
46
46
|
const page = (await this.getLoader()).getPage(markdownPathToSlugs(params.slugs), params.lang);
|
|
47
47
|
if (!page) unstable_notFound();
|
|
48
|
-
|
|
48
|
+
const txt = await getLLMText(page);
|
|
49
|
+
return new Response(txt ?? "", { headers: { "Content-Type": "text/markdown" } });
|
|
49
50
|
}
|
|
50
51
|
});
|
|
51
52
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ConfigContext } from "../config.js";
|
|
2
|
+
import { Awaitable, ServerPlugin } from "../lib/types.js";
|
|
3
|
+
import { FC } from "react";
|
|
4
|
+
import { OpenAPIServer, openapiPlugin as openapiLoaderPlugin } from "fumadocs-openapi/server";
|
|
5
|
+
import { ClientApiPageProps } from "fumadocs-openapi/ui/create-client";
|
|
6
|
+
|
|
7
|
+
//#region src/plugins/openapi.d.ts
|
|
8
|
+
interface OpenAPIOptions {
|
|
9
|
+
server: OpenAPIServer;
|
|
10
|
+
/** must be a client component */
|
|
11
|
+
ClientAPIPage?: FC<ClientApiPageProps>;
|
|
12
|
+
/** create proxy server */
|
|
13
|
+
createProxy?: boolean | (() => Awaitable<ReturnType<OpenAPIServer["createProxy"]>>);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* this will register the OpenAPI adapter & required layout configs.
|
|
17
|
+
*/
|
|
18
|
+
declare function openapiPlugin<C extends ConfigContext>(options: OpenAPIOptions): ServerPlugin<C>;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { OpenAPIOptions, openapiLoaderPlugin, openapiPlugin };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { PayloadProvider, WithPayload } from "../components/openapi.payload.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { unstable_notFound } from "waku/router/server";
|
|
4
|
+
import { openapiPlugin as openapiLoaderPlugin } from "fumadocs-openapi/server";
|
|
5
|
+
//#region src/plugins/openapi.tsx
|
|
6
|
+
/**
|
|
7
|
+
* this will register the OpenAPI adapter & required layout configs.
|
|
8
|
+
*/
|
|
9
|
+
function openapiPlugin(options) {
|
|
10
|
+
function initRenderers(data) {
|
|
11
|
+
(data.renderers ??= []).push(function(data) {
|
|
12
|
+
if (isOpenAPI(this.page.data)) data.pageProps.full ??= true;
|
|
13
|
+
return data;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
name: "core:openapi",
|
|
18
|
+
init() {
|
|
19
|
+
this.adapters.push(adapter(options));
|
|
20
|
+
initRenderers(this.data["core:docs-layout"] ??= {});
|
|
21
|
+
initRenderers(this.data["core:notebook-layout"] ??= {});
|
|
22
|
+
},
|
|
23
|
+
resolvePage(page) {
|
|
24
|
+
if (isOpenAPI(page.data)) return false;
|
|
25
|
+
},
|
|
26
|
+
async createPages({ createPage, createLayout, createApi }) {
|
|
27
|
+
const { server, createProxy } = options;
|
|
28
|
+
const renderMode = this.mode === "dynamic" ? "dynamic" : "static";
|
|
29
|
+
createLayout({
|
|
30
|
+
path: this.i18nConfig ? "/[lang]/(openapi)" : "/(openapi)",
|
|
31
|
+
render: renderMode,
|
|
32
|
+
async component({ children }) {
|
|
33
|
+
const payload = {};
|
|
34
|
+
for (const [schemaId, schema] of Object.entries(await server.getSchemas())) payload[schemaId] = {
|
|
35
|
+
bundled: schema.bundled,
|
|
36
|
+
proxyUrl: server.options.proxyUrl
|
|
37
|
+
};
|
|
38
|
+
return /* @__PURE__ */ jsx(PayloadProvider, {
|
|
39
|
+
payload: JSON.stringify(payload),
|
|
40
|
+
children
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const staticPaths = [];
|
|
45
|
+
if (renderMode === "static") for (const page of (await this.getLoader()).getPages()) {
|
|
46
|
+
if (!isOpenAPI(page.data)) continue;
|
|
47
|
+
staticPaths.push(page.locale ? [page.locale, ...page.slugs] : page.slugs);
|
|
48
|
+
}
|
|
49
|
+
createPage({
|
|
50
|
+
render: renderMode,
|
|
51
|
+
path: this.i18nConfig ? "/[lang]/(openapi)/[...slugs]" : "/(openapi)/[...slugs]",
|
|
52
|
+
staticPaths,
|
|
53
|
+
component: async ({ slugs, lang }) => {
|
|
54
|
+
const page = (await this.getLoader()).getPage(slugs, lang);
|
|
55
|
+
if (!page || !isOpenAPI(page.data)) unstable_notFound();
|
|
56
|
+
return /* @__PURE__ */ jsx(this.layouts.page, {
|
|
57
|
+
slugs,
|
|
58
|
+
page,
|
|
59
|
+
ctx: this
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
if (createProxy) {
|
|
64
|
+
const proxyUrl = server.options.proxyUrl;
|
|
65
|
+
if (!proxyUrl) throw new Error(`[Fumapress] The "proxyUrl" option in createOpenAPI() is required to create proxy server`);
|
|
66
|
+
if (this.mode === "static") throw new Error(`[Fumapress] static mode is not compatible with proxy server`);
|
|
67
|
+
createApi({
|
|
68
|
+
path: proxyUrl,
|
|
69
|
+
render: "dynamic",
|
|
70
|
+
handlers: { all: (typeof createProxy === "function" ? await createProxy() : server.createProxy()).handle }
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function adapter(options) {
|
|
77
|
+
return {
|
|
78
|
+
async "core:render-body"(page) {
|
|
79
|
+
if (isOpenAPI(page.data)) {
|
|
80
|
+
const ClientAPIPage = options.ClientAPIPage ?? (await import("../components/openapi.js")).default;
|
|
81
|
+
const props = page.data.getAPIPageProps();
|
|
82
|
+
return /* @__PURE__ */ jsx(WithPayload, {
|
|
83
|
+
schemaId: props.document,
|
|
84
|
+
Comp: ClientAPIPage,
|
|
85
|
+
props
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"core:render-toc"(page) {
|
|
90
|
+
if (isOpenAPI(page.data)) return page.data.toc;
|
|
91
|
+
},
|
|
92
|
+
"core:get-structured-data"(page) {
|
|
93
|
+
if (isOpenAPI(page.data)) return page.data.structuredData;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** @internal */
|
|
98
|
+
function isOpenAPI(data) {
|
|
99
|
+
return "getAPIPageProps" in data && typeof data.getAPIPageProps === "function";
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
102
|
+
export { openapiLoaderPlugin, openapiPlugin };
|
|
@@ -13,10 +13,11 @@ function oramaSearchPlugin({ buildIndex = async function buildIndexDefault(page)
|
|
|
13
13
|
throw new Error("[Fumapress] Please specify the `buildIndex` option to oramaSearchPlugin()");
|
|
14
14
|
} } = {}) {
|
|
15
15
|
return {
|
|
16
|
+
name: "core:orama-search",
|
|
16
17
|
init() {
|
|
17
|
-
|
|
18
|
-
props.search ??= {};
|
|
19
|
-
props.search.SearchDialog ??= (await import("../components/orama-search-static.js")).default;
|
|
18
|
+
(this.data["core:provider"] ??= []).push(async (props) => {
|
|
19
|
+
props.search ??= { enabled: true };
|
|
20
|
+
if (this.mode === "static") props.search.SearchDialog ??= (await import("../components/orama-search-static.js")).default;
|
|
20
21
|
return props;
|
|
21
22
|
});
|
|
22
23
|
},
|
package/dist/plugins/takumi.js
CHANGED
package/dist/router.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AppContext } from "./lib/shared.js";
|
|
2
|
+
import { ConfigBuilder, ConfigContext } from "./config.js";
|
|
3
|
+
import { Awaitable, RouteFns } from "./lib/types.js";
|
|
2
4
|
import * as waku from "waku";
|
|
3
5
|
|
|
4
6
|
//#region src/router.d.ts
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
createPages: () => ReturnType<typeof waku.createPages>;
|
|
7
|
+
type Options = Parameters<typeof waku.createPages>[1];
|
|
8
|
+
declare function createRouter<C extends ConfigContext>(userConfig: ConfigBuilder<C>): {
|
|
9
|
+
createPages: (fn?: (this: AppContext<C>, fns: RouteFns) => Awaitable<void>, options?: Options) => ReturnType<typeof waku.createPages>;
|
|
8
10
|
};
|
|
9
11
|
//#endregion
|
|
10
12
|
export { createRouter };
|
package/dist/router.js
CHANGED
|
@@ -2,22 +2,18 @@ import { parseConfig } from "./lib/shared.js";
|
|
|
2
2
|
import * as waku from "waku";
|
|
3
3
|
import { Fragment } from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
import { unstable_redirect } from "waku/router/server";
|
|
5
|
+
import { unstable_notFound, unstable_redirect } from "waku/router/server";
|
|
6
6
|
//#region src/router.tsx
|
|
7
7
|
function createRouter(userConfig) {
|
|
8
8
|
async function init() {
|
|
9
|
-
const context = parseConfig(userConfig);
|
|
10
|
-
for (const plugin of context.plugins) plugin.init?.call(context);
|
|
11
|
-
return
|
|
12
|
-
context,
|
|
13
|
-
root: context.layouts.root ?? (await import("./layouts/root.js")).createRootLayout(),
|
|
14
|
-
page: context.layouts.page ?? (await import("./layouts/docs.js")).createDocsLayoutPage(),
|
|
15
|
-
notFound: context.layouts.notFound ?? (await import("fumadocs-ui/layouts/home/not-found")).DefaultNotFound
|
|
16
|
-
};
|
|
9
|
+
const context = await parseConfig(userConfig);
|
|
10
|
+
for (const plugin of context.plugins) await plugin.init?.call(context);
|
|
11
|
+
return context;
|
|
17
12
|
}
|
|
18
13
|
const createPages = (base, createPagesOptions) => {
|
|
19
14
|
return waku.createPages(async (_fns) => {
|
|
20
|
-
const
|
|
15
|
+
const context = await init();
|
|
16
|
+
const layouts = context.layouts;
|
|
21
17
|
const fns = {
|
|
22
18
|
..._fns,
|
|
23
19
|
createApiIsomorphic(config) {
|
|
@@ -35,17 +31,24 @@ function createRouter(userConfig) {
|
|
|
35
31
|
});
|
|
36
32
|
}
|
|
37
33
|
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
resolved
|
|
34
|
+
async function resolvePage(slugs, lang) {
|
|
35
|
+
let page = (await context.getLoader()).getPage(slugs, lang);
|
|
36
|
+
if (!page) unstable_notFound();
|
|
37
|
+
for (const plugin of context.plugins) {
|
|
38
|
+
const resolved = await plugin.resolvePage?.call(context, page);
|
|
39
|
+
if (typeof resolved === "object") page = resolved;
|
|
40
|
+
else if (resolved === false) unstable_notFound();
|
|
44
41
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
return page;
|
|
43
|
+
}
|
|
44
|
+
await base?.call(context, fns);
|
|
45
|
+
for (const plugin of context.plugins) await plugin.createPages?.call(context, fns);
|
|
46
|
+
const staticPaths = [];
|
|
48
47
|
const defaultRenderMode = context.mode === "dynamic" ? "dynamic" : "static";
|
|
48
|
+
if (defaultRenderMode === "static") outer: for (const page of (await context.getLoader()).getPages()) {
|
|
49
|
+
for (const plugin of context.plugins) if (await plugin.resolvePage?.call(context, page) === false) continue outer;
|
|
50
|
+
staticPaths.push(page.locale ? [page.locale, ...page.slugs] : page.slugs);
|
|
51
|
+
}
|
|
49
52
|
if (context.i18nConfig) {
|
|
50
53
|
fns.createRoot({
|
|
51
54
|
render: defaultRenderMode,
|
|
@@ -65,11 +68,12 @@ function createRouter(userConfig) {
|
|
|
65
68
|
fns.createPage({
|
|
66
69
|
render: defaultRenderMode,
|
|
67
70
|
path: "/[lang]/[...slugs]",
|
|
68
|
-
staticPaths
|
|
69
|
-
component({ slugs, lang }) {
|
|
71
|
+
staticPaths,
|
|
72
|
+
async component({ slugs, lang }) {
|
|
70
73
|
return /* @__PURE__ */ jsx(layouts.page, {
|
|
71
74
|
lang,
|
|
72
75
|
slugs,
|
|
76
|
+
page: await resolvePage(slugs, lang),
|
|
73
77
|
ctx: context
|
|
74
78
|
});
|
|
75
79
|
}
|
|
@@ -105,10 +109,11 @@ function createRouter(userConfig) {
|
|
|
105
109
|
fns.createPage({
|
|
106
110
|
render: defaultRenderMode,
|
|
107
111
|
path: "/[...slugs]",
|
|
108
|
-
staticPaths
|
|
109
|
-
component({ slugs }) {
|
|
112
|
+
staticPaths,
|
|
113
|
+
async component({ slugs }) {
|
|
110
114
|
return /* @__PURE__ */ jsx(layouts.page, {
|
|
111
115
|
slugs,
|
|
116
|
+
page: await resolvePage(slugs),
|
|
112
117
|
ctx: context
|
|
113
118
|
});
|
|
114
119
|
}
|
|
@@ -125,12 +130,7 @@ function createRouter(userConfig) {
|
|
|
125
130
|
return null;
|
|
126
131
|
}, createPagesOptions);
|
|
127
132
|
};
|
|
128
|
-
return {
|
|
129
|
-
extend: createPages,
|
|
130
|
-
createPages() {
|
|
131
|
-
return createPages(() => null);
|
|
132
|
-
}
|
|
133
|
-
};
|
|
133
|
+
return { createPages };
|
|
134
134
|
}
|
|
135
135
|
//#endregion
|
|
136
136
|
export { createRouter };
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
2
|
|
|
3
3
|
//#region src/vite.d.ts
|
|
4
|
-
|
|
4
|
+
interface PluginOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Auto-generate Vite config to handle CJS bundling.
|
|
7
|
+
*
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
generateViteConfig?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare function press(options?: PluginOptions): Plugin;
|
|
5
13
|
//#endregion
|
|
6
|
-
export { press as default };
|
|
14
|
+
export { PluginOptions, press as default };
|
package/dist/vite.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { crawlFrameworkPkgs } from "./lib/vitefu.js";
|
|
2
2
|
//#region src/vite.ts
|
|
3
|
-
function press() {
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
function pressCore() {
|
|
3
|
+
function press(options = {}) {
|
|
4
|
+
const { generateViteConfig = true } = options;
|
|
7
5
|
return {
|
|
8
6
|
name: "fumapress:core",
|
|
9
7
|
async config(_, { command }) {
|
|
8
|
+
if (!generateViteConfig) return;
|
|
10
9
|
const out = await crawlFrameworkPkgs({
|
|
11
10
|
root: process.cwd(),
|
|
12
11
|
isBuild: command === "build",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumapress",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "An opinionated docs framework powered by Fumadocs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Docs",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"./plugins/blog": "./dist/plugins/blog.js",
|
|
33
33
|
"./plugins/flexsearch": "./dist/plugins/flexsearch.js",
|
|
34
34
|
"./plugins/llms.txt": "./dist/plugins/llms.txt.js",
|
|
35
|
+
"./plugins/openapi": "./dist/plugins/openapi.js",
|
|
35
36
|
"./plugins/orama-search": "./dist/plugins/orama-search.js",
|
|
36
37
|
"./plugins/takumi": "./dist/plugins/takumi.js",
|
|
37
38
|
"./router": "./dist/router.js",
|
|
@@ -45,11 +46,11 @@
|
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
48
|
"@orama/orama": "^3.1.18",
|
|
48
|
-
"@takumi-rs/image-response": "^1.
|
|
49
|
+
"@takumi-rs/image-response": "^1.3.0",
|
|
49
50
|
"class-variance-authority": "^0.7.1",
|
|
50
51
|
"flexsearch": "^0.8.212",
|
|
51
|
-
"fumadocs-core": "^16.8.
|
|
52
|
-
"fumadocs-ui": "^16.8.
|
|
52
|
+
"fumadocs-core": "^16.8.12",
|
|
53
|
+
"fumadocs-ui": "^16.8.12",
|
|
53
54
|
"lucide-react": "^1.16.0",
|
|
54
55
|
"tailwind-merge": "^3.6.0",
|
|
55
56
|
"vite": "^8.0.13",
|
|
@@ -59,9 +60,10 @@
|
|
|
59
60
|
"@fastify/deepmerge": "^3.2.1",
|
|
60
61
|
"@tailwindcss/oxide": "^4.3.0",
|
|
61
62
|
"@types/mdx": "^2.0.13",
|
|
62
|
-
"@types/node": "^25.
|
|
63
|
-
"@types/react": "^19.2.
|
|
64
|
-
"fumadocs-mdx": "^15.0.
|
|
63
|
+
"@types/node": "^25.9.1",
|
|
64
|
+
"@types/react": "^19.2.15",
|
|
65
|
+
"fumadocs-mdx": "^15.0.7",
|
|
66
|
+
"fumadocs-openapi": "^10.9.0",
|
|
65
67
|
"react": "^19.2.6",
|
|
66
68
|
"react-dom": "^19.2.6",
|
|
67
69
|
"tsdown": "0.22.0",
|
|
@@ -72,11 +74,15 @@
|
|
|
72
74
|
"@types/mdx": "*",
|
|
73
75
|
"@types/react": "*",
|
|
74
76
|
"fumadocs-mdx": "^15.0.0",
|
|
77
|
+
"fumadocs-openapi": "^10.8.0",
|
|
75
78
|
"react": "^19.2.0",
|
|
76
79
|
"react-dom": "^19.2.0",
|
|
77
80
|
"waku": "1.0.0-beta.0"
|
|
78
81
|
},
|
|
79
82
|
"peerDependenciesMeta": {
|
|
83
|
+
"fumadocs-openapi": {
|
|
84
|
+
"optional": true
|
|
85
|
+
},
|
|
80
86
|
"@types/mdx": {
|
|
81
87
|
"optional": true
|
|
82
88
|
},
|