fumapress 0.2.2 → 0.2.4

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.
@@ -0,0 +1,103 @@
1
+ @source inline("@orama/orama");
2
+ @source inline("absolutePath");
3
+ @source inline("adapter");
4
+ @source inline("as");
5
+ @source inline("async");
6
+ @source inline("await");
7
+ @source inline("body");
8
+ @source inline("border-b");
9
+ @source inline("className");
10
+ @source inline("client");
11
+ @source inline("const");
12
+ @source inline("core:docs-layout");
13
+ @source inline("core:home-layout");
14
+ @source inline("core:provider");
15
+ @source inline("core:render-body");
16
+ @source inline("core:render-toc");
17
+ @source inline("create");
18
+ @source inline("createDocsLayout");
19
+ @source inline("createHomeLayout");
20
+ @source inline("createRootLayout");
21
+ @source inline("data");
22
+ @source inline("data-version");
23
+ @source inline("default");
24
+ @source inline("else");
25
+ @source inline("empty");
26
+ @source inline("en");
27
+ @source inline("english");
28
+ @source inline("export");
29
+ @source inline("extends");
30
+ @source inline("flex");
31
+ @source inline("flex-col");
32
+ @source inline("flex-row");
33
+ @source inline("flexsearchStaticClient");
34
+ @source inline("for");
35
+ @source inline("from");
36
+ @source inline("fumadocs-core/source");
37
+ @source inline("fumadocs-core/toc");
38
+ @source inline("function");
39
+ @source inline("gap-2");
40
+ @source inline("githubUrl");
41
+ @source inline("hook");
42
+ @source inline("hooks");
43
+ @source inline("i18n");
44
+ @source inline("i18nConfig");
45
+ @source inline("if");
46
+ @source inline("import");
47
+ @source inline("in");
48
+ @source inline("interface");
49
+ @source inline("isLoading");
50
+ @source inline("items");
51
+ @source inline("items-center");
52
+ @source inline("lang");
53
+ @source inline("language");
54
+ @source inline("languages");
55
+ @source inline("layoutData");
56
+ @source inline("layoutProps");
57
+ @source inline("let");
58
+ @source inline("loaderConfig");
59
+ @source inline("locale");
60
+ @source inline("locales");
61
+ @source inline("markdownUrl");
62
+ @source inline("mb-0");
63
+ @source inline("min-h-screen");
64
+ @source inline("name");
65
+ @source inline("new");
66
+ @source inline("of");
67
+ @source inline("onSearchChange");
68
+ @source inline("option");
69
+ @source inline("page");
70
+ @source inline("pageProps");
71
+ @source inline("pb-6");
72
+ @source inline("providerProps");
73
+ @source inline("pt-2");
74
+ @source inline("query");
75
+ @source inline("r");
76
+ @source inline("react");
77
+ @source inline("render");
78
+ @source inline("renderCtx");
79
+ @source inline("renderPageMeta");
80
+ @source inline("renderRootMeta");
81
+ @source inline("result");
82
+ @source inline("return");
83
+ @source inline("root");
84
+ @source inline("satisfies");
85
+ @source inline("schema");
86
+ @source inline("search");
87
+ @source inline("source");
88
+ @source inline("specify");
89
+ @source inline("static");
90
+ @source inline("string");
91
+ @source inline("styles");
92
+ @source inline("the");
93
+ @source inline("this");
94
+ @source inline("throw");
95
+ @source inline("toc");
96
+ @source inline("translations");
97
+ @source inline("tree");
98
+ @source inline("type");
99
+ @source inline("undefined");
100
+ @source inline("unstable_notFound");
101
+ @source inline("use");
102
+ @source inline("useDocsSearch");
103
+ @source inline("useI18n");
@@ -0,0 +1,12 @@
1
+ import { AppContext } from "../lib/shared.js";
2
+ import { ConfigContext } from "../config.js";
3
+ import { Adapter, Awaitable } from "../lib/types.js";
4
+ import { MDXComponents } from "mdx/types";
5
+
6
+ //#region src/adapters/mdx.d.ts
7
+ interface MdxAdapterOptions<C extends ConfigContext = ConfigContext> {
8
+ getMdxComponents?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => Awaitable<MDXComponents>;
9
+ }
10
+ declare function fumadocsMdx<C extends ConfigContext = ConfigContext>(options?: MdxAdapterOptions<C>): Adapter<C>;
11
+ //#endregion
12
+ export { MdxAdapterOptions, fumadocsMdx };
@@ -0,0 +1,37 @@
1
+ import { createElement } from "react";
2
+ import defaultMdxComponents, { createRelativeLink } from "fumadocs-ui/mdx";
3
+ //#region src/adapters/mdx.ts
4
+ function fumadocsMdx(options) {
5
+ const getMdxComponents = options?.getMdxComponents;
6
+ return {
7
+ async "core:get-text"(page) {
8
+ if (isAsyncEntry(page.data) || isSyncEntry(page.data)) return page.data.getText("processed");
9
+ },
10
+ async "core:get-structured-data"(page) {
11
+ if (isSyncEntry(page.data)) return page.data.structuredData;
12
+ if (isAsyncEntry(page.data)) return (await page.data.load()).structuredData;
13
+ },
14
+ async "core:render-body"(page) {
15
+ let body;
16
+ if (isSyncEntry(page.data)) body = page.data.body;
17
+ else if (isAsyncEntry(page.data)) body = (await page.data.load()).body;
18
+ else return;
19
+ return createElement(body, getMdxComponents ? await getMdxComponents.call(this, page) : { components: {
20
+ ...defaultMdxComponents,
21
+ a: createRelativeLink(await this.getLoader(), page)
22
+ } });
23
+ },
24
+ async "core:render-toc"(page) {
25
+ if (isSyncEntry(page.data)) return page.data.toc;
26
+ if (isAsyncEntry(page.data)) return (await page.data.load()).toc;
27
+ }
28
+ };
29
+ }
30
+ function isSyncEntry(v) {
31
+ return "info" in v && typeof v.info === "object" && "_exports" in v && typeof v._exports === "object";
32
+ }
33
+ function isAsyncEntry(v) {
34
+ return "info" in v && typeof v.info === "object" && "load" in v && typeof v.load === "function";
35
+ }
36
+ //#endregion
37
+ export { fumadocsMdx };
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { SearchDialog, SearchDialogClose, SearchDialogContent, SearchDialogHeader, SearchDialogIcon, SearchDialogInput, SearchDialogList, SearchDialogOverlay } from "fumadocs-ui/components/dialog/search";
4
+ import { useDocsSearch } from "fumadocs-core/search/client";
5
+ import { flexsearchStaticClient } from "fumadocs-core/search/client/flexsearch-static";
6
+ import { useI18n } from "fumadocs-ui/contexts/i18n";
7
+ //#region src/components/flexsearch-static.tsx
8
+ function DefaultSearchDialog(props) {
9
+ const { locale } = useI18n();
10
+ const { search, setSearch, query } = useDocsSearch({ client: flexsearchStaticClient({ locale }) });
11
+ return /* @__PURE__ */ jsxs(SearchDialog, {
12
+ search,
13
+ onSearchChange: setSearch,
14
+ isLoading: query.isLoading,
15
+ ...props,
16
+ children: [/* @__PURE__ */ jsx(SearchDialogOverlay, {}), /* @__PURE__ */ jsxs(SearchDialogContent, { children: [/* @__PURE__ */ jsxs(SearchDialogHeader, { children: [
17
+ /* @__PURE__ */ jsx(SearchDialogIcon, {}),
18
+ /* @__PURE__ */ jsx(SearchDialogInput, {}),
19
+ /* @__PURE__ */ jsx(SearchDialogClose, {})
20
+ ] }), /* @__PURE__ */ jsx(SearchDialogList, { items: query.data !== "empty" ? query.data : null })] })]
21
+ });
22
+ }
23
+ //#endregion
24
+ export { DefaultSearchDialog as default };
@@ -0,0 +1,34 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { SearchDialog, SearchDialogClose, SearchDialogContent, SearchDialogHeader, SearchDialogIcon, SearchDialogInput, SearchDialogList, SearchDialogOverlay } from "fumadocs-ui/components/dialog/search";
4
+ import { useDocsSearch } from "fumadocs-core/search/client";
5
+ import { useI18n } from "fumadocs-ui/contexts/i18n";
6
+ import { create } from "@orama/orama";
7
+ //#region src/components/orama-search-static.tsx
8
+ function initOrama() {
9
+ return create({
10
+ schema: { _: "string" },
11
+ language: "english"
12
+ });
13
+ }
14
+ function DefaultSearchDialog(props) {
15
+ const { locale } = useI18n();
16
+ const { search, setSearch, query } = useDocsSearch({
17
+ type: "static",
18
+ initOrama,
19
+ locale
20
+ });
21
+ return /* @__PURE__ */ jsxs(SearchDialog, {
22
+ search,
23
+ onSearchChange: setSearch,
24
+ isLoading: query.isLoading,
25
+ ...props,
26
+ children: [/* @__PURE__ */ jsx(SearchDialogOverlay, {}), /* @__PURE__ */ jsxs(SearchDialogContent, { children: [/* @__PURE__ */ jsxs(SearchDialogHeader, { children: [
27
+ /* @__PURE__ */ jsx(SearchDialogIcon, {}),
28
+ /* @__PURE__ */ jsx(SearchDialogInput, {}),
29
+ /* @__PURE__ */ jsx(SearchDialogClose, {})
30
+ ] }), /* @__PURE__ */ jsx(SearchDialogList, { items: query.data !== "empty" ? query.data : null })] })]
31
+ });
32
+ }
33
+ //#endregion
34
+ export { DefaultSearchDialog as default };
@@ -0,0 +1,84 @@
1
+ import { AppContext } from "./lib/shared.js";
2
+ import { Adapter, Awaitable, ServerPlugin } from "./lib/types.js";
3
+ import { ComponentType, ReactNode } from "react";
4
+ import { TranslationsOption } from "fumadocs-ui/contexts/i18n";
5
+ import { LoaderConfig, LoaderOutput } from "fumadocs-core/source";
6
+ import { I18nConfig } from "fumadocs-core/i18n";
7
+
8
+ //#region src/config.d.ts
9
+ interface ConfigContext {
10
+ loaderConfig: LoaderConfig;
11
+ lang: string;
12
+ }
13
+ type BuildMode = "static" | "dynamic" | "default";
14
+ interface Config<C extends ConfigContext = ConfigContext> {
15
+ /**
16
+ * - `static`: always prefer static, including search etc.
17
+ * - `dynamic`: always prefer dynamic.
18
+ * - `default`: only certain parts like search routes are dynamic.
19
+ */
20
+ mode?: BuildMode;
21
+ /** the default content loader */
22
+ loader: LoaderOutput<C["loaderConfig"]> | (() => Awaitable<LoaderOutput<C["loaderConfig"]>>);
23
+ site?: SiteConfig;
24
+ layouts?: Partial<Layouts>;
25
+ plugins?: ServerPlugin[];
26
+ /** adapter for content sources, use `fumadocs-mdx` if not specified */
27
+ adapters?: Adapter[];
28
+ i18n?: I18nConfig$1<C["lang"]>;
29
+ meta?: {
30
+ /** render meta tags for any pages */root?: (this: AppContext<C>) => ReactNode; /** render meta tags for page */
31
+ page?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => ReactNode;
32
+ };
33
+ }
34
+ interface Layouts<C extends ConfigContext = ConfigContext> {
35
+ root: ComponentType<AppContext<C> & {
36
+ lang?: string;
37
+ children: ReactNode;
38
+ }>;
39
+ page: ComponentType<AppContext<C> & {
40
+ lang?: string;
41
+ slugs: string[];
42
+ }>;
43
+ notFound: ComponentType<AppContext<C> & {
44
+ lang?: string;
45
+ }>;
46
+ }
47
+ interface I18nConfig$1<Lang extends string = string> extends Pick<I18nConfig<NoInfer<Lang>>, "fallbackLanguage" | "parser"> {
48
+ /** locale code -> language info */
49
+ languages: { [K in Lang]: {
50
+ displayName: string;
51
+ translations?: TranslationsOption;
52
+ } };
53
+ defaultLanguage: NoInfer<Lang>;
54
+ }
55
+ interface SiteConfig {
56
+ /** full URL of app, used for metadata generation*/
57
+ baseUrl?: string;
58
+ name?: string;
59
+ git?: {
60
+ user: string;
61
+ repo: string;
62
+ branch: string; /** the root directory of git repo */
63
+ rootDir?: string;
64
+ };
65
+ }
66
+ interface I18nConfigBuilder<Lang extends string> extends I18nConfig$1<Lang> {
67
+ /** convert Fumapress i18n config to core i18n config */
68
+ toCore: () => I18nConfig<Lang>;
69
+ }
70
+ interface ConfigBuilder<C extends ConfigContext> extends Config<C> {
71
+ usePlugins: (...plugins: ServerPlugin<C>[]) => ConfigBuilder<C>;
72
+ useLayouts: (layouts: Partial<Layouts<C>>) => ConfigBuilder<C>;
73
+ useAdapters: (...adapters: Adapter[]) => ConfigBuilder<C>;
74
+ }
75
+ declare function defineConfig<C extends LoaderConfig, L extends string = string>(config: Config<{
76
+ loaderConfig: C;
77
+ lang: L;
78
+ }>): ConfigBuilder<{
79
+ loaderConfig: C;
80
+ lang: L;
81
+ }>;
82
+ declare function defineI18nConfig<Lang extends string>(config: I18nConfig$1<Lang>): I18nConfigBuilder<Lang>;
83
+ //#endregion
84
+ export { BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig$1 as I18nConfig, I18nConfigBuilder, Layouts, SiteConfig, defineConfig, defineI18nConfig };
package/dist/config.js ADDED
@@ -0,0 +1,36 @@
1
+ //#region src/config.ts
2
+ function defineConfig(config) {
3
+ return {
4
+ ...config,
5
+ useAdapters(...adapters) {
6
+ this.adapters ??= [];
7
+ this.adapters.push(...adapters);
8
+ return this;
9
+ },
10
+ useLayouts(layouts) {
11
+ this.layouts ??= {};
12
+ Object.assign(this.layouts, layouts);
13
+ return this;
14
+ },
15
+ usePlugins(...plugins) {
16
+ this.plugins ??= [];
17
+ this.plugins.push(...plugins);
18
+ return this;
19
+ }
20
+ };
21
+ }
22
+ function defineI18nConfig(config) {
23
+ return {
24
+ ...config,
25
+ toCore() {
26
+ return {
27
+ defaultLanguage: this.defaultLanguage,
28
+ fallbackLanguage: this.fallbackLanguage,
29
+ parser: this.parser,
30
+ languages: Object.keys(this.languages)
31
+ };
32
+ }
33
+ };
34
+ }
35
+ //#endregion
36
+ export { defineConfig, defineI18nConfig };
@@ -0,0 +1,4 @@
1
+ import { AppContext, AppContextData } from "./lib/shared.js";
2
+ import { BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, SiteConfig, defineConfig, defineI18nConfig } from "./config.js";
3
+ import { Adapter, ServerPlugin } from "./lib/types.js";
4
+ export { type Adapter, type AppContext, type AppContextData, BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, type ServerPlugin, SiteConfig, defineConfig, defineI18nConfig };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { defineConfig, defineI18nConfig } from "./config.js";
2
+ export { defineConfig, defineI18nConfig };
@@ -0,0 +1,35 @@
1
+ import { AppContext } from "../lib/shared.js";
2
+ import { ConfigContext, Layouts } from "../config.js";
3
+ import { Awaitable } from "../lib/types.js";
4
+ import { ReactNode } from "react";
5
+ import { DocsLayoutProps } from "fumadocs-ui/layouts/docs";
6
+ import { DocsPageProps } from "fumadocs-ui/layouts/docs/page";
7
+ import { Page } from "fumadocs-core/source";
8
+
9
+ //#region src/layouts/docs.d.ts
10
+ interface DocsLayoutOptions<C extends ConfigContext = ConfigContext> {
11
+ render?: (this: AppContext<C> & {
12
+ lang?: string;
13
+ }, page: C["loaderConfig"]["page"]) => Awaitable<{
14
+ markdownUrl?: string;
15
+ body?: ReactNode;
16
+ layoutProps?: Partial<DocsLayoutProps>;
17
+ pageProps?: DocsPageProps;
18
+ }>;
19
+ }
20
+ interface DocsLayoutRenderData {
21
+ markdownUrl?: string;
22
+ body: ReactNode;
23
+ layoutProps: DocsLayoutProps;
24
+ pageProps: DocsPageProps;
25
+ }
26
+ interface DocsLayoutContextData {
27
+ renderers?: ((this: {
28
+ page: Page;
29
+ }, data: DocsLayoutRenderData) => Awaitable<DocsLayoutRenderData>)[];
30
+ }
31
+ declare function createDocsLayout<C extends ConfigContext = ConfigContext>({
32
+ render
33
+ }?: DocsLayoutOptions<NoInfer<C>>): Layouts<C>["page"];
34
+ //#endregion
35
+ export { DocsLayoutContextData, DocsLayoutOptions, DocsLayoutRenderData, createDocsLayout };
@@ -0,0 +1,85 @@
1
+ import { baseOptions, getGitHubFileUrl, renderPageMeta } from "../lib/shared.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { unstable_notFound } from "waku/router/server";
4
+ import { DocsLayout } from "fumadocs-ui/layouts/docs";
5
+ import { DocsBody, DocsDescription, DocsPage, DocsTitle, MarkdownCopyButton, ViewOptionsPopover } from "fumadocs-ui/layouts/docs/page";
6
+ //#region src/layouts/docs.tsx
7
+ function createDocsLayout({ render } = {}) {
8
+ async function defaultRender(page) {
9
+ let body;
10
+ let toc;
11
+ for (const adapter of this.adapters) {
12
+ body = await adapter["core:render-body"]?.call(this, page);
13
+ if (body !== void 0) break;
14
+ }
15
+ for (const adapter of this.adapters) {
16
+ toc = await adapter["core:render-toc"]?.call(this, page);
17
+ if (toc !== void 0) break;
18
+ }
19
+ if (body === void 0) throw new Error("[Fumapress] Please specify the `render` option in createDocsLayout()");
20
+ return {
21
+ body,
22
+ pageProps: { toc }
23
+ };
24
+ }
25
+ return async function Layout(props) {
26
+ const { slugs, lang, getLoader, data: { "core:docs-layout": layoutData } } = props;
27
+ const source = await getLoader();
28
+ const page = source.getPage(slugs, lang);
29
+ if (!page) unstable_notFound();
30
+ const _raw = await (render ?? defaultRender).call(props, page);
31
+ let result;
32
+ if (_raw.body === void 0 || _raw.pageProps === void 0) {
33
+ const _default = await defaultRender.call(props, page);
34
+ result = {
35
+ markdownUrl: _raw.markdownUrl,
36
+ pageProps: _raw.pageProps ?? _default.pageProps,
37
+ body: _raw.body ?? _default.body,
38
+ layoutProps: {
39
+ tree: source.getPageTree(lang),
40
+ ..._raw.layoutProps ?? baseOptions(props)
41
+ }
42
+ };
43
+ } else result = {
44
+ body: _raw.body,
45
+ pageProps: _raw.pageProps,
46
+ markdownUrl: _raw.markdownUrl,
47
+ layoutProps: {
48
+ tree: source.getPageTree(lang),
49
+ ..._raw.layoutProps ?? baseOptions(props)
50
+ }
51
+ };
52
+ if (layoutData?.renderers) {
53
+ const renderCtx = { page };
54
+ for (const r of layoutData.renderers) result = await r.call(renderCtx, result);
55
+ }
56
+ return /* @__PURE__ */ jsxs(DocsLayout, {
57
+ ...result.layoutProps,
58
+ children: [
59
+ renderPageMeta(page, props),
60
+ result.layoutProps.children,
61
+ /* @__PURE__ */ jsxs(DocsPage, {
62
+ ...result.pageProps,
63
+ children: [
64
+ result.pageProps.children,
65
+ /* @__PURE__ */ jsx(DocsTitle, { children: page.data.title }),
66
+ /* @__PURE__ */ jsx(DocsDescription, {
67
+ className: "mb-0",
68
+ children: page.data.description
69
+ }),
70
+ /* @__PURE__ */ jsxs("div", {
71
+ className: "flex flex-row gap-2 items-center border-b pt-2 pb-6",
72
+ children: [result.markdownUrl && /* @__PURE__ */ jsx(MarkdownCopyButton, { markdownUrl: result.markdownUrl }), /* @__PURE__ */ jsx(ViewOptionsPopover, {
73
+ markdownUrl: result.markdownUrl,
74
+ githubUrl: page.absolutePath ? getGitHubFileUrl(props, page.absolutePath) : void 0
75
+ })]
76
+ }),
77
+ /* @__PURE__ */ jsx(DocsBody, { children: result.body })
78
+ ]
79
+ })
80
+ ]
81
+ });
82
+ };
83
+ }
84
+ //#endregion
85
+ export { createDocsLayout };
@@ -0,0 +1,28 @@
1
+ import { AppContext } from "../lib/shared.js";
2
+ import { ConfigContext, Layouts } from "../config.js";
3
+ import { Awaitable } from "../lib/types.js";
4
+ import { ReactNode } from "react";
5
+ import { HomeLayoutProps } from "fumadocs-ui/layouts/home";
6
+ import { Page } from "fumadocs-core/source";
7
+
8
+ //#region src/layouts/home.d.ts
9
+ interface HomeLayoutOptions<C extends ConfigContext = ConfigContext> {
10
+ render?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => Awaitable<{
11
+ body?: ReactNode;
12
+ layoutProps?: Partial<HomeLayoutProps>;
13
+ }>;
14
+ }
15
+ interface HomeLayoutRenderData {
16
+ body: ReactNode;
17
+ layoutProps: HomeLayoutProps;
18
+ }
19
+ interface HomeLayoutContextData {
20
+ renderers?: ((this: {
21
+ page: Page;
22
+ }, data: HomeLayoutRenderData) => Awaitable<HomeLayoutRenderData>)[];
23
+ }
24
+ declare function createHomeLayout<C extends ConfigContext = ConfigContext>({
25
+ render
26
+ }: HomeLayoutOptions<NoInfer<C>>): Layouts<C>["page"];
27
+ //#endregion
28
+ export { HomeLayoutContextData, HomeLayoutOptions, HomeLayoutRenderData, createHomeLayout };
@@ -0,0 +1,34 @@
1
+ import { baseOptions, renderPageMeta } from "../lib/shared.js";
2
+ import { jsxs } from "react/jsx-runtime";
3
+ import { unstable_notFound } from "waku/router/server";
4
+ import { HomeLayout } from "fumadocs-ui/layouts/home";
5
+ //#region src/layouts/home.tsx
6
+ function createHomeLayout({ render }) {
7
+ async function renderDefault(page) {
8
+ for (const adapter of this.adapters) {
9
+ const body = await adapter["core:render-body"]?.call(this, page);
10
+ if (body !== void 0) return { body };
11
+ }
12
+ throw new Error("[Fumapress] Please specify the `render` option in createHomeLayout()");
13
+ }
14
+ return async function Layout(props) {
15
+ const { slugs, lang, getLoader, data: { "core:home-layout": layoutData } } = props;
16
+ const page = (await getLoader()).getPage(slugs, lang);
17
+ if (!page) unstable_notFound();
18
+ const _raw = await (render ?? renderDefault).call(props, page);
19
+ let result = {
20
+ body: _raw.body === void 0 ? (await renderDefault.call(props, page)).body : _raw.body,
21
+ layoutProps: _raw.layoutProps ?? baseOptions(props)
22
+ };
23
+ if (layoutData?.renderers) {
24
+ const renderCtx = { page };
25
+ for (const r of layoutData.renderers) result = await r.call(renderCtx, result);
26
+ }
27
+ return /* @__PURE__ */ jsxs(HomeLayout, {
28
+ ...result.layoutProps,
29
+ children: [renderPageMeta(page, props), result.body]
30
+ });
31
+ };
32
+ }
33
+ //#endregion
34
+ export { createHomeLayout };
@@ -0,0 +1,10 @@
1
+ import { ConfigContext, Layouts } from "../config.js";
2
+ import { RootProviderProps } from "fumadocs-ui/provider/waku";
3
+
4
+ //#region src/layouts/root.d.ts
5
+ interface RootLayoutOptions {
6
+ providerProps?: RootProviderProps;
7
+ }
8
+ declare function createRootLayout<C extends ConfigContext = ConfigContext>(options?: RootLayoutOptions): Layouts<C>["root"];
9
+ //#endregion
10
+ export { RootLayoutOptions, createRootLayout };
@@ -0,0 +1,38 @@
1
+ import { renderRootMeta } from "../lib/shared.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import styles from "virtual:root.css?inline";
4
+ import { RootProvider } from "fumadocs-ui/provider/waku";
5
+ //#region src/layouts/root.tsx
6
+ function createRootLayout(options) {
7
+ return async function(props) {
8
+ const { children, lang, i18nConfig, data } = props;
9
+ const hooks = data["core:provider"];
10
+ let providerProps = { ...options?.providerProps };
11
+ if (i18nConfig) {
12
+ const { languages } = i18nConfig;
13
+ providerProps.i18n ??= {
14
+ locale: lang,
15
+ locales: Object.entries(languages).map(([k, v]) => ({
16
+ name: v.displayName,
17
+ locale: k
18
+ })),
19
+ translations: lang ? languages[lang]?.translations : void 0
20
+ };
21
+ }
22
+ if (hooks) for (const hook of hooks) providerProps = await hook(providerProps);
23
+ return /* @__PURE__ */ jsxs("html", {
24
+ lang: lang ?? "en",
25
+ suppressHydrationWarning: true,
26
+ children: [/* @__PURE__ */ jsxs("head", { children: [/* @__PURE__ */ jsx("style", { children: styles }), renderRootMeta(props)] }), /* @__PURE__ */ jsx("body", {
27
+ "data-version": "1.0",
28
+ className: "flex flex-col min-h-screen",
29
+ children: /* @__PURE__ */ jsx(RootProvider, {
30
+ ...providerProps,
31
+ children
32
+ })
33
+ })]
34
+ });
35
+ };
36
+ }
37
+ //#endregion
38
+ export { createRootLayout };
package/dist/lib/fs.js ADDED
@@ -0,0 +1,18 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ //#region src/lib/fs.ts
4
+ /**
5
+ * Returns the absolute path to the root directory of the current git repository.
6
+ */
7
+ function getGitRootDir(startDir = process.cwd()) {
8
+ let dir = startDir;
9
+ while (true) {
10
+ if (existsSync(join(dir, ".git"))) return dir;
11
+ const parent = dirname(dir);
12
+ if (parent === dir) break;
13
+ dir = parent;
14
+ }
15
+ return null;
16
+ }
17
+ //#endregion
18
+ export { getGitRootDir };
@@ -0,0 +1,41 @@
1
+ import { DocsLayoutContextData } from "../layouts/docs.js";
2
+ import { HomeLayoutContextData } from "../layouts/home.js";
3
+ import { BuildMode, Config, ConfigContext, I18nConfig } from "../config.js";
4
+ import { Adapter, Awaitable, ServerPlugin } from "./types.js";
5
+ import { ReactNode } from "react";
6
+ import { RootProviderProps } from "fumadocs-ui/provider/waku";
7
+ import { LoaderOutput, Page } from "fumadocs-core/source";
8
+
9
+ //#region src/lib/shared.d.ts
10
+ interface AppContext<C extends ConfigContext = ConfigContext> {
11
+ mode: BuildMode;
12
+ getLoader: () => Awaitable<LoaderOutput<C["loaderConfig"]>>;
13
+ plugins: ServerPlugin<C>[];
14
+ adapters: Adapter<C>[];
15
+ /** always `undefined`, easier way to infer types */
16
+ $context: C;
17
+ /**
18
+ * custom data in app context, can be referenced from plugins/pages etc
19
+ */
20
+ data: AppContextData & Record<string, unknown>;
21
+ i18nConfig?: I18nConfig<C["lang"]>;
22
+ metaConfig?: Config<C>["meta"];
23
+ siteConfig: {
24
+ name: string;
25
+ baseUrl?: string;
26
+ git?: {
27
+ user: string;
28
+ repo: string;
29
+ branch: string;
30
+ rootDir: string;
31
+ };
32
+ };
33
+ }
34
+ interface AppContextData {
35
+ "core:page-meta"?: ((page: Page) => ReactNode)[];
36
+ "core:docs-layout"?: DocsLayoutContextData;
37
+ "core:home-layout"?: HomeLayoutContextData;
38
+ "core:provider"?: ((props: RootProviderProps) => Awaitable<RootProviderProps>)[];
39
+ }
40
+ //#endregion
41
+ export { AppContext, AppContextData };