mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
chore(vscode-ide-companion): rm markdown code copy button
This commit is contained in:
@@ -160,49 +160,6 @@
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-content .code-block-wrapper {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-content .code-block-wrapper pre {
|
|
||||||
padding-top: 1rem; /* Reduced padding - room for the button height */
|
|
||||||
padding-right: 2rem; /* Reduced padding - room for the button width */
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-content .code-block-wrapper .copy-button {
|
|
||||||
position: absolute;
|
|
||||||
top: 6px;
|
|
||||||
right: 6px;
|
|
||||||
padding: 2px 8px;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.6;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid var(--app-primary-border-color);
|
|
||||||
background-color: var(--app-primary-background, rgba(255, 255, 255, 0.1));
|
|
||||||
color: var(--app-secondary-foreground);
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 1;
|
|
||||||
opacity: 0; /* show on hover to reduce visual noise */
|
|
||||||
transition: opacity 100ms ease-in-out;
|
|
||||||
pointer-events: none; /* prevent blocking text selection */
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-content .code-block-wrapper:hover .copy-button,
|
|
||||||
.markdown-content .code-block-wrapper .copy-button:focus {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: auto; /* enable interaction when visible */
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-content .code-block-wrapper .copy-button:hover {
|
|
||||||
background-color: var(--app-list-hover-background, rgba(127, 127, 127, 0.2));
|
|
||||||
border-color: var(--app-input-active-border, rgba(97, 95, 255, 0.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-content .code-block-wrapper .copy-button:disabled {
|
|
||||||
opacity: 0.7;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.markdown-content pre code {
|
.markdown-content pre code {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@@ -46,46 +46,6 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({
|
|||||||
typographer: true,
|
typographer: true,
|
||||||
} as MarkdownItOptions);
|
} as MarkdownItOptions);
|
||||||
|
|
||||||
// Add syntax highlighting + a copy button for code blocks
|
|
||||||
md.use((md) => {
|
|
||||||
const renderWithCopy = (token: {
|
|
||||||
info: string;
|
|
||||||
content: string;
|
|
||||||
}): string => {
|
|
||||||
const lang = (token.info || 'plaintext').trim();
|
|
||||||
const content = token.content;
|
|
||||||
|
|
||||||
// Wrap in a container so we can position a copy button
|
|
||||||
return (
|
|
||||||
`<div class="code-block-wrapper">` +
|
|
||||||
`<button class="copy-button" data-lang="${md.utils.escapeHtml(lang)}" aria-label="Copy code block">Copy</button>` +
|
|
||||||
`<pre class="code-block language-${md.utils.escapeHtml(lang)}"><code class="language-${md.utils.escapeHtml(lang)}">${md.utils.escapeHtml(content)}</code></pre>` +
|
|
||||||
`</div>`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
md.renderer.rules.code_block = function (
|
|
||||||
tokens,
|
|
||||||
idx: number,
|
|
||||||
_options,
|
|
||||||
_env,
|
|
||||||
) {
|
|
||||||
const token = tokens[idx] as unknown as {
|
|
||||||
info: string;
|
|
||||||
content: string;
|
|
||||||
};
|
|
||||||
return renderWithCopy(token);
|
|
||||||
};
|
|
||||||
|
|
||||||
md.renderer.rules.fence = function (tokens, idx: number, _options, _env) {
|
|
||||||
const token = tokens[idx] as unknown as {
|
|
||||||
info: string;
|
|
||||||
content: string;
|
|
||||||
};
|
|
||||||
return renderWithCopy(token);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return md;
|
return md;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -288,7 +248,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({
|
|||||||
return container.innerHTML;
|
return container.innerHTML;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Event delegation: intercept clicks on copy buttons and generated file-path links
|
// Event delegation: intercept clicks on generated file-path links
|
||||||
const handleContainerClick = (
|
const handleContainerClick = (
|
||||||
e: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
e: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
||||||
) => {
|
) => {
|
||||||
@@ -297,34 +257,6 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle copy button clicks for fenced code blocks
|
|
||||||
const copyBtn = (target.closest &&
|
|
||||||
target.closest('button.copy-button')) as HTMLButtonElement | null;
|
|
||||||
if (copyBtn) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const wrapper = copyBtn.closest('.code-block-wrapper');
|
|
||||||
const codeEl = wrapper?.querySelector('pre code');
|
|
||||||
const text = codeEl?.textContent ?? '';
|
|
||||||
if (text) {
|
|
||||||
void navigator.clipboard.writeText(text);
|
|
||||||
// Quick feedback
|
|
||||||
const original = copyBtn.textContent || 'Copy';
|
|
||||||
copyBtn.textContent = 'Copied';
|
|
||||||
copyBtn.disabled = true;
|
|
||||||
setTimeout(() => {
|
|
||||||
copyBtn.textContent = original;
|
|
||||||
copyBtn.disabled = false;
|
|
||||||
}, 1200);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.warn('Copy failed:', err);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find nearest anchor with our marker class
|
// Find nearest anchor with our marker class
|
||||||
const anchor = (target.closest &&
|
const anchor = (target.closest &&
|
||||||
target.closest('a.file-path-link')) as HTMLAnchorElement | null;
|
target.closest('a.file-path-link')) as HTMLAnchorElement | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user