Copy code block

This commit is contained in:
andrepimenta
2025-07-09 13:46:32 +01:00
parent 234516c1ef
commit 4f5a4cb7ef
2 changed files with 101 additions and 4 deletions

View File

@@ -856,6 +856,59 @@ const styles = `
word-break: break-word;
}
/* Code block container and header */
.code-block-container {
margin: 8px 0;
border: 1px solid var(--vscode-panel-border);
border-radius: 4px;
background-color: var(--vscode-textCodeBlock-background);
overflow: hidden;
}
.code-block-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 4px 6px;
background-color: var(--vscode-editor-background);
border-bottom: 1px solid var(--vscode-panel-border);
font-size: 10px;
}
.code-block-language {
color: var(--vscode-descriptionForeground);
font-family: var(--vscode-editor-font-family);
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.code-copy-btn {
background: none;
border: none;
color: var(--vscode-descriptionForeground);
cursor: pointer;
padding: 4px;
border-radius: 3px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
opacity: 0.7;
}
.code-copy-btn:hover {
background-color: var(--vscode-list-hoverBackground);
opacity: 1;
}
.code-block-container .code-block {
margin: 0;
border: none;
border-radius: 0;
background: none;
}
/* Inline code */
.message-content code {
background-color: var(--vscode-textCodeBlock-background);

View File

@@ -1815,6 +1815,32 @@ const html = `<!DOCTYPE html>
});
}
}
function copyCodeBlock(codeId) {
const codeElement = document.getElementById(codeId);
if (codeElement) {
const rawCode = codeElement.getAttribute('data-raw-code');
if (rawCode) {
// Decode HTML entities
const decodedCode = rawCode.replace(/&quot;/g, '"').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');
navigator.clipboard.writeText(decodedCode).then(() => {
// Show temporary feedback
const copyBtn = codeElement.closest('.code-block-container').querySelector('.code-copy-btn');
if (copyBtn) {
const originalInnerHTML = copyBtn.innerHTML;
copyBtn.innerHTML = '<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>';
copyBtn.style.color = '#4caf50';
setTimeout(() => {
copyBtn.innerHTML = originalInnerHTML;
copyBtn.style.color = '';
}, 1000);
}
}).catch(err => {
console.error('Failed to copy code:', err);
});
}
}
}
window.addEventListener('message', event => {
const message = event.data;
@@ -2263,6 +2289,9 @@ const html = `<!DOCTYPE html>
// First, handle code blocks before line-by-line processing
let processedMarkdown = markdown;
// Store code blocks temporarily to protect them from further processing
const codeBlockPlaceholders = [];
// Handle multi-line code blocks with triple backticks
// Using RegExp constructor to avoid backtick conflicts in template literal
const codeBlockRegex = new RegExp('\\\`\\\`\\\`(\\\\w*)\\n([\\\\s\\\\S]*?)\\\`\\\`\\\`', 'g');
@@ -2277,7 +2306,16 @@ const html = `<!DOCTYPE html>
codeHtml += '<div class="code-line">' + escapedLine + '</div>';
}
return '\\n<pre class="code-block"><code class="language-' + language + '">' + codeHtml + '</code></pre>\\n';
// Create unique ID for this code block
const codeId = 'code_' + Math.random().toString(36).substr(2, 9);
const escapedCode = escapeHtml(code);
const codeBlockHtml = '<div class="code-block-container"><div class="code-block-header"><span class="code-block-language">' + language + '</span><button class="code-copy-btn" onclick="copyCodeBlock(\\\'' + codeId + '\\\')" title="Copy code"><svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></div><pre class="code-block"><code class="language-' + language + '" id="' + codeId + '" data-raw-code="' + escapedCode.replace(/"/g, '&quot;') + '">' + codeHtml + '</code></pre></div>';
// Store the code block and return a placeholder
const placeholder = '__CODEBLOCK_' + codeBlockPlaceholders.length + '__';
codeBlockPlaceholders.push(codeBlockHtml);
return placeholder;
});
// Handle inline code with single backticks
@@ -2292,9 +2330,9 @@ const html = `<!DOCTYPE html>
for (let line of lines) {
line = line.trim();
// Check if this is a code block
if (line.includes('<pre class="code-block"><code')) {
// This is a complete code block on potentially multiple lines
// Check if this is a code block placeholder
if (line.startsWith('__CODEBLOCK_') && line.endsWith('__')) {
// This is a code block placeholder, don't process it
html += line;
continue;
}
@@ -2363,6 +2401,12 @@ const html = `<!DOCTYPE html>
if (inUnorderedList) html += '</ul>';
if (inOrderedList) html += '</ol>';
// Restore code block placeholders
for (let i = 0; i < codeBlockPlaceholders.length; i++) {
const placeholder = '__CODEBLOCK_' + i + '__';
html = html.replace(placeholder, codeBlockPlaceholders[i]);
}
return html;
}