@farming-labs/theme 0.2.97 → 0.2.99
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/dist/browser.d.mts +25 -0
- package/dist/browser.mjs +74 -0
- package/dist/docs-client-hooks.mjs +1 -1
- package/dist/docs-command-search.mjs +13 -2
- package/dist/docs-layout.mjs +60 -4
- package/dist/docs-page-client.d.mts +9 -0
- package/dist/docs-page-client.mjs +49 -10
- package/dist/mdx.mjs +1 -1
- package/dist/open-docs-provider-icons.mjs +14 -0
- package/dist/open-docs-providers.mjs +17 -2
- package/dist/page-actions.mjs +3 -8
- package/dist/pixel-border/index.d.mts +1 -0
- package/dist/pixel-border/index.mjs +11 -10
- package/dist/reading-time-options.mjs +27 -0
- package/dist/reading-time.mjs +2 -24
- package/dist/tablet-sidebar-bridge.mjs +64 -0
- package/dist/tanstack-layout.d.mts +2 -0
- package/dist/tanstack-layout.mjs +8 -4
- package/dist/tanstack.d.mts +1 -1
- package/dist/tanstack.mjs +1 -1
- package/package.json +9 -2
- package/styles/bundles/browser-framework.css +10585 -0
- package/styles/bundles/shared-framework.css +3 -3
- package/styles/pixel-border.css +1097 -68
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { TanstackDocsLayout, TanstackDocsLayoutProps } from "./tanstack-layout.mjs";
|
|
2
|
+
import { ComponentPropsWithoutRef } from "react";
|
|
3
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
+
import { RootProvider } from "fumadocs-ui/provider/base";
|
|
5
|
+
|
|
6
|
+
//#region src/browser.d.ts
|
|
7
|
+
type FumadocsProviderProps = ComponentPropsWithoutRef<typeof RootProvider>;
|
|
8
|
+
declare global {
|
|
9
|
+
interface Window {
|
|
10
|
+
__fdBrowserHistoryPatched?: boolean;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
interface BrowserRootProviderProps extends FumadocsProviderProps {
|
|
14
|
+
/** Path rendered by the server, used to keep hydration deterministic. */
|
|
15
|
+
initialPathname?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Framework-neutral provider for server-rendered React documentation adapters. */
|
|
18
|
+
declare function BrowserRootProvider({
|
|
19
|
+
children,
|
|
20
|
+
search,
|
|
21
|
+
initialPathname,
|
|
22
|
+
...props
|
|
23
|
+
}: BrowserRootProviderProps): react_jsx_runtime0.JSX.Element;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { TanstackDocsLayout as BrowserDocsLayout, type TanstackDocsLayoutProps as BrowserDocsLayoutProps, BrowserRootProvider, BrowserRootProviderProps };
|
package/dist/browser.mjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { TanstackDocsLayout } from "./tanstack-layout.mjs";
|
|
4
|
+
import { useMemo, useSyncExternalStore } from "react";
|
|
5
|
+
import { FrameworkProvider } from "fumadocs-core/framework";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import { RootProvider } from "fumadocs-ui/provider/base";
|
|
8
|
+
|
|
9
|
+
//#region src/browser.tsx
|
|
10
|
+
function patchHistoryEvents() {
|
|
11
|
+
if (typeof window === "undefined" || window.__fdBrowserHistoryPatched) return;
|
|
12
|
+
for (const method of ["pushState", "replaceState"]) {
|
|
13
|
+
const original = window.history[method];
|
|
14
|
+
window.history[method] = function patchedHistoryMethod(...args) {
|
|
15
|
+
const result = original.apply(this, args);
|
|
16
|
+
window.dispatchEvent(new Event("fd-location-change"));
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
window.__fdBrowserHistoryPatched = true;
|
|
21
|
+
}
|
|
22
|
+
function subscribeToLocation(onStoreChange) {
|
|
23
|
+
if (typeof window === "undefined") return () => {};
|
|
24
|
+
patchHistoryEvents();
|
|
25
|
+
window.addEventListener("popstate", onStoreChange);
|
|
26
|
+
window.addEventListener("fd-location-change", onStoreChange);
|
|
27
|
+
return () => {
|
|
28
|
+
window.removeEventListener("popstate", onStoreChange);
|
|
29
|
+
window.removeEventListener("fd-location-change", onStoreChange);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function getBrowserPathname() {
|
|
33
|
+
return typeof window === "undefined" ? "/" : window.location.pathname;
|
|
34
|
+
}
|
|
35
|
+
function useBrowserRouter() {
|
|
36
|
+
return useMemo(() => ({
|
|
37
|
+
push(url) {
|
|
38
|
+
window.location.assign(url);
|
|
39
|
+
},
|
|
40
|
+
refresh() {
|
|
41
|
+
window.location.reload();
|
|
42
|
+
}
|
|
43
|
+
}), []);
|
|
44
|
+
}
|
|
45
|
+
function useBrowserParams() {
|
|
46
|
+
return useMemo(() => ({}), []);
|
|
47
|
+
}
|
|
48
|
+
function BrowserLink({ prefetch: _prefetch, ...props }) {
|
|
49
|
+
return /* @__PURE__ */ jsx("a", { ...props });
|
|
50
|
+
}
|
|
51
|
+
/** Framework-neutral provider for server-rendered React documentation adapters. */
|
|
52
|
+
function BrowserRootProvider({ children, search, initialPathname = "/", ...props }) {
|
|
53
|
+
const useBrowserPathname = () => useSyncExternalStore(subscribeToLocation, getBrowserPathname, () => initialPathname);
|
|
54
|
+
return /* @__PURE__ */ jsx(FrameworkProvider, {
|
|
55
|
+
Link: BrowserLink,
|
|
56
|
+
usePathname: useBrowserPathname,
|
|
57
|
+
useParams: useBrowserParams,
|
|
58
|
+
useRouter: useBrowserRouter,
|
|
59
|
+
children: /* @__PURE__ */ jsx(RootProvider, {
|
|
60
|
+
search: {
|
|
61
|
+
...search,
|
|
62
|
+
options: {
|
|
63
|
+
api: "/api/docs",
|
|
64
|
+
...search?.options
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
...props,
|
|
68
|
+
children
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
export { TanstackDocsLayout as BrowserDocsLayout, BrowserRootProvider };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { emitClientAnalyticsEvent } from "./client-analytics.mjs";
|
|
4
4
|
import { useEffect } from "react";
|
|
5
|
-
import { emitDocsAnalyticsEvent, resolveDocsAnalyticsConfig } from "@farming-labs/docs";
|
|
5
|
+
import { emitDocsAnalyticsEvent, resolveDocsAnalyticsConfig } from "@farming-labs/docs/browser";
|
|
6
6
|
|
|
7
7
|
//#region src/docs-client-hooks.tsx
|
|
8
8
|
function useWindowHook(key, handler) {
|
|
@@ -256,6 +256,7 @@ function DocsCommandSearch({ api = "/api/docs", locale, analytics = false }) {
|
|
|
256
256
|
const searchApi = useMemo(() => withLangInUrl(api, activeLocale), [activeLocale, api]);
|
|
257
257
|
const inputRef = useRef(null);
|
|
258
258
|
const listRef = useRef(null);
|
|
259
|
+
const restoreFocusRef = useRef(null);
|
|
259
260
|
const searchCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
260
261
|
const setOpenWithAnalytics = useCallback((nextOpen, trigger) => {
|
|
261
262
|
setOpen(nextOpen);
|
|
@@ -404,13 +405,23 @@ function DocsCommandSearch({ api = "/api/docs", locale, analytics = false }) {
|
|
|
404
405
|
searchApi
|
|
405
406
|
]);
|
|
406
407
|
useEffect(() => {
|
|
407
|
-
if (open)
|
|
408
|
-
|
|
408
|
+
if (open) {
|
|
409
|
+
const activeElement = document.activeElement;
|
|
410
|
+
restoreFocusRef.current = activeElement instanceof HTMLElement ? activeElement : null;
|
|
411
|
+
const focusTimer = window.setTimeout(() => inputRef.current?.focus(), 10);
|
|
412
|
+
return () => window.clearTimeout(focusTimer);
|
|
413
|
+
} else {
|
|
409
414
|
setQuery("");
|
|
410
415
|
setResults([]);
|
|
411
416
|
setFilter("all");
|
|
412
417
|
setFilterOpen(false);
|
|
413
418
|
setActiveIndex(0);
|
|
419
|
+
const restoreTarget = restoreFocusRef.current;
|
|
420
|
+
restoreFocusRef.current = null;
|
|
421
|
+
if (restoreTarget?.isConnected) {
|
|
422
|
+
const focusFrame = window.requestAnimationFrame(() => restoreTarget.focus({ preventScroll: true }));
|
|
423
|
+
return () => window.cancelAnimationFrame(focusFrame);
|
|
424
|
+
}
|
|
414
425
|
}
|
|
415
426
|
}, [open]);
|
|
416
427
|
useEffect(() => {
|
package/dist/docs-layout.mjs
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { serializeIcon } from "./serialize-icon.mjs";
|
|
2
|
+
import { resolveOpenDocsProviders } from "./open-docs-providers.mjs";
|
|
2
3
|
import { withLangInUrl } from "./i18n.mjs";
|
|
3
4
|
import { DocsPageClient } from "./docs-page-client.mjs";
|
|
4
5
|
import { DocsAIFeatures } from "./docs-ai-features.mjs";
|
|
5
6
|
import { resolveDocsCloudAIClientRequest } from "./docs-cloud-ai-client.mjs";
|
|
6
7
|
import { DocsCommandSearch } from "./docs-command-search.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import { resolvePageReadingTime
|
|
8
|
+
import { resolveReadingTimeOptions } from "./reading-time-options.mjs";
|
|
9
|
+
import { resolvePageReadingTime } from "./reading-time.mjs";
|
|
9
10
|
import { SidebarSearchWithAI } from "./sidebar-search-ai.mjs";
|
|
11
|
+
import { TabletSidebarBridge } from "./tablet-sidebar-bridge.mjs";
|
|
10
12
|
import { LocaleThemeControl } from "./locale-theme-control.mjs";
|
|
11
13
|
import fs from "node:fs";
|
|
12
14
|
import path from "node:path";
|
|
@@ -35,6 +37,30 @@ function readFrontmatter(filePath) {
|
|
|
35
37
|
return {};
|
|
36
38
|
}
|
|
37
39
|
}
|
|
40
|
+
function hasAuthoredPageTitle(source) {
|
|
41
|
+
const { content } = matter(source);
|
|
42
|
+
const lines = content.split(/\r?\n/);
|
|
43
|
+
let fence;
|
|
44
|
+
let previousTextLine = "";
|
|
45
|
+
for (const line of lines) {
|
|
46
|
+
const fenceMatch = line.match(/^\s*(`{3,}|~{3,})/);
|
|
47
|
+
if (fenceMatch) {
|
|
48
|
+
const marker = fenceMatch[1]?.[0];
|
|
49
|
+
fence = fence === marker ? void 0 : fence ?? marker;
|
|
50
|
+
previousTextLine = "";
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (fence) continue;
|
|
54
|
+
if (/^ {0,3}#(?:\s+|$)/.test(line) || /^\s*<h1(?:\s|>)/i.test(line)) return true;
|
|
55
|
+
if (previousTextLine && /^ {0,3}=+\s*$/.test(line)) return true;
|
|
56
|
+
previousTextLine = line.trim() && !line.trimStart().startsWith("<") ? line : "";
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
function resolveSidebarFolderName(themeName, slug, pageTitle) {
|
|
61
|
+
if (themeName !== "shadcn" || pageTitle.trim().toLowerCase() !== "introduction") return pageTitle;
|
|
62
|
+
return slug.split(/[-_]/).filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join(" ");
|
|
63
|
+
}
|
|
38
64
|
/** Check if a directory has any subdirectories that contain page.mdx. */
|
|
39
65
|
function isWithinDir(candidate, target) {
|
|
40
66
|
const relative = path.relative(target, candidate);
|
|
@@ -194,12 +220,13 @@ function buildTree(config, ctx, flat = false) {
|
|
|
194
220
|
const url = publicDocsRoute(ctx, slug);
|
|
195
221
|
const icon = resolveIcon(data.icon, icons);
|
|
196
222
|
const displayName = data.title ?? name.replace(/-/g, " ");
|
|
223
|
+
const folderName = resolveSidebarFolderName(config.theme?.name, name, displayName);
|
|
197
224
|
const hasChildren = hasChildPages(full, excludedDirs);
|
|
198
225
|
if (data.hidden === true) {
|
|
199
226
|
if (!hasChildren) return null;
|
|
200
227
|
return {
|
|
201
228
|
type: "folder",
|
|
202
|
-
name:
|
|
229
|
+
name: folderName,
|
|
203
230
|
icon,
|
|
204
231
|
children: scanDir(full, slug, slugOrder),
|
|
205
232
|
...flat ? {
|
|
@@ -212,7 +239,7 @@ function buildTree(config, ctx, flat = false) {
|
|
|
212
239
|
const folderChildren = scanDir(full, slug, slugOrder);
|
|
213
240
|
return {
|
|
214
241
|
type: "folder",
|
|
215
|
-
name:
|
|
242
|
+
name: folderName,
|
|
216
243
|
icon,
|
|
217
244
|
index: {
|
|
218
245
|
type: "page",
|
|
@@ -380,6 +407,31 @@ function buildDescriptionMap(config, ctx) {
|
|
|
380
407
|
scan(docsDir, []);
|
|
381
408
|
return map;
|
|
382
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* Build titles only for pages whose MDX body does not already author an h1.
|
|
412
|
+
* This lets the page frame render the frontmatter title exactly once.
|
|
413
|
+
*/
|
|
414
|
+
function buildGeneratedTitleMap(config, ctx) {
|
|
415
|
+
const docsDir = ctx.docsDir;
|
|
416
|
+
const map = {};
|
|
417
|
+
const excludedDirs = getExcludedDocsDirs(config, ctx);
|
|
418
|
+
function scan(dir, slugParts) {
|
|
419
|
+
if (!fs.existsSync(dir)) return;
|
|
420
|
+
if (isExcludedDir(dir, excludedDirs)) return;
|
|
421
|
+
const pagePath = findDocsPageFile(dir);
|
|
422
|
+
if (pagePath) {
|
|
423
|
+
const source = fs.readFileSync(pagePath, "utf-8");
|
|
424
|
+
const { data } = matter(source);
|
|
425
|
+
if (typeof data.title === "string" && !hasAuthoredPageTitle(source)) map[publicDocsRoute(ctx, slugParts)] = data.title;
|
|
426
|
+
}
|
|
427
|
+
for (const name of fs.readdirSync(dir)) {
|
|
428
|
+
const full = path.join(dir, name);
|
|
429
|
+
if (fs.statSync(full).isDirectory()) scan(full, [...slugParts, name]);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
scan(docsDir, []);
|
|
433
|
+
return map;
|
|
434
|
+
}
|
|
383
435
|
function buildReadingTimeMap(config, ctx, options) {
|
|
384
436
|
const docsDir = ctx.docsDir;
|
|
385
437
|
const map = {};
|
|
@@ -702,6 +754,7 @@ function createDocsLayout(config, options) {
|
|
|
702
754
|
}
|
|
703
755
|
const lastModifiedMap = buildLastModifiedMap(config, localeContext);
|
|
704
756
|
const descriptionMap = buildDescriptionMap(config, localeContext);
|
|
757
|
+
const generatedTitleMap = config.theme?.name === "shadcn" ? buildGeneratedTitleMap(config, localeContext) : {};
|
|
705
758
|
const readingTimeMap = buildReadingTimeMap(config, localeContext, {
|
|
706
759
|
enabledByDefault: readingTimeEnabledByDefault,
|
|
707
760
|
wordsPerMinute: readingTimeWordsPerMinute,
|
|
@@ -756,6 +809,7 @@ function createDocsLayout(config, options) {
|
|
|
756
809
|
/* @__PURE__ */ jsx(TypographyStyle, { typography }),
|
|
757
810
|
/* @__PURE__ */ jsx(LayoutStyle, { layout: layoutDimensions }),
|
|
758
811
|
forcedTheme && /* @__PURE__ */ jsx(ForcedThemeScript, { theme: forcedTheme }),
|
|
812
|
+
config.theme?.name === "fumadocs-pixel-border" && /* @__PURE__ */ jsx(TabletSidebarBridge, {}),
|
|
759
813
|
!staticExport && /* @__PURE__ */ jsx(Suspense, {
|
|
760
814
|
fallback: null,
|
|
761
815
|
children: /* @__PURE__ */ jsx(DocsCommandSearch, {
|
|
@@ -790,6 +844,7 @@ function createDocsLayout(config, options) {
|
|
|
790
844
|
fallback: children,
|
|
791
845
|
children: /* @__PURE__ */ jsx(DocsPageClient, {
|
|
792
846
|
tocEnabled,
|
|
847
|
+
themeName: config.theme?.name,
|
|
793
848
|
tocStyle,
|
|
794
849
|
breadcrumbEnabled,
|
|
795
850
|
changelogBasePath,
|
|
@@ -820,6 +875,7 @@ function createDocsLayout(config, options) {
|
|
|
820
875
|
readingTimeMap,
|
|
821
876
|
structuredDataMap,
|
|
822
877
|
llmsTxtEnabled,
|
|
878
|
+
generatedTitleMap,
|
|
823
879
|
descriptionMap,
|
|
824
880
|
feedbackEnabled: feedbackConfig.enabled,
|
|
825
881
|
feedbackQuestion: feedbackConfig.question,
|
|
@@ -17,6 +17,8 @@ interface SerializedProvider {
|
|
|
17
17
|
}
|
|
18
18
|
interface DocsPageClientProps {
|
|
19
19
|
tocEnabled: boolean;
|
|
20
|
+
/** Active theme preset name, used for theme-specific structural affordances. */
|
|
21
|
+
themeName?: string;
|
|
20
22
|
tocStyle?: "default" | "directional";
|
|
21
23
|
breadcrumbEnabled?: boolean;
|
|
22
24
|
changelogBasePath?: string;
|
|
@@ -78,10 +80,14 @@ interface DocsPageClientProps {
|
|
|
78
80
|
lastUpdatedPosition?: "footer" | "below-title";
|
|
79
81
|
/** Whether llms.txt is enabled — shows links in footer */
|
|
80
82
|
llmsTxtEnabled?: boolean;
|
|
83
|
+
/** Frontmatter titles for pages whose MDX body does not author an h1 */
|
|
84
|
+
generatedTitleMap?: Record<string, string>;
|
|
81
85
|
/** Map of pathname → frontmatter description */
|
|
82
86
|
descriptionMap?: Record<string, string>;
|
|
83
87
|
/** Frontmatter description to display below the page title (overrides descriptionMap) */
|
|
84
88
|
description?: string;
|
|
89
|
+
/** The first authored paragraph already contains the frontmatter description. */
|
|
90
|
+
descriptionInBody?: boolean;
|
|
85
91
|
/** Built-in page feedback prompt configuration */
|
|
86
92
|
feedbackEnabled?: boolean;
|
|
87
93
|
feedbackQuestion?: string;
|
|
@@ -98,6 +104,7 @@ interface DocsPageClientProps {
|
|
|
98
104
|
}
|
|
99
105
|
declare function DocsPageClient({
|
|
100
106
|
tocEnabled,
|
|
107
|
+
themeName,
|
|
101
108
|
tocStyle,
|
|
102
109
|
breadcrumbEnabled,
|
|
103
110
|
changelogBasePath,
|
|
@@ -134,8 +141,10 @@ declare function DocsPageClient({
|
|
|
134
141
|
lastUpdatedLabel,
|
|
135
142
|
lastUpdatedPosition,
|
|
136
143
|
llmsTxtEnabled,
|
|
144
|
+
generatedTitleMap,
|
|
137
145
|
descriptionMap,
|
|
138
146
|
description,
|
|
147
|
+
descriptionInBody,
|
|
139
148
|
feedbackEnabled,
|
|
140
149
|
feedbackQuestion,
|
|
141
150
|
feedbackPlaceholder,
|
|
@@ -255,7 +255,7 @@ function findThreadlineTocActionsContainer() {
|
|
|
255
255
|
}
|
|
256
256
|
return toc.parentElement ?? toc;
|
|
257
257
|
}
|
|
258
|
-
function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled = true, changelogBasePath, entry = "docs", publicPath, locale, copyMarkdown = false, copyMarkdownFormat, copyMarkdownIncludeTitle, copyMarkdownLabel, copyMarkdownCopiedLabel, openDocs = false, openDocsProviders, openDocsTarget, openDocsPrompt, pageActionsPosition = "below-title", pageActionsAlignment = "left", githubUrl, contentDir, githubBranch = "main", githubDirectory, editOnGithubUrl, lastModifiedMap, lastModified: lastModifiedProp, readingTimeMap, readingTime: readingTimeProp, readingTimeFormat = "long", previousPage, nextPage, structuredDataMap, structuredData: structuredDataProp, readingTimeEnabled = false, lastUpdatedEnabled = true, lastUpdatedLabel = "Last updated", lastUpdatedPosition = "footer", llmsTxtEnabled = false, descriptionMap, description, feedbackEnabled = false, feedbackQuestion, feedbackPlaceholder, feedbackRequireComment, feedbackPositiveLabel, feedbackNegativeLabel, feedbackSubmitLabel, feedbackSuccessMessage, feedbackErrorMessage, feedbackOnFeedback, analytics = false, children }) {
|
|
258
|
+
function DocsPageClient({ tocEnabled, themeName, tocStyle = "default", breadcrumbEnabled = true, changelogBasePath, entry = "docs", publicPath, locale, copyMarkdown = false, copyMarkdownFormat, copyMarkdownIncludeTitle, copyMarkdownLabel, copyMarkdownCopiedLabel, openDocs = false, openDocsProviders, openDocsTarget, openDocsPrompt, pageActionsPosition = "below-title", pageActionsAlignment = "left", githubUrl, contentDir, githubBranch = "main", githubDirectory, editOnGithubUrl, lastModifiedMap, lastModified: lastModifiedProp, readingTimeMap, readingTime: readingTimeProp, readingTimeFormat = "long", previousPage, nextPage, structuredDataMap, structuredData: structuredDataProp, readingTimeEnabled = false, lastUpdatedEnabled = true, lastUpdatedLabel = "Last updated", lastUpdatedPosition = "footer", llmsTxtEnabled = false, generatedTitleMap, descriptionMap, description, descriptionInBody = false, feedbackEnabled = false, feedbackQuestion, feedbackPlaceholder, feedbackRequireComment, feedbackPositiveLabel, feedbackNegativeLabel, feedbackSubmitLabel, feedbackSuccessMessage, feedbackErrorMessage, feedbackOnFeedback, analytics = false, children }) {
|
|
259
259
|
const fdTocStyle = tocStyle === "directional" ? "clerk" : void 0;
|
|
260
260
|
const [toc, setToc] = useState([]);
|
|
261
261
|
const [titlePortalHost, setTitlePortalHost] = useState(null);
|
|
@@ -268,8 +268,10 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
268
268
|
const activeLocale = resolveClientLocale(searchParams, locale);
|
|
269
269
|
const resolvedPublicPath = normalizePublicDocsPath(publicPath, entry);
|
|
270
270
|
const llmsLangQuery = activeLocale ? `?lang=${encodeURIComponent(activeLocale)}` : "";
|
|
271
|
-
const
|
|
271
|
+
const showLlmsInHeader = llmsTxtEnabled && themeName === "fumadocs-pixel-border";
|
|
272
272
|
const normalizedPath = (browserPathname || pathname).replace(/\/$/, "") || "/";
|
|
273
|
+
const pageTitle = generatedTitleMap?.[normalizedPath];
|
|
274
|
+
const pageDescription = description ?? descriptionMap?.[normalizedPath];
|
|
273
275
|
const isChangelogRoute = !!(changelogBasePath && (normalizedPath === changelogBasePath || normalizedPath.startsWith(`${changelogBasePath}/`)));
|
|
274
276
|
const matchedReadingTime = readingTimeMap?.[normalizedPath];
|
|
275
277
|
const structuredDataJson = !isChangelogRoute ? structuredDataProp ?? structuredDataMap?.[normalizedPath] : void 0;
|
|
@@ -495,7 +497,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
495
497
|
]
|
|
496
498
|
}, "below-title") : void 0;
|
|
497
499
|
const decoratedChildren = children;
|
|
498
|
-
const needsTitleDecorationsPortal = !!titleDescription || !!belowTitleBlock;
|
|
500
|
+
const needsTitleDecorationsPortal = !pageTitle && (!!titleDescription || !!belowTitleBlock);
|
|
499
501
|
useEffect(() => {
|
|
500
502
|
if (!needsTitleDecorationsPortal) {
|
|
501
503
|
setTitlePortalHost(null);
|
|
@@ -508,19 +510,54 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
508
510
|
}
|
|
509
511
|
const host = document.createElement("div");
|
|
510
512
|
host.className = "fd-title-decorations-host";
|
|
513
|
+
const placeHost = () => {
|
|
514
|
+
let anchor = title;
|
|
515
|
+
if (descriptionInBody) {
|
|
516
|
+
let sibling = title.nextElementSibling;
|
|
517
|
+
while (sibling) {
|
|
518
|
+
if (sibling === host || sibling.matches(".not-prose, .fd-title-decorations-host")) {
|
|
519
|
+
sibling = sibling.nextElementSibling;
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
if (sibling.matches("p")) anchor = sibling;
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
if (anchor.nextElementSibling !== host) anchor.insertAdjacentElement("afterend", host);
|
|
527
|
+
};
|
|
511
528
|
title.insertAdjacentElement("afterend", host);
|
|
529
|
+
placeHost();
|
|
530
|
+
const observer = new MutationObserver(placeHost);
|
|
531
|
+
observer.observe(title.parentElement ?? title, { childList: true });
|
|
532
|
+
const animationFrame = window.requestAnimationFrame(placeHost);
|
|
512
533
|
setTitlePortalHost(host);
|
|
513
534
|
return () => {
|
|
535
|
+
window.cancelAnimationFrame(animationFrame);
|
|
536
|
+
observer.disconnect();
|
|
514
537
|
host.remove();
|
|
515
538
|
setTitlePortalHost(null);
|
|
516
539
|
};
|
|
517
|
-
}, [
|
|
540
|
+
}, [
|
|
541
|
+
descriptionInBody,
|
|
542
|
+
needsTitleDecorationsPortal,
|
|
543
|
+
pathname
|
|
544
|
+
]);
|
|
518
545
|
const titleDecorations = needsTitleDecorationsPortal ? /* @__PURE__ */ jsx(TitleDecorations, {
|
|
519
546
|
description: titleDescription,
|
|
520
547
|
belowTitle: belowTitleBlock
|
|
521
548
|
}) : null;
|
|
522
549
|
const titleDecorationsPortal = titleDecorations && titlePortalHost ? createPortal(titleDecorations, titlePortalHost, "title-decorations") : null;
|
|
523
550
|
const titleDecorationsFallback = titleDecorations && !titlePortalHost ? titleDecorations : null;
|
|
551
|
+
const generatedPageHeader = pageTitle ? /* @__PURE__ */ jsxs("div", {
|
|
552
|
+
className: "fd-generated-page-header not-prose",
|
|
553
|
+
children: [/* @__PURE__ */ jsx("h1", {
|
|
554
|
+
className: "fd-page-title",
|
|
555
|
+
children: pageTitle
|
|
556
|
+
}), /* @__PURE__ */ jsx(TitleDecorations, {
|
|
557
|
+
description: titleDescription,
|
|
558
|
+
belowTitle: belowTitleBlock
|
|
559
|
+
})]
|
|
560
|
+
}) : null;
|
|
524
561
|
const titleControlsPortal = showActionsInToc && titleControlsPortalHost ? createPortal(/* @__PURE__ */ jsx(ThreadlinePageControls, {}), titleControlsPortalHost, "title-controls") : null;
|
|
525
562
|
const tocActionsPortal = showActionsInToc && tocActionsPortalHost ? createPortal(/* @__PURE__ */ jsx("div", {
|
|
526
563
|
className: "fd-actions-toc-portal not-prose",
|
|
@@ -549,10 +586,11 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
549
586
|
llmsTxtEnabled && /* @__PURE__ */ jsx("a", {
|
|
550
587
|
href: `/llms.txt${llmsLangQuery}`,
|
|
551
588
|
className: "fd-agent-llms-directive",
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
589
|
+
"data-visible-in-header": showLlmsInHeader ? "true" : void 0,
|
|
590
|
+
style: showLlmsInHeader ? void 0 : agentLlmsDirectiveStyle,
|
|
591
|
+
tabIndex: showLlmsInHeader ? void 0 : -1,
|
|
592
|
+
"aria-hidden": showLlmsInHeader ? void 0 : true,
|
|
593
|
+
children: showLlmsInHeader ? "LLMS.TXT" : "llms.txt"
|
|
556
594
|
}, "llms-txt"),
|
|
557
595
|
titleControlsPortal,
|
|
558
596
|
tocActionsPortal,
|
|
@@ -568,7 +606,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
568
606
|
style: fdTocStyle
|
|
569
607
|
},
|
|
570
608
|
breadcrumb: { enabled: false },
|
|
571
|
-
footer: { enabled:
|
|
609
|
+
footer: { enabled: false },
|
|
572
610
|
children: [
|
|
573
611
|
effectiveBreadcrumbEnabled && /* @__PURE__ */ jsx(PathBreadcrumb, {
|
|
574
612
|
pathname,
|
|
@@ -604,11 +642,12 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
604
642
|
flexDirection: "column"
|
|
605
643
|
},
|
|
606
644
|
children: [
|
|
645
|
+
generatedPageHeader,
|
|
607
646
|
/* @__PURE__ */ jsx("div", {
|
|
608
647
|
style: { flex: 1 },
|
|
609
648
|
children: renderedChildren
|
|
610
649
|
}, "content"),
|
|
611
|
-
titleDecorationsFallback,
|
|
650
|
+
!generatedPageHeader && titleDecorationsFallback,
|
|
612
651
|
titleDecorationsPortal,
|
|
613
652
|
!isChangelogRoute && feedbackEnabled && /* @__PURE__ */ jsx(DocsFeedback, {
|
|
614
653
|
pathname: normalizedPath,
|
package/dist/mdx.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { HoverLink } from "./hover-link.mjs";
|
|
|
5
5
|
import { extractPromptText } from "./prompt-text.mjs";
|
|
6
6
|
import { Prompt } from "./prompt.mjs";
|
|
7
7
|
import React from "react";
|
|
8
|
-
import { resolveDocsAudienceExposure } from "@farming-labs/docs";
|
|
8
|
+
import { resolveDocsAudienceExposure } from "@farming-labs/docs/browser";
|
|
9
9
|
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
10
10
|
import { CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger } from "fumadocs-ui/components/codeblock";
|
|
11
11
|
import defaultMdxComponents from "fumadocs-ui/mdx";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/open-docs-provider-icons.ts
|
|
2
|
+
/** Monochrome provider marks used by the built-in Open in… presets. */
|
|
3
|
+
const OPEN_DOCS_PROVIDER_ICONS = {
|
|
4
|
+
chatgpt: "<svg viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M11.248 18.25q-.825 0-1.568-.314a4.3 4.3 0 0 1-1.32-.874 4 4 0 0 1-1.304.214 4 4 0 0 1-2.046-.544 4.27 4.27 0 0 1-1.518-1.485 4 4 0 0 1-.56-2.095q0-.48.131-1.04A4.4 4.4 0 0 1 2.04 10.71a4.07 4.07 0 0 1 .017-3.4 4.2 4.2 0 0 1 1.056-1.418 3.8 3.8 0 0 1 1.6-.842 3.9 3.9 0 0 1 .76-1.683q.593-.759 1.451-1.188a4.04 4.04 0 0 1 1.832-.429q.825 0 1.567.313.742.314 1.32.875a4 4 0 0 1 1.304-.215q1.106 0 2.046.545a4.14 4.14 0 0 1 1.501 1.485q.578.941.578 2.095 0 .48-.132 1.04.66.61 1.023 1.419.363.792.363 1.666 0 .892-.38 1.717a4.3 4.3 0 0 1-1.072 1.435 3.8 3.8 0 0 1-1.584.825 3.8 3.8 0 0 1-.775 1.683 4.06 4.06 0 0 1-1.436 1.188 4.04 4.04 0 0 1-1.832.429m-4.076-2.062q.825 0 1.435-.347l3.103-1.782a.36.36 0 0 0 .164-.313v-1.42L7.881 14.62a.67.67 0 0 1-.726 0l-3.118-1.798a.5.5 0 0 1-.017.115v.198q0 .841.396 1.551.413.693 1.139 1.089a3.2 3.2 0 0 0 1.617.412m.165-2.69a.4.4 0 0 0 .181.05q.083 0 .165-.05l1.238-.71-3.977-2.31a.7.7 0 0 1-.363-.643v-3.58q-.825.362-1.32 1.122a2.9 2.9 0 0 0-.495 1.65q0 .809.413 1.55.412.743 1.072 1.123zm3.91 3.663q.875 0 1.585-.396a2.96 2.96 0 0 0 1.534-2.64v-3.564a.32.32 0 0 0-.165-.297l-1.254-.726v4.604a.7.7 0 0 1-.363.643l-3.119 1.799a3 3 0 0 0 1.783.577m.627-6.039V8.878L10.01 7.822 8.129 8.878v2.244l1.881 1.056zM7.057 5.859a.7.7 0 0 1 .363-.644l3.119-1.798a3 3 0 0 0-1.782-.578q-.874 0-1.584.396A2.96 2.96 0 0 0 6.05 4.324a3.07 3.07 0 0 0-.396 1.551v3.547q0 .199.165.314l1.237.726zm8.383 7.887q.825-.364 1.303-1.123.495-.758.495-1.65a3.15 3.15 0 0 0-.412-1.55q-.413-.743-1.073-1.123l-3.086-1.782q-.099-.065-.181-.049a.3.3 0 0 0-.165.05l-1.238.692 3.993 2.327a.6.6 0 0 1 .264.264.64.64 0 0 1 .1.363zm-3.317-8.382a.63.63 0 0 1 .726 0l3.135 1.831v-.297q0-.792-.396-1.501a2.86 2.86 0 0 0-1.105-1.155q-.71-.43-1.65-.43-.825 0-1.436.347L8.294 5.941a.36.36 0 0 0-.165.314v1.418z\"/></svg>",
|
|
5
|
+
claude: "<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z\"/></svg>",
|
|
6
|
+
cursor: "<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M11.503.131 1.891 5.678a.84.84 0 0 0-.42.726v11.188c0 .3.162.575.42.724l9.609 5.55a1 1 0 0 0 .998 0l9.61-5.55a.84.84 0 0 0 .42-.724V6.404a.84.84 0 0 0-.42-.726L12.497.131a1.01 1.01 0 0 0-.996 0M2.657 6.338h18.55c.263 0 .43.287.297.515L12.23 22.918c-.062.107-.229.064-.229-.06V12.335a.59.59 0 0 0-.295-.51l-9.11-5.257c-.109-.063-.064-.23.061-.23\"/></svg>",
|
|
7
|
+
gemini: "<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81\"/></svg>",
|
|
8
|
+
copilot: "<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M23.922 16.997C23.061 18.492 18.063 22.02 12 22.02 5.937 22.02.939 18.492.078 16.997A.641.641 0 0 1 0 16.741v-2.869a.883.883 0 0 1 .053-.22c.372-.935 1.347-2.292 2.605-2.656.167-.429.414-1.055.644-1.517a10.098 10.098 0 0 1-.052-1.086c0-1.331.282-2.499 1.132-3.368.397-.406.89-.717 1.474-.952C7.255 2.937 9.248 1.98 11.978 1.98c2.731 0 4.767.957 6.166 2.093.584.235 1.077.546 1.474.952.85.869 1.132 2.037 1.132 3.368 0 .368-.014.733-.052 1.086.23.462.477 1.088.644 1.517 1.258.364 2.233 1.721 2.605 2.656a.841.841 0 0 1 .053.22v2.869a.641.641 0 0 1-.078.256Zm-11.75-5.992h-.344a4.359 4.359 0 0 1-.355.508c-.77.947-1.918 1.492-3.508 1.492-1.725 0-2.989-.359-3.782-1.259a2.137 2.137 0 0 1-.085-.104L4 11.746v6.585c1.435.779 4.514 2.179 8 2.179 3.486 0 6.565-1.4 8-2.179v-6.585l-.098-.104s-.033.045-.085.104c-.793.9-2.057 1.259-3.782 1.259-1.59 0-2.738-.545-3.508-1.492a4.359 4.359 0 0 1-.355-.508Zm2.328 3.25c.549 0 1 .451 1 1v2c0 .549-.451 1-1 1-.549 0-1-.451-1-1v-2c0-.549.451-1 1-1Zm-5 0c.549 0 1 .451 1 1v2c0 .549-.451 1-1 1-.549 0-1-.451-1-1v-2c0-.549.451-1 1-1Zm3.313-6.185c.136 1.057.403 1.913.878 2.497.442.544 1.134.938 2.344.938 1.573 0 2.292-.337 2.657-.751.384-.435.558-1.15.558-2.361 0-1.14-.243-1.847-.705-2.319-.477-.488-1.319-.862-2.824-1.025-1.487-.161-2.192.138-2.533.529-.269.307-.437.808-.438 1.578v.021c0 .265.021.562.063.893Zm-1.626 0c.042-.331.063-.628.063-.894v-.02c-.001-.77-.169-1.271-.438-1.578-.341-.391-1.046-.69-2.533-.529-1.505.163-2.347.537-2.824 1.025-.462.472-.705 1.179-.705 2.319 0 1.211.175 1.926.558 2.361.365.414 1.084.751 2.657.751 1.21 0 1.902-.394 2.344-.938.475-.584.742-1.44.878-2.497Z\"/></svg>",
|
|
9
|
+
perplexity: "<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M22.3977 7.0896h-2.3106V.0676l-7.5094 6.3542V.1577h-1.1554v6.1966L4.4904 0v7.0896H1.6023v10.3976h2.8882V24l6.932-6.3591v6.2005h1.1554v-6.0469l6.9318 6.1807v-6.4879h2.8882V7.0896zm-3.4657-4.531v4.531h-5.355l5.355-4.531zm-13.2862.0676 4.8691 4.4634H5.6458V2.6262zM2.7576 16.332V8.245h7.8476l-6.1149 6.1147v1.9723H2.7576zm2.8882 5.0404v-3.8852h.0001v-2.6488l5.7763-5.7764v7.0111l-5.7764 5.2993zm12.7086.0248-5.7766-5.1509V9.0618l5.7766 5.7766v6.5588zm2.8882-5.0652h-1.733v-1.9723L13.3948 8.245h7.8478v8.087z\"/></svg>",
|
|
10
|
+
github: "<svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"/></svg>"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { OPEN_DOCS_PROVIDER_ICONS };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { OPEN_DOCS_PROVIDER_ICONS } from "./open-docs-provider-icons.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/open-docs-providers.ts
|
|
2
4
|
const PROMPT_PROVIDER_TEMPLATES = {
|
|
3
5
|
chatgpt: "https://chatgpt.com/?q={prompt}",
|
|
@@ -10,36 +12,43 @@ const PROMPT_PROVIDER_TEMPLATES = {
|
|
|
10
12
|
const OPEN_DOCS_PROVIDER_PRESETS = {
|
|
11
13
|
chatgpt: {
|
|
12
14
|
name: "ChatGPT",
|
|
15
|
+
iconHtml: OPEN_DOCS_PROVIDER_ICONS.chatgpt,
|
|
13
16
|
urlTemplate: "https://chatgpt.com/?q={prompt}",
|
|
14
17
|
promptUrlTemplate: PROMPT_PROVIDER_TEMPLATES.chatgpt
|
|
15
18
|
},
|
|
16
19
|
claude: {
|
|
17
20
|
name: "Claude",
|
|
21
|
+
iconHtml: OPEN_DOCS_PROVIDER_ICONS.claude,
|
|
18
22
|
urlTemplate: "https://claude.ai/new?q={prompt}",
|
|
19
23
|
promptUrlTemplate: PROMPT_PROVIDER_TEMPLATES.claude
|
|
20
24
|
},
|
|
21
25
|
cursor: {
|
|
22
26
|
name: "Cursor",
|
|
27
|
+
iconHtml: OPEN_DOCS_PROVIDER_ICONS.cursor,
|
|
23
28
|
urlTemplate: "https://cursor.com/link/prompt?text={prompt}",
|
|
24
29
|
promptUrlTemplate: PROMPT_PROVIDER_TEMPLATES.cursor
|
|
25
30
|
},
|
|
26
31
|
gemini: {
|
|
27
32
|
name: "Gemini",
|
|
33
|
+
iconHtml: OPEN_DOCS_PROVIDER_ICONS.gemini,
|
|
28
34
|
urlTemplate: "https://gemini.google.com/app?q={prompt}",
|
|
29
35
|
promptUrlTemplate: PROMPT_PROVIDER_TEMPLATES.gemini
|
|
30
36
|
},
|
|
31
37
|
copilot: {
|
|
32
38
|
name: "Copilot",
|
|
39
|
+
iconHtml: OPEN_DOCS_PROVIDER_ICONS.copilot,
|
|
33
40
|
urlTemplate: "https://github.com/copilot?prompt={prompt}",
|
|
34
41
|
promptUrlTemplate: PROMPT_PROVIDER_TEMPLATES.copilot
|
|
35
42
|
},
|
|
36
43
|
perplexity: {
|
|
37
44
|
name: "Perplexity",
|
|
45
|
+
iconHtml: OPEN_DOCS_PROVIDER_ICONS.perplexity,
|
|
38
46
|
urlTemplate: "https://www.perplexity.ai/search/?q={prompt}",
|
|
39
47
|
promptUrlTemplate: PROMPT_PROVIDER_TEMPLATES.perplexity
|
|
40
48
|
},
|
|
41
49
|
github: {
|
|
42
50
|
name: "GitHub",
|
|
51
|
+
iconHtml: OPEN_DOCS_PROVIDER_ICONS.github,
|
|
43
52
|
urlTemplate: "{githubUrl}",
|
|
44
53
|
promptUrlTemplate: "{githubUrl}",
|
|
45
54
|
target: "github"
|
|
@@ -48,6 +57,11 @@ const OPEN_DOCS_PROVIDER_PRESETS = {
|
|
|
48
57
|
function normalizeProviderName(name) {
|
|
49
58
|
return name.trim().toLowerCase();
|
|
50
59
|
}
|
|
60
|
+
function resolveOpenDocsProviderIcon(name) {
|
|
61
|
+
if (!name) return void 0;
|
|
62
|
+
const normalizedName = normalizeProviderName(name);
|
|
63
|
+
return OPEN_DOCS_PROVIDER_PRESETS[normalizedName === "github copilot" ? "copilot" : normalizedName]?.iconHtml;
|
|
64
|
+
}
|
|
51
65
|
function resolveOpenDocsProviders(providers, options = {}) {
|
|
52
66
|
if (!providers || providers.length === 0) return void 0;
|
|
53
67
|
const serialized = providers.map((provider) => resolveOpenDocsProvider(provider, options)).filter((provider) => provider !== void 0);
|
|
@@ -60,6 +74,7 @@ function resolveOpenDocsProvider(provider, options = {}) {
|
|
|
60
74
|
if (!preset) return void 0;
|
|
61
75
|
return {
|
|
62
76
|
name: preset.name,
|
|
77
|
+
iconHtml: preset.iconHtml,
|
|
63
78
|
urlTemplate: preset.urlTemplate,
|
|
64
79
|
promptUrlTemplate: preset.promptUrlTemplate,
|
|
65
80
|
target: preset.target ?? options.target,
|
|
@@ -75,11 +90,11 @@ function resolveOpenDocsProvider(provider, options = {}) {
|
|
|
75
90
|
name,
|
|
76
91
|
urlTemplate,
|
|
77
92
|
promptUrlTemplate: provider.promptUrlTemplate ?? cursorAppTemplate ?? preset?.promptUrlTemplate,
|
|
78
|
-
iconHtml: options.serializeIcon?.(provider.icon) ?? (typeof provider.icon === "string" ? provider.icon : void 0),
|
|
93
|
+
iconHtml: options.serializeIcon?.(provider.icon) ?? (typeof provider.icon === "string" ? provider.icon : void 0) ?? preset?.iconHtml,
|
|
79
94
|
target: provider.target ?? preset?.target ?? options.target ?? (hasCustomUrlTemplate ? "page" : void 0),
|
|
80
95
|
prompt: provider.prompt ?? options.prompt
|
|
81
96
|
};
|
|
82
97
|
}
|
|
83
98
|
|
|
84
99
|
//#endregion
|
|
85
|
-
export { resolveOpenDocsProviders };
|
|
100
|
+
export { resolveOpenDocsProviderIcon, resolveOpenDocsProviders };
|
package/dist/page-actions.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { emitClientAnalyticsEvent } from "./client-analytics.mjs";
|
|
4
|
+
import { resolveOpenDocsProviderIcon, resolveOpenDocsProviders } from "./open-docs-providers.mjs";
|
|
4
5
|
import { sanitizeIconHtml } from "./safe-icon-html.mjs";
|
|
5
6
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
7
|
import { usePathname } from "fumadocs-core/framework";
|
|
@@ -107,13 +108,7 @@ const SparklesIcon = () => /* @__PURE__ */ jsxs("svg", {
|
|
|
107
108
|
/* @__PURE__ */ jsx("path", { d: "M19 11.5 20 15l3.5 1-3.5 1-1 3.5-1-3.5-3.5-1 3.5-1Z" })
|
|
108
109
|
]
|
|
109
110
|
});
|
|
110
|
-
const DEFAULT_PROVIDERS = [
|
|
111
|
-
name: "ChatGPT",
|
|
112
|
-
urlTemplate: "https://chatgpt.com/?q={prompt}"
|
|
113
|
-
}, {
|
|
114
|
-
name: "Claude",
|
|
115
|
-
urlTemplate: "https://claude.ai/new?q={prompt}"
|
|
116
|
-
}];
|
|
111
|
+
const DEFAULT_PROVIDERS = resolveOpenDocsProviders(["chatgpt", "claude"]) ?? [];
|
|
117
112
|
const DEFAULT_OPEN_DOCS_TARGET = "markdown";
|
|
118
113
|
const DEFAULT_OPEN_DOCS_PROMPT = "Read this documentation: {url}";
|
|
119
114
|
function pageUrlToMarkdownUrl(pageUrl) {
|
|
@@ -328,7 +323,7 @@ function PageActions({ copyMarkdown, copyMarkdownFormat = "markdown", copyMarkdo
|
|
|
328
323
|
className: "fd-page-action-menu",
|
|
329
324
|
role: "menu",
|
|
330
325
|
children: resolvedProviders.map((provider) => {
|
|
331
|
-
const iconHtml = sanitizeIconHtml(provider.iconHtml);
|
|
326
|
+
const iconHtml = sanitizeIconHtml(provider.iconHtml ?? resolveOpenDocsProviderIcon(provider.name));
|
|
332
327
|
return /* @__PURE__ */ jsxs("button", {
|
|
333
328
|
type: "button",
|
|
334
329
|
role: "menuitem",
|
|
@@ -29,30 +29,30 @@ const PixelBorderUIDefaults = {
|
|
|
29
29
|
},
|
|
30
30
|
h1: {
|
|
31
31
|
size: "2.25rem",
|
|
32
|
-
weight:
|
|
33
|
-
lineHeight: "1.
|
|
32
|
+
weight: 400,
|
|
33
|
+
lineHeight: "1.14",
|
|
34
34
|
letterSpacing: "-0.02em"
|
|
35
35
|
},
|
|
36
36
|
h2: {
|
|
37
37
|
size: "1.5rem",
|
|
38
|
-
weight:
|
|
39
|
-
lineHeight: "1.
|
|
38
|
+
weight: 400,
|
|
39
|
+
lineHeight: "1.24",
|
|
40
40
|
letterSpacing: "-0.01em"
|
|
41
41
|
},
|
|
42
42
|
h3: {
|
|
43
43
|
size: "1.25rem",
|
|
44
|
-
weight:
|
|
45
|
-
lineHeight: "1.
|
|
44
|
+
weight: 400,
|
|
45
|
+
lineHeight: "1.3"
|
|
46
46
|
},
|
|
47
47
|
h4: {
|
|
48
48
|
size: "1.125rem",
|
|
49
|
-
weight:
|
|
49
|
+
weight: 400,
|
|
50
50
|
lineHeight: "1.4"
|
|
51
51
|
},
|
|
52
52
|
body: {
|
|
53
|
-
size: "
|
|
53
|
+
size: "0.975rem",
|
|
54
54
|
weight: 400,
|
|
55
|
-
lineHeight: "1.
|
|
55
|
+
lineHeight: "1.8"
|
|
56
56
|
},
|
|
57
57
|
small: {
|
|
58
58
|
size: "0.875rem",
|
|
@@ -63,12 +63,13 @@ const PixelBorderUIDefaults = {
|
|
|
63
63
|
layout: {
|
|
64
64
|
contentWidth: 860,
|
|
65
65
|
sidebarWidth: 286,
|
|
66
|
+
tocWidth: 240,
|
|
66
67
|
toc: {
|
|
67
68
|
enabled: true,
|
|
68
69
|
depth: 3
|
|
69
70
|
},
|
|
70
71
|
header: {
|
|
71
|
-
height:
|
|
72
|
+
height: 44,
|
|
72
73
|
sticky: true
|
|
73
74
|
}
|
|
74
75
|
},
|