diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e12e69..2fb34cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## Unreleased +### Added + +- `copy-link` action — copies a link to the current page's Markdown (`.md`) URL to the clipboard. It resolves the same URL the "Open in …" AI actions use (honouring `markdownUrl` / `generateMarkdownRoutes`), so on sites that serve per-page markdown it copies the `.md` link instead of the HTML page URL. Enabled by default; configurable via `enabledActions` and `labels.copyLink`. + ## 0.8.3 — 2026-06-17 ### Fixed diff --git a/README.md b/README.md index 566d272..24d1b65 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,7 @@ module.exports = { **Available actions:** - `'copy'` - Copy page as Markdown - `'view'` - View as Markdown in new tab +- `'copy-link'` - Copy a link to the page's Markdown (`.md`) URL - `'chatgpt'` - Open in ChatGPT - `'claude'` - Open in Claude - `'perplexity'` - Open in Perplexity @@ -225,7 +226,7 @@ module.exports = { - `'mcp-cursor'` - Install MCP server in Cursor (shown when `mcpServer` is configured) - `'mcp-vscode'` - Install MCP server in VS Code (shown when `mcpServer` is configured) -**Default:** Standard actions are enabled: `['copy', 'view', 'chatgpt', 'claude', 'perplexity', 'gemini']`. MCP actions are enabled automatically only when `mcpServer` is configured. +**Default:** Standard actions are enabled: `['copy', 'view', 'copy-link', 'chatgpt', 'claude', 'perplexity', 'gemini']`. MCP actions are enabled automatically only when `mcpServer` is configured. **Example configurations:** @@ -237,7 +238,7 @@ enabledActions: ['copy'] enabledActions: ['copy', 'view'] // All standard AI actions (default) -enabledActions: ['copy', 'view', 'chatgpt', 'claude', 'perplexity', 'gemini'] +enabledActions: ['copy', 'view', 'copy-link', 'chatgpt', 'claude', 'perplexity', 'gemini'] ``` ### MCP server actions @@ -440,6 +441,7 @@ Available translation IDs: | `copyPageButton.button.label` | `Copy page` (visible button text) | | `copyPageButton.copy.title` / `.description` | `Copy page` / `Copy the page as Markdown for LLMs` | | `copyPageButton.view.title` / `.description` | `View as Markdown` / `View this page as plain text` | +| `copyPageButton.copyLink.title` / `.description` | `Copy link to Markdown` / `Copy this page's .md URL` | | `copyPageButton.chatgpt.title` / `.description` | `Open in ChatGPT` / `Ask questions about this page` | | `copyPageButton.claude.title` / `.description` | `Open in Claude` / `Ask questions about this page` | | `copyPageButton.perplexity.title` / `.description` | `Open in Perplexity` / `Ask questions about this page` | diff --git a/index.d.ts b/index.d.ts index 29875c3..508ec5f 100644 --- a/index.d.ts +++ b/index.d.ts @@ -3,6 +3,7 @@ import type {CSSProperties} from 'react'; type ActionId = | 'copy' | 'view' + | 'copy-link' | 'chatgpt' | 'claude' | 'perplexity' @@ -38,6 +39,7 @@ export type CopyPageButtonLabels = { button?: {label?: string}; copy?: LabelGroup; view?: LabelGroup; + copyLink?: LabelGroup; chatgpt?: LabelGroup; claude?: LabelGroup; perplexity?: LabelGroup; diff --git a/react.d.ts b/react.d.ts index 12c22e6..8fd8a11 100644 --- a/react.d.ts +++ b/react.d.ts @@ -3,6 +3,7 @@ import type {ComponentType, CSSProperties} from 'react'; type ActionId = | 'copy' | 'view' + | 'copy-link' | 'chatgpt' | 'claude' | 'perplexity' @@ -38,6 +39,7 @@ export type CopyPageButtonLabels = { button?: {label?: string}; copy?: LabelGroup; view?: LabelGroup; + copyLink?: LabelGroup; chatgpt?: LabelGroup; claude?: LabelGroup; perplexity?: LabelGroup; diff --git a/src/CopyPageButton.js b/src/CopyPageButton.js index 4e744c7..2183a75 100644 --- a/src/CopyPageButton.js +++ b/src/CopyPageButton.js @@ -6,7 +6,7 @@ const { getMarkdownRouteUrl, } = require("./htmlToMarkdown"); -const DEFAULT_ACTIONS = ['copy', 'view', 'chatgpt', 'claude', 'perplexity', 'gemini']; +const DEFAULT_ACTIONS = ['copy', 'view', 'copy-link', 'chatgpt', 'claude', 'perplexity', 'gemini']; const DEFAULT_MCP_ACTIONS = ['mcp-copy', 'mcp-cursor', 'mcp-vscode']; const POSITIONING_PROPS = ['position', 'top', 'right', 'bottom', 'left', 'zIndex', 'transform']; const DROPDOWN_WIDTH = 300; @@ -241,6 +241,16 @@ export default function CopyPageButton({ return generateMarkdownRoutes ? getMarkdownRouteUrl(pageUrl) : pageUrl; }; + // Copy a link to the current page's markdown to the clipboard. Resolves the + // same URL the "Open in ChatGPT/Claude/…" actions reference, so on sites that + // serve per-page markdown this copies the `.md` link rather than the HTML one. + const copyMarkdownLink = async () => { + if (typeof window === "undefined") { + return; + } + await writeTextToClipboard(resolveContextUrl(window.location.href)); + }; + // Notify host-site analytics whenever a dropdown action runs, so maintainers // can measure how the button is used. Pairs with the `data-copy-page-action` // attributes for sites that prefer delegated DOM listeners. @@ -409,6 +419,25 @@ Please provide a clear summary and help me understand the key concepts covered i ), action: viewAsMarkdown, }, + { + id: "copy-link", + title: t("copyLink", "title", "Copy link to Markdown"), + description: t("copyLink", "description", "Copy this page's .md URL"), + icon: ( + + + + + ), + action: copyMarkdownLink, + }, { id: "chatgpt", title: t("chatgpt", "title", "Open in ChatGPT"),