Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default async function Page(props: PageProps<"/docs/[[...slug]]">) {
)}
{page.path && (
<div className="flex flex-row gap-2 shrink-0">
<LLMCopyButton pagePath={page.path} />
<LLMCopyButton slugs={page.slugs} />
<ViewOptions pagePath={page.path} githubUrl={githubUrl} />
</div>
)}
Expand Down
27 changes: 11 additions & 16 deletions src/components/ai/page-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,33 @@ import { getMarkdownContent } from "@/lib/get-markdown-content";

const cache = new Map<string, string>();

// Helper function to normalize doc file paths to GitHub URL format
function normalizeDocPathForGithub(path: string): string {
let normalized = path.startsWith("content/") ? path : `content/${path}`;
if (!normalized.startsWith("content/docs/")) {
normalized = normalized.replace(/^content\//, "content/docs/");
}
return normalized;
}

export function LLMCopyButton({
/**
* The page path for fetching the raw Markdown/MDX content
* The page slugs for fetching the raw Markdown/MDX content
*/
pagePath,
slugs,
}: {
pagePath: string;
slugs: string[];
}) {
const [isLoading, setLoading] = useState(false);
const [checked, onClick] = useCopyButton(async () => {
try {
setLoading(true);
const cached = cache.get(pagePath);
const content = cached || (await getMarkdownContent(pagePath));
const cacheKey = slugs.join("/");
const cached = cache.get(cacheKey);
const content = cached || (await getMarkdownContent(slugs));

if (!cached) {
cache.set(pagePath, content);
cache.set(cacheKey, content);
}

await navigator.clipboard.writeText(content);
} catch (error) {
console.error("Failed to copy markdown to clipboard:", error);
window.alert("Failed to copy the markdown to your clipboard. Please copy it manually.");
const errorMessage = error instanceof Error ? error.message : String(error);
window.alert(
`Failed to copy the markdown to your clipboard: ${errorMessage}\n\nPlease copy it manually.`,
);
throw error;
} finally {
setLoading(false);
Expand Down
24 changes: 4 additions & 20 deletions src/lib/get-markdown-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,13 @@

import { source, getLLMText } from "./source";

export async function getMarkdownContent(pagePath: string): Promise<string> {
export async function getMarkdownContent(slugs: string[]): Promise<string> {
try {
// Get all pages from the source
const pages = source.getPages();

// Normalize the path - remove leading/trailing slashes and 'content/' prefix if present
let normalizedPath = pagePath.replace(/^\/|\/$/g, "").replace(/^content\//, "");

// Try to find a matching page
// page.path from Fumadocs is typically in the format 'docs/...' or similar
const candidates = [
normalizedPath,
normalizedPath.startsWith("docs/") ? normalizedPath : `docs/${normalizedPath}`,
];

let page;
for (const candidate of candidates) {
page = pages.find((p) => p.path === candidate);
if (page) break;
}
// Use slugs to get the page directly from the source
const page = source.getPage(slugs);

if (!page) {
throw new Error(`Page not found: ${pagePath}`);
throw new Error(`Page not found for slugs: ${slugs.join("/")}`);
}

// Get the formatted markdown content with metadata (title, URL, source, description)
Expand Down
Loading