fumapress 0.2.5 → 0.3.1

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 (44) hide show
  1. package/css/generated.css +155 -8
  2. package/dist/_virtual/_rolldown/runtime.js +24 -0
  3. package/dist/adapters/mdx/schema.d.ts +39 -0
  4. package/dist/adapters/mdx/schema.js +9 -0
  5. package/dist/adapters/mdx.js +25 -5
  6. package/dist/adapters/openapi.d.ts +15 -0
  7. package/dist/adapters/openapi.js +22 -0
  8. package/dist/components/blog-panel.js +56 -0
  9. package/dist/components/blog.js +60 -0
  10. package/dist/config.d.ts +23 -10
  11. package/dist/index.d.ts +2 -2
  12. package/dist/layouts/blog.d.ts +21 -0
  13. package/dist/layouts/blog.index.d.ts +15 -0
  14. package/dist/layouts/blog.index.js +36 -0
  15. package/dist/layouts/blog.js +82 -0
  16. package/dist/layouts/blog.tags.d.ts +19 -0
  17. package/dist/layouts/blog.tags.js +113 -0
  18. package/dist/layouts/docs.d.ts +3 -3
  19. package/dist/layouts/docs.js +24 -51
  20. package/dist/layouts/home.d.ts +18 -6
  21. package/dist/layouts/home.js +37 -21
  22. package/dist/layouts/notebook.d.ts +3 -3
  23. package/dist/layouts/notebook.js +24 -51
  24. package/dist/layouts/root.js +5 -6
  25. package/dist/layouts/switch.d.ts +11 -0
  26. package/dist/layouts/switch.js +21 -0
  27. package/dist/lib/cn.js +2 -0
  28. package/dist/lib/join-pathname.js +9 -0
  29. package/dist/lib/shared/blog.js +39 -0
  30. package/dist/lib/shared.d.ts +3 -2
  31. package/dist/lib/shared.js +50 -11
  32. package/dist/lib/types.d.ts +20 -6
  33. package/dist/node_modules/.pnpm/@fastify_deepmerge@3.2.1/node_modules/@fastify/deepmerge/index.js +108 -0
  34. package/dist/plugins/blog.d.ts +72 -0
  35. package/dist/plugins/blog.js +175 -0
  36. package/dist/plugins/llms.txt.d.ts +1 -1
  37. package/dist/plugins/llms.txt.js +5 -5
  38. package/dist/plugins/openapi.d.ts +13 -0
  39. package/dist/plugins/openapi.js +21 -0
  40. package/dist/router.d.ts +7 -6
  41. package/dist/router.js +49 -40
  42. package/dist/vite.d.ts +11 -3
  43. package/dist/vite.js +3 -4
  44. package/package.json +32 -11
package/css/generated.css CHANGED
@@ -1,82 +1,187 @@
1
+ @source inline("---spacing");
2
+ @source inline("-translate-x-1/2");
1
3
  @source inline("@orama/orama");
2
4
  @source inline("absolutePath");
3
- @source inline("adapter");
5
+ @source inline("active:scale-95");
4
6
  @source inline("as");
5
7
  @source inline("async");
6
8
  @source inline("await");
9
+ @source inline("backdrop-blur-sm");
10
+ @source inline("bg-fd-card");
11
+ @source inline("bg-fd-primary");
12
+ @source inline("bg-fd-primary/10");
13
+ @source inline("bg-fd-secondary/80");
14
+ @source inline("blog");
15
+ @source inline("blogPosts");
7
16
  @source inline("body");
17
+ @source inline("border");
18
+ @source inline("border-2");
8
19
  @source inline("border-b");
20
+ @source inline("border-dashed");
21
+ @source inline("border-fd-primary");
22
+ @source inline("border-y");
23
+ @source inline("bottom-2");
24
+ @source inline("buttonVariants");
9
25
  @source inline("children");
26
+ @source inline("class-variance-authority");
10
27
  @source inline("className");
11
28
  @source inline("client");
29
+ @source inline("cn");
12
30
  @source inline("const");
13
31
  @source inline("core:docs-layout");
14
32
  @source inline("core:home-layout");
15
33
  @source inline("core:notebook-layout");
16
34
  @source inline("core:provider");
17
- @source inline("core:render-body");
18
- @source inline("core:render-toc");
35
+ @source inline("count");
19
36
  @source inline("create");
20
- @source inline("createDocsLayout");
37
+ @source inline("createBlogIndexPage");
38
+ @source inline("createBlogLayout");
39
+ @source inline("createBlogLayoutPage");
40
+ @source inline("createBlogTagPage");
41
+ @source inline("createBlogTagsPage");
42
+ @source inline("createDocsLayoutPage");
21
43
  @source inline("createHomeLayout");
22
- @source inline("createNotebookLayout");
44
+ @source inline("createHomeLayoutPage");
45
+ @source inline("createLayoutSwitch");
46
+ @source inline("createLayoutSwitchAuto");
47
+ @source inline("createNotebookLayoutPage");
23
48
  @source inline("createRootLayout");
49
+ @source inline("creationDate");
50
+ @source inline("ctx");
51
+ @source inline("currentDate");
52
+ @source inline("cva");
24
53
  @source inline("data");
25
54
  @source inline("data-version");
26
55
  @source inline("date");
56
+ @source inline("decoration-fd-primary");
27
57
  @source inline("default");
58
+ @source inline("detect");
59
+ @source inline("detector");
60
+ @source inline("duration-150");
28
61
  @source inline("else");
29
62
  @source inline("empty");
63
+ @source inline("empty:hidden");
30
64
  @source inline("en");
31
65
  @source inline("english");
32
66
  @source inline("export");
33
67
  @source inline("extends");
68
+ @source inline("false");
69
+ @source inline("fixed");
34
70
  @source inline("flex");
71
+ @source inline("flex-1");
35
72
  @source inline("flex-col");
36
73
  @source inline("flex-row");
74
+ @source inline("flex-wrap");
37
75
  @source inline("flexsearchStaticClient");
76
+ @source inline("font-medium");
77
+ @source inline("font-mono");
78
+ @source inline("font-semibold");
38
79
  @source inline("for");
39
80
  @source inline("from");
40
81
  @source inline("fumadocs-core/source");
41
82
  @source inline("fumadocs-core/toc");
42
83
  @source inline("function");
84
+ @source inline("gap-1");
43
85
  @source inline("gap-2");
86
+ @source inline("gap-4");
87
+ @source inline("getCreationDate");
88
+ @source inline("getTags");
89
+ @source inline("ghost");
44
90
  @source inline("githubUrl");
91
+ @source inline("grid");
92
+ @source inline("grid-cols-1");
93
+ @source inline("grid-cols-2");
94
+ @source inline("groupTags");
95
+ @source inline("grouped");
45
96
  @source inline("hook");
46
97
  @source inline("hooks");
98
+ @source inline("hover:bg-fd-accent");
99
+ @source inline("hover:text-fd-accent-foreground");
100
+ @source inline("href");
47
101
  @source inline("i18n");
48
102
  @source inline("i18nConfig");
49
103
  @source inline("if");
50
104
  @source inline("import");
51
105
  @source inline("in");
106
+ @source inline("inherit");
107
+ @source inline("inline-flex");
52
108
  @source inline("interface");
53
109
  @source inline("isLoading");
110
+ @source inline("item");
54
111
  @source inline("items");
55
112
  @source inline("items-center");
113
+ @source inline("items-start");
114
+ @source inline("joinPathname");
115
+ @source inline("key");
56
116
  @source inline("lang");
57
117
  @source inline("language");
58
118
  @source inline("languages");
59
119
  @source inline("lastModified");
120
+ @source inline("layout");
60
121
  @source inline("layoutData");
61
122
  @source inline("layoutProps");
123
+ @source inline("layouts");
124
+ @source inline("left-1/2");
125
+ @source inline("length");
62
126
  @source inline("let");
63
127
  @source inline("loaderConfig");
64
128
  @source inline("locale");
65
129
  @source inline("locales");
130
+ @source inline("lucide-react");
66
131
  @source inline("markdownUrl");
132
+ @source inline("matching");
133
+ @source inline("max-h-[min(600px,calc(100vh---spacing(30)))]");
134
+ @source inline("max-sm:-mx-4");
135
+ @source inline("max-w-[1400px]");
136
+ @source inline("max-w-[900px]");
137
+ @source inline("max-w-[calc(100%---spacing(4))]");
67
138
  @source inline("mb-0");
139
+ @source inline("md:grid-cols-3");
140
+ @source inline("md:grid-cols-4");
141
+ @source inline("md:p-8");
68
142
  @source inline("min-h-screen");
143
+ @source inline("min-w-0");
144
+ @source inline("ms-auto");
145
+ @source inline("mt-4");
146
+ @source inline("mt-6");
147
+ @source inline("mt-auto");
148
+ @source inline("mx-auto");
69
149
  @source inline("name");
150
+ @source inline("never");
70
151
  @source inline("new");
71
152
  @source inline("of");
153
+ @source inline("onClick");
154
+ @source inline("onCopy");
155
+ @source inline("onOpenChange");
72
156
  @source inline("onSearchChange");
157
+ @source inline("open");
73
158
  @source inline("option");
159
+ @source inline("options");
160
+ @source inline("orderedPosts");
161
+ @source inline("overline");
162
+ @source inline("p-1");
163
+ @source inline("p-4");
74
164
  @source inline("page");
75
165
  @source inline("pageProps");
166
+ @source inline("panelButtonVariants");
167
+ @source inline("pb-20");
76
168
  @source inline("pb-6");
169
+ @source inline("posts");
170
+ @source inline("primary");
77
171
  @source inline("props");
172
+ @source inline("prose");
78
173
  @source inline("providerProps");
79
174
  @source inline("pt-2");
175
+ @source inline("pt-3.5");
176
+ @source inline("pt-4");
177
+ @source inline("pt-6");
178
+ @source inline("px-1.5");
179
+ @source inline("px-2");
180
+ @source inline("px-3");
181
+ @source inline("px-4");
182
+ @source inline("py-0.5");
183
+ @source inline("py-1");
184
+ @source inline("py-2");
80
185
  @source inline("query");
81
186
  @source inline("r");
82
187
  @source inline("react");
@@ -86,23 +191,65 @@
86
191
  @source inline("result");
87
192
  @source inline("return");
88
193
  @source inline("root");
89
- @source inline("satisfies");
194
+ @source inline("rotate-180");
195
+ @source inline("rounded-2xl");
196
+ @source inline("rounded-lg");
197
+ @source inline("rounded-xl");
90
198
  @source inline("schema");
91
199
  @source inline("search");
200
+ @source inline("setOpen");
201
+ @source inline("shadow-inner");
202
+ @source inline("shadow-md");
203
+ @source inline("shadow-sm");
204
+ @source inline("shrink-0");
205
+ @source inline("size-3.5");
206
+ @source inline("size-4");
207
+ @source inline("size-6");
208
+ @source inline("sm:border");
209
+ @source inline("sm:bottom-4");
210
+ @source inline("sm:grid-cols-3");
211
+ @source inline("sm:max-w-[400px]");
212
+ @source inline("sm:rounded-xl");
92
213
  @source inline("source");
93
214
  @source inline("specify");
94
215
  @source inline("static");
95
216
  @source inline("string");
96
217
  @source inline("styles");
218
+ @source inline("tags");
219
+ @source inline("tagsPath");
220
+ @source inline("text-2xl");
221
+ @source inline("text-3xl");
222
+ @source inline("text-fd-card-foreground");
223
+ @source inline("text-fd-muted-foreground");
224
+ @source inline("text-fd-primary");
225
+ @source inline("text-fd-primary-foreground");
226
+ @source inline("text-sm");
227
+ @source inline("text-xs");
97
228
  @source inline("the");
98
229
  @source inline("this");
99
- @source inline("throw");
230
+ @source inline("title");
231
+ @source inline("to");
100
232
  @source inline("toc");
233
+ @source inline("transition-all");
234
+ @source inline("transition-colors");
235
+ @source inline("transition-transform");
101
236
  @source inline("translations");
102
237
  @source inline("tree");
238
+ @source inline("truncate");
103
239
  @source inline("type");
104
240
  @source inline("undefined");
105
241
  @source inline("unstable_notFound");
242
+ @source inline("url");
106
243
  @source inline("use");
244
+ @source inline("useCopyButton");
107
245
  @source inline("useDocsSearch");
108
- @source inline("useI18n");
246
+ @source inline("useI18n");
247
+ @source inline("useState");
248
+ @source inline("useTOCItems");
249
+ @source inline("variant");
250
+ @source inline("w-full");
251
+ @source inline("waku");
252
+ @source inline("xl:grid-cols-4");
253
+ @source inline("xl:grid-cols-6");
254
+ @source inline("z-2");
255
+ @source inline("z-20");
@@ -0,0 +1,24 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ export { __commonJSMin, __toESM };
@@ -0,0 +1,39 @@
1
+ import * as base from "fumadocs-core/source/schema";
2
+ import z from "zod";
3
+
4
+ //#region src/adapters/mdx/schema.d.ts
5
+ declare const pageSchema: z.ZodObject<{
6
+ title: z.ZodString;
7
+ description: z.ZodOptional<z.ZodString>;
8
+ icon: z.ZodOptional<z.ZodString>;
9
+ full: z.ZodOptional<z.ZodBoolean>;
10
+ _openapi: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodCustom<base._JSONType, base._JSONType>>>;
11
+ }, z.core.$strip>;
12
+ declare const metaSchema: z.ZodObject<{
13
+ title: z.ZodOptional<z.ZodString>;
14
+ pages: z.ZodOptional<z.ZodArray<z.ZodString>>;
15
+ description: z.ZodOptional<z.ZodString>;
16
+ root: z.ZodOptional<z.ZodBoolean>;
17
+ defaultOpen: z.ZodOptional<z.ZodBoolean>;
18
+ collapsible: z.ZodOptional<z.ZodBoolean>;
19
+ icon: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strip>;
21
+ declare const blogPageSchema: z.ZodObject<{
22
+ title: z.ZodString;
23
+ description: z.ZodOptional<z.ZodString>;
24
+ icon: z.ZodOptional<z.ZodString>;
25
+ full: z.ZodOptional<z.ZodBoolean>;
26
+ _openapi: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodCustom<base._JSONType, base._JSONType>>>;
27
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
28
+ }, z.core.$strip>;
29
+ declare const blogMetaSchema: z.ZodObject<{
30
+ title: z.ZodOptional<z.ZodString>;
31
+ pages: z.ZodOptional<z.ZodArray<z.ZodString>>;
32
+ description: z.ZodOptional<z.ZodString>;
33
+ root: z.ZodOptional<z.ZodBoolean>;
34
+ defaultOpen: z.ZodOptional<z.ZodBoolean>;
35
+ collapsible: z.ZodOptional<z.ZodBoolean>;
36
+ icon: z.ZodOptional<z.ZodString>;
37
+ }, z.core.$strip>;
38
+ //#endregion
39
+ export { blogMetaSchema, blogPageSchema, metaSchema, pageSchema };
@@ -0,0 +1,9 @@
1
+ import * as base from "fumadocs-core/source/schema";
2
+ import z from "zod";
3
+ //#region src/adapters/mdx/schema.ts
4
+ const pageSchema = base.pageSchema;
5
+ const metaSchema = base.metaSchema;
6
+ const blogPageSchema = base.pageSchema.extend({ tags: z.array(z.string()).optional() });
7
+ const blogMetaSchema = base.metaSchema;
8
+ //#endregion
9
+ export { blogMetaSchema, blogPageSchema, metaSchema, pageSchema };
@@ -1,8 +1,14 @@
1
1
  import { createElement } from "react";
2
2
  import defaultMdxComponents, { createRelativeLink } from "fumadocs-ui/mdx";
3
+ import { z } from "zod/mini";
3
4
  //#region src/adapters/mdx.ts
4
5
  function fumadocsMdx(options) {
5
- 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
+ };
6
12
  return {
7
13
  async "core:get-text"(page) {
8
14
  if (isAsyncEntry(page.data) || isSyncEntry(page.data)) return page.data.getText("processed");
@@ -16,17 +22,31 @@ function fumadocsMdx(options) {
16
22
  if (isSyncEntry(page.data)) body = page.data.body;
17
23
  else if (isAsyncEntry(page.data)) body = (await page.data.load()).body;
18
24
  else return;
19
- return createElement(body, getMdxComponents ? await getMdxComponents.call(this, page) : { components: {
20
- ...defaultMdxComponents,
21
- a: createRelativeLink(await this.getLoader(), page)
22
- } });
25
+ return createElement(body, { components: await getMdxComponents.call(this, page) });
23
26
  },
24
27
  async "core:render-toc"(page) {
25
28
  if (isSyncEntry(page.data)) return page.data.toc;
26
29
  if (isAsyncEntry(page.data)) return (await page.data.load()).toc;
30
+ },
31
+ "core:get-creation-date"(page) {
32
+ if (isSyncEntry(page.data) || isAsyncEntry(page.data)) return "date" in page.data && page.data.date instanceof Date ? page.data.date : void 0;
33
+ },
34
+ async "core:get-modified-date"(page) {
35
+ let data;
36
+ if (isSyncEntry(page.data)) data = page.data;
37
+ else if (isAsyncEntry(page.data)) data = await page.data.load();
38
+ else return;
39
+ return "lastModified" in data && data.lastModified instanceof Date ? data.lastModified : void 0;
40
+ },
41
+ "blog:get-tags"(page) {
42
+ if (isSyncEntry(page.data) || isAsyncEntry(page.data)) {
43
+ const parsed = tagsSchema.safeParse(page.data);
44
+ return parsed.success ? parsed.data.tags : void 0;
45
+ }
27
46
  }
28
47
  };
29
48
  }
49
+ const tagsSchema = z.looseObject({ tags: z.optional(z.array(z.string())) });
30
50
  function isSyncEntry(v) {
31
51
  return "info" in v && typeof v.info === "object" && "_exports" in v && typeof v._exports === "object";
32
52
  }
@@ -0,0 +1,15 @@
1
+ import { ConfigContext } from "../config.js";
2
+ import { Adapter } from "../lib/types.js";
3
+ import { FC } from "react";
4
+ import { OpenAPIPageData } from "fumadocs-openapi/server";
5
+ import { ClientApiPageProps } from "fumadocs-openapi/ui/create-client";
6
+
7
+ //#region src/adapters/openapi.d.ts
8
+ interface OpenAPIAdapterOptions {
9
+ ClientAPIPage: FC<ClientApiPageProps>;
10
+ }
11
+ declare function fumadocsOpenAPI<C extends ConfigContext>(options: OpenAPIAdapterOptions): Adapter<C>;
12
+ /** @internal */
13
+ declare function isOpenAPI(data: object): data is OpenAPIPageData;
14
+ //#endregion
15
+ export { OpenAPIAdapterOptions, fumadocsOpenAPI, isOpenAPI };
@@ -0,0 +1,22 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ //#region src/adapters/openapi.tsx
3
+ function fumadocsOpenAPI(options) {
4
+ const { ClientAPIPage } = options;
5
+ return {
6
+ async "core:render-body"(page) {
7
+ if (isOpenAPI(page.data)) return /* @__PURE__ */ jsx(ClientAPIPage, { ...await page.data.getClientAPIPageProps() });
8
+ },
9
+ "core:render-toc"(page) {
10
+ if (isOpenAPI(page.data)) return page.data.toc;
11
+ },
12
+ "core:get-structured-data"(page) {
13
+ if (isOpenAPI(page.data)) return page.data.structuredData;
14
+ }
15
+ };
16
+ }
17
+ /** @internal */
18
+ function isOpenAPI(data) {
19
+ return "getAPIPageProps" in data && typeof data.getAPIPageProps === "function";
20
+ }
21
+ //#endregion
22
+ export { fumadocsOpenAPI, isOpenAPI };
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { useState } from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { ChevronDown, ShareIcon } from "lucide-react";
6
+ import { TOCProvider, TOCScrollArea, useTOCItems } from "fumadocs-ui/components/toc";
7
+ import { TOCItem, TOCItems } from "fumadocs-ui/components/toc/clerk";
8
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "fumadocs-ui/components/ui/collapsible";
9
+ import { cva } from "class-variance-authority";
10
+ import { useCopyButton } from "fumadocs-ui/utils/use-copy-button";
11
+ //#region src/components/blog-panel.tsx
12
+ const panelButtonVariants = cva("inline-flex items-center font-medium gap-2 px-3 py-2 transition-all duration-150 rounded-lg hover:text-fd-accent-foreground hover:bg-fd-accent active:scale-95");
13
+ function BlogPanel() {
14
+ const items = useTOCItems();
15
+ const [open, setOpen] = useState(false);
16
+ const [isSuccessful, onCopy] = useCopyButton(() => {
17
+ if (navigator.share) return navigator.share({
18
+ title: document.title,
19
+ url: location.href
20
+ });
21
+ else return navigator.clipboard.writeText(location.href);
22
+ });
23
+ return /* @__PURE__ */ jsxs(Collapsible, {
24
+ open,
25
+ onOpenChange: setOpen,
26
+ className: "fixed w-full max-w-[calc(100%---spacing(4))] left-1/2 -translate-x-1/2 bottom-2 border shadow-md text-sm bg-fd-secondary/80 backdrop-blur-sm z-20 p-1 rounded-xl sm:max-w-[400px] sm:bottom-4",
27
+ children: [/* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(TOCScrollArea, {
28
+ className: "max-h-[min(600px,calc(100vh---spacing(30)))]",
29
+ children: /* @__PURE__ */ jsx(TOCItems, { children: items.map((item) => /* @__PURE__ */ jsx(TOCItem, {
30
+ item,
31
+ onClick: () => setOpen(false)
32
+ }, item.url)) })
33
+ }) }), /* @__PURE__ */ jsxs("div", {
34
+ className: "flex flex-row gap-2",
35
+ children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
36
+ className: cn(panelButtonVariants(), "min-w-0"),
37
+ children: [/* @__PURE__ */ jsx("span", {
38
+ className: "truncate",
39
+ children: "Table of Contents"
40
+ }), /* @__PURE__ */ jsx(ChevronDown, { className: cn("size-3.5 shrink-0 text-fd-muted-foreground transition-transform", open && "rotate-180") })]
41
+ }), /* @__PURE__ */ jsxs("button", {
42
+ className: cn(panelButtonVariants(), "ms-auto text-fd-muted-foreground"),
43
+ onClick: onCopy,
44
+ children: [/* @__PURE__ */ jsx(ShareIcon, { className: "size-3.5 shrink-0" }), isSuccessful ? "Copied" : "Share"]
45
+ })]
46
+ })]
47
+ });
48
+ }
49
+ function BlogProvider({ toc, children }) {
50
+ return /* @__PURE__ */ jsx(TOCProvider, {
51
+ toc,
52
+ children
53
+ });
54
+ }
55
+ //#endregion
56
+ export { BlogPanel, BlogProvider };
@@ -0,0 +1,60 @@
1
+ import { getCreationDate } from "../lib/shared.js";
2
+ import { cn } from "../lib/cn.js";
3
+ import { joinPathname } from "../lib/join-pathname.js";
4
+ import { Link } from "waku";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { buttonVariants } from "fumadocs-ui/components/ui/button";
7
+ import { CornerLeftUpIcon } from "lucide-react";
8
+ //#region src/components/blog.tsx
9
+ function BlogItem({ page, date }) {
10
+ return /* @__PURE__ */ jsxs(Link, {
11
+ to: page.url,
12
+ className: "flex flex-col bg-fd-card rounded-2xl border shadow-sm p-4 transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground",
13
+ children: [
14
+ /* @__PURE__ */ jsx("p", {
15
+ className: "font-medium",
16
+ children: page.data.title
17
+ }),
18
+ /* @__PURE__ */ jsx("p", {
19
+ className: "text-sm text-fd-muted-foreground",
20
+ children: page.data.description
21
+ }),
22
+ /* @__PURE__ */ jsx("p", {
23
+ className: "mt-auto pt-4 text-xs text-fd-primary",
24
+ children: date.toDateString()
25
+ })
26
+ ]
27
+ });
28
+ }
29
+ async function OrderedBlogGrid({ posts, ctx }) {
30
+ const currentDate = new Date(Date.now());
31
+ const orderedPosts = [];
32
+ for (const page of posts) {
33
+ const date = await getCreationDate(ctx, page);
34
+ orderedPosts.push({
35
+ page,
36
+ date: date ?? currentDate
37
+ });
38
+ }
39
+ orderedPosts.sort((a, b) => b.date.getTime() - a.date.getTime());
40
+ return /* @__PURE__ */ jsx("div", {
41
+ className: "grid grid-cols-1 gap-2 mt-4 md:grid-cols-3 xl:grid-cols-4",
42
+ children: orderedPosts.map(({ page, date }) => /* @__PURE__ */ jsx(BlogItem, {
43
+ page,
44
+ date
45
+ }, page.url))
46
+ });
47
+ }
48
+ function LinkToHome({ lang, blog }) {
49
+ if (!blog.indexPath) return;
50
+ return /* @__PURE__ */ jsxs(Link, {
51
+ to: lang ? joinPathname(lang, blog.indexPath) : blog.indexPath,
52
+ className: cn(buttonVariants({
53
+ variant: "ghost",
54
+ className: "text-fd-muted-foreground gap-2"
55
+ })),
56
+ children: [/* @__PURE__ */ jsx(CornerLeftUpIcon, { className: "size-3.5" }), "Back to Home"]
57
+ });
58
+ }
59
+ //#endregion
60
+ export { LinkToHome, OrderedBlogGrid };
package/dist/config.d.ts CHANGED
@@ -4,6 +4,7 @@ import { ComponentType, ReactNode } from "react";
4
4
  import { TranslationsOption } from "fumadocs-ui/contexts/i18n";
5
5
  import { LoaderConfig, LoaderOutput } from "fumadocs-core/source";
6
6
  import { I18nConfig } from "fumadocs-core/i18n";
7
+ import { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
7
8
 
8
9
  //#region src/config.d.ts
9
10
  interface ConfigContext {
@@ -26,31 +27,43 @@ interface Config<C extends ConfigContext = ConfigContext> {
26
27
  /** adapter for content sources, use `fumadocs-mdx` if not specified */
27
28
  adapters?: Adapter[];
28
29
  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
- };
30
+ meta?: MetaConfig<C>;
33
31
  }
34
32
  interface Layouts<C extends ConfigContext = ConfigContext> {
35
- root: ComponentType<AppContext<C> & {
33
+ root: ComponentType<{
36
34
  lang?: string;
35
+ ctx: AppContext<C>;
37
36
  children: ReactNode;
38
37
  }>;
39
- page: ComponentType<AppContext<C> & {
38
+ page: ComponentType<{
40
39
  lang?: string;
41
40
  slugs: string[];
41
+ ctx: AppContext<C>;
42
+ page: C["loaderConfig"]["page"];
42
43
  }>;
43
- notFound: ComponentType<AppContext<C> & {
44
+ notFound: ComponentType<{
44
45
  lang?: string;
46
+ ctx: AppContext<C>;
45
47
  }>;
48
+ /**
49
+ * Define default props for page layouts, will be merged with current props.
50
+ */
51
+ defaultProps?: (this: AppContext<C>, env: {
52
+ lang: string | undefined;
53
+ }) => Awaitable<Omit<BaseLayoutProps, "children">>;
46
54
  }
47
- interface I18nConfig$1<Lang extends string = string> extends Pick<I18nConfig<NoInfer<Lang>>, "fallbackLanguage" | "parser"> {
55
+ interface I18nConfig$1<Lang extends string = string> extends Pick<I18nConfig<NoInfer<Lang>>, "defaultLanguage" | "fallbackLanguage" | "parser"> {
48
56
  /** locale code -> language info */
49
57
  languages: { [K in Lang]: {
50
58
  displayName: string;
51
59
  translations?: TranslationsOption;
52
60
  } };
53
- defaultLanguage: NoInfer<Lang>;
61
+ }
62
+ interface MetaConfig<C extends ConfigContext = ConfigContext> {
63
+ /** render meta tags for any pages */
64
+ root?: (this: AppContext<C>) => ReactNode;
65
+ /** render meta tags for page */
66
+ page?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => ReactNode;
54
67
  }
55
68
  interface SiteConfig {
56
69
  /** full URL of app, used for metadata generation*/
@@ -81,4 +94,4 @@ declare function defineConfig<C extends LoaderConfig, L extends string = string>
81
94
  }>;
82
95
  declare function defineI18nConfig<Lang extends string>(config: I18nConfig$1<Lang>): I18nConfigBuilder<Lang>;
83
96
  //#endregion
84
- export { BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig$1 as I18nConfig, I18nConfigBuilder, Layouts, SiteConfig, defineConfig, defineI18nConfig };
97
+ export { BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig$1 as I18nConfig, I18nConfigBuilder, Layouts, MetaConfig, SiteConfig, defineConfig, defineI18nConfig };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { AppContext, AppContextData } from "./lib/shared.js";
2
- import { BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, SiteConfig, defineConfig, defineI18nConfig } from "./config.js";
2
+ import { BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, MetaConfig, SiteConfig, defineConfig, defineI18nConfig } from "./config.js";
3
3
  import { Adapter, RouteFns, ServerPlugin } from "./lib/types.js";
4
- export { type Adapter, type AppContext, type AppContextData, BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, type RouteFns, type ServerPlugin, SiteConfig, defineConfig, defineI18nConfig };
4
+ export { type Adapter, type AppContext, type AppContextData, BuildMode, Config, ConfigBuilder, ConfigContext, I18nConfig, I18nConfigBuilder, Layouts, MetaConfig, type RouteFns, type ServerPlugin, SiteConfig, defineConfig, defineI18nConfig };
@@ -0,0 +1,21 @@
1
+ import { HomeLayoutOptions } from "./home.js";
2
+ import { AppContext } from "../lib/shared.js";
3
+ import { ConfigContext } from "../config.js";
4
+ import { Awaitable } from "../lib/types.js";
5
+ import { BlogLayout, BlogLayoutPage } from "../plugins/blog.js";
6
+ import { ReactNode } from "react";
7
+ import { TOCItemType } from "fumadocs-core/toc";
8
+
9
+ //#region src/layouts/blog.d.ts
10
+ declare function createBlogLayout<C extends ConfigContext = ConfigContext>(options?: HomeLayoutOptions<C>): BlogLayout<C>;
11
+ interface BlogLayoutPageRenderData {
12
+ creationDate?: Date;
13
+ toc: TOCItemType[];
14
+ body: ReactNode;
15
+ }
16
+ interface BlogLayoutPageOptions<C extends ConfigContext = ConfigContext> {
17
+ render?: (this: AppContext<C>, page: C["loaderConfig"]["page"]) => Awaitable<Partial<BlogLayoutPageRenderData>>;
18
+ }
19
+ declare function createBlogLayoutPage<C extends ConfigContext = ConfigContext>(options?: BlogLayoutPageOptions<C>): BlogLayoutPage<C>;
20
+ //#endregion
21
+ export { BlogLayoutPageOptions, BlogLayoutPageRenderData, createBlogLayout, createBlogLayoutPage };
@@ -0,0 +1,15 @@
1
+ import { ConfigContext } from "../config.js";
2
+ import { BlogIndexPage } from "../plugins/blog.js";
3
+ import { ReactNode } from "react";
4
+
5
+ //#region src/layouts/blog.index.d.ts
6
+ interface BlogIndexPageOptions {
7
+ heading?: ReactNode;
8
+ description?: ReactNode;
9
+ }
10
+ declare function createBlogIndexPage<C extends ConfigContext = ConfigContext>({
11
+ heading,
12
+ description
13
+ }?: BlogIndexPageOptions): BlogIndexPage<C>;
14
+ //#endregion
15
+ export { BlogIndexPageOptions, createBlogIndexPage };