Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.claude
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "docusaurus-plugin-copy-page-button",
"version": "0.4.2",
"version": "0.5.0",
"description": "Docusaurus plugin that adds a copy page button to extract documentation content as markdown for AI tools like ChatGPT, Claude, and Gemini",
"main": "src/index.js",
"keywords": [
Expand Down
109 changes: 108 additions & 1 deletion src/CopyPageButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ const separatePositioningStyles = (styleObject = {}) => {

export default function CopyPageButton({
customStyles = {},
enabledActions = ['copy', 'view', 'chatgpt', 'claude', 'gemini']
enabledActions = ['copy', 'view', 'chatgpt', 'claude', 'perplexity', 'gemini', 'mcp-copy', 'mcp-cursor', 'mcp-vscode'],
mcpServer = null
}) {
const [isOpen, setIsOpen] = useState(false);
const [pageContent, setPageContent] = useState("");
Expand Down Expand Up @@ -423,6 +424,34 @@ Please provide a clear summary and help me understand the key concepts covered i
}
};

const buildCursorMcpUrl = () => {
if (!mcpServer) return null;
const config = JSON.stringify({ name: mcpServer.name, url: mcpServer.url });
const encodedConfig = btoa(config);
return `cursor://anysphere.cursor-deeplink/mcp/install?name=${encodeURIComponent(mcpServer.name)}&config=${encodeURIComponent(encodedConfig)}`;
};

const buildVscodeMcpUrl = () => {
if (!mcpServer) return null;
const config = JSON.stringify({ name: mcpServer.name, url: mcpServer.url });
return `vscode:mcp/install?${encodeURIComponent(config)}`;
};

const copyMcpConfig = async () => {
if (!mcpServer) return;
await copyToClipboard(mcpServer.url);
};

const openInCursor = () => {
const url = buildCursorMcpUrl();
if (url) window.open(url, "_self");
};

const openInVscode = () => {
const url = buildVscodeMcpUrl();
if (url) window.open(url, "_self");
};

const allDropdownItems = [
{
id: "copy",
Expand Down Expand Up @@ -503,6 +532,23 @@ Please provide a clear summary and help me understand the key concepts covered i
),
action: () => openInAI("https://claude.ai/new"),
},
{
id: "perplexity",
title: "Open in Perplexity",
description: "Ask questions about this page",
icon: (
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M22 12.2H13.4V3.7l-1.4 1.2V12.2H3.4l8.6 7.5V22h1.4v-2.3l8.6-7.5zM12 18.3 5.7 13h6.3v5.3zm1.4 0V13h5.9l-5.9 5.3zM12 10.7V5.6l5.7 5.1H12zm-1.4 0H4.3L10 5.6v5.1z"/>
</svg>
),
action: () => openInAI("https://www.perplexity.ai/search", "q"),
},
{
id: "gemini",
title: "Open in Gemini",
Expand All @@ -523,6 +569,67 @@ Please provide a clear summary and help me understand the key concepts covered i
),
action: () => openInAI("https://gemini.google.com/guided-learning", "query"),
},
...(mcpServer ? [
{
id: "mcp-copy",
title: "Copy MCP Server",
description: "Copy MCP Server URL to clipboard",
icon: (
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
</svg>
),
action: copyMcpConfig,
},
{
id: "mcp-cursor",
title: "Connect to Cursor",
description: "Install MCP Server on Cursor",
icon: (
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M12 2L2 7l10 5 10-5-10-5z"></path>
<path d="M2 17l10 5 10-5"></path>
<path d="M2 12l10 5 10-5"></path>
</svg>
),
action: openInCursor,
},
{
id: "mcp-vscode",
title: "Connect to VS Code",
description: "Install MCP Server on VS Code",
icon: (
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M23.15 2.587L18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 19.88V4.12a1.5 1.5 0 0 0-.85-1.533zm-5.146 14.861L10.826 12l7.178-5.448v10.896z"/>
</svg>
),
action: openInVscode,
},
] : []),
];

// Filter dropdown items based on enabled actions
Expand Down
9 changes: 6 additions & 3 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ if (ExecutionEnvironment.canUseDOM) {
const renderOptions = getPluginOptions();
root.render(React.createElement(CopyPageButton, {
customStyles: renderOptions.customStyles,
enabledActions: renderOptions.enabledActions
enabledActions: renderOptions.enabledActions,
mcpServer: renderOptions.mcpServer
}));
};

Expand Down Expand Up @@ -141,7 +142,8 @@ if (ExecutionEnvironment.canUseDOM) {
const renderOptions = getPluginOptions();
root.render(React.createElement(CopyPageButton, {
customStyles: renderOptions.customStyles,
enabledActions: renderOptions.enabledActions
enabledActions: renderOptions.enabledActions,
mcpServer: renderOptions.mcpServer
}));
};

Expand Down Expand Up @@ -218,7 +220,8 @@ if (ExecutionEnvironment.canUseDOM) {
const renderOptions = getPluginOptions();
root.render(React.createElement(CopyPageButton, {
customStyles: renderOptions.customStyles,
enabledActions: renderOptions.enabledActions
enabledActions: renderOptions.enabledActions,
mcpServer: renderOptions.mcpServer
}));

// Reset injection attempts on successful injection
Expand Down
4 changes: 3 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ const path = require("path");
module.exports = function copyPageButtonPlugin(context, options = {}) {
const {
customStyles = {},
enabledActions = ['copy', 'view', 'chatgpt', 'claude', 'gemini'],
enabledActions = ['copy', 'view', 'chatgpt', 'claude', 'perplexity', 'gemini', 'mcp-copy', 'mcp-cursor', 'mcp-vscode'],
mcpServer = null,
...otherOptions
} = options;

Expand All @@ -23,6 +24,7 @@ module.exports = function copyPageButtonPlugin(context, options = {}) {
window.__COPY_PAGE_BUTTON_OPTIONS__ = ${JSON.stringify({
customStyles,
enabledActions,
mcpServer,
...otherOptions
})};
`
Expand Down