Skip to main content
Glama
CopyAsMarkdown.tsx3.07 kB
import { CheckIcon, CopyIcon } from "@radix-ui/react-icons"; import clsx from "clsx"; import React, { useCallback, useState, useRef, useEffect } from "react"; import { toast } from "sonner"; import { useLocation } from "@docusaurus/router"; export function CopyAsMarkdown() { const [isCopied, setIsCopied] = useState(false); const [hasBeenCopied, setHasBeenCopied] = useState(false); const [markdownContent, setMarkdownContent] = useState<string | null>(null); const copyTimeout = useRef<number | undefined>(undefined); const location = useLocation(); const pathWithoutTrailingSlash = location.pathname.endsWith("/") ? location.pathname.slice(0, -1) : location.pathname; const markdownUrl = pathWithoutTrailingSlash === "/home" ? "/llms.txt" : `${pathWithoutTrailingSlash}.md`; useEffect(() => { const fetchMarkdown = async () => { setMarkdownContent(null); try { const response = await fetch(markdownUrl); if (!response.ok) { throw new Error( `Received non-OK Markdown response on ${markdownUrl}: ${response.status}`, ); } const content = await response.text(); setMarkdownContent(content); } catch (error) { console.error("Failed to fetch page as Markdown:", error); } }; void fetchMarkdown(); }, [markdownUrl]); const handleCopyAsMarkdown = useCallback(async () => { if (markdownContent === null) return; try { await navigator.clipboard.writeText(markdownContent); setIsCopied(true); setHasBeenCopied(true); copyTimeout.current = window.setTimeout(() => { setIsCopied(false); }, 2000); } catch (error) { toast.error("Can’t write to clipboard."); console.error("Failed to copy as Markdown:", error); } }, [markdownContent]); return ( <button type="button" className="font-[inherit] appearance-none bg-transparent border p-0 border-(--convex-breadcrumb-font-color)/50 hover:border-(--convex-breadcrumb-font-color)/80 rounded text-(--convex-breadcrumb-font-color) transition-colors cursor-pointer disabled:opacity-0 focus-visible:ring-2 focus-visible:ring-blue-500 focus:outline-none overflow-hidden relative" onClick={handleCopyAsMarkdown} disabled={markdownContent === null} {...(markdownContent === null && { inert: "inert" })} > <div className={clsx( "px-2 py-1 flex gap-1.5 items-center", hasBeenCopied && !isCopied && "animate-slideToTop", isCopied && "opacity-0", )} {...(isCopied && { inert: "inert" })} > <CopyIcon /> Copy as Markdown </div> <div className={clsx( "absolute inset-0 px-2 py-1 flex gap-1.5 items-center", isCopied && "animate-slideToTop", !isCopied && "opacity-0", )} {...(!isCopied && { inert: "inert" })} > <CheckIcon className="text-green-g3" /> Copied! </div> </button> ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/get-convex/convex-backend'

If you have feedback or need assistance with the MCP directory API, please join our Discord server