spwotton's picture
im still geting the config error and site isnt live
3a1d448 verified
Raw
History Blame Contribute Delete
6.93 kB
class CodeSnippet extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
static get observedAttributes() {
return ['language', 'filename', 'code'];
}
connectedCallback() {
this.render();
}
highlightSyntax(code) {
// Simple syntax highlighting
return code
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/(".*?")/g, '<span class="syntax-string">$1</span>')
.replace(/('.*?')/g, '<span class="syntax-string">$1</span>')
.replace(/\b(def|class|import|from|if|else|elif|for|while|return|yield|try|except|finally|with|as|pass|break|continue|lambda|None|True|False)\b/g, '<span class="syntax-keyword">$1</span>')
.replace(/\b(\d+\.?\d*)\b/g, '<span class="syntax-number">$1</span>')
.replace(/(#.*$)/gm, '<span class="syntax-comment">$1</span>')
.replace(/\b([A-Z][a-zA-Z0-9_]*)\b/g, '<span class="syntax-class">$1</span>')
.replace(/\b([a-z_][a-zA-Z0-9_]*)(?=\()/g, '<span class="syntax-function">$1</span>');
}
render() {
const language = this.getAttribute('language') || 'python';
const filename = this.getAttribute('filename') || 'code.py';
const rawCode = this.getAttribute('code') || '';
const highlightedCode = this.highlightSyntax(rawCode);
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
margin: 1rem 0;
}
.code-container {
background: #1e1e1e;
border: 1px solid #2d2d2d;
border-radius: 0.75rem;
overflow: hidden;
font-family: 'Roboto Mono', 'Consolas', 'Monaco', monospace;
}
.code-header {
background: #2d2d2d;
border-bottom: 1px solid #3d3d3d;
padding: 0.75rem 1rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.file-info {
display: flex;
align-items: center;
gap: 0.5rem;
color: #9aa0a6;
font-size: 0.875rem;
}
.language-badge {
padding: 0.25rem 0.75rem;
background: rgba(66, 133, 244, 0.15);
color: #8ab4f8;
border-radius: 0.25rem;
font-size: 0.75rem;
font-weight: 500;
text-transform: uppercase;
font-family: 'Roboto Mono', monospace;
}
.copy-btn {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
background: #3d3d3d;
border: 1px solid #4d4d4d;
border-radius: 0.5rem;
color: #e8eaed;
font-size: 0.875rem;
cursor: pointer;
transition: all 0.2s;
font-family: 'Roboto', sans-serif;
}
.copy-btn:hover {
background: #4d4d4d;
border-color: #5f6368;
}
.copy-btn.copied {
background: rgba(52, 168, 83, 0.2);
border-color: #34A853;
color: #81c995;
}
.code-content {
padding: 1.5rem;
overflow-x: auto;
line-height: 1.6;
font-size: 0.875rem;
color: #e8eaed;
}
.syntax-keyword { color: #c586c0; }
.syntax-string { color: #ce9178; }
.syntax-comment { color: #6a9955; font-style: italic; }
.syntax-function { color: #dcdcaa; }
.syntax-number { color: #b5cea8; }
.syntax-class { color: #4ec9b0; }
@media (max-width: 640px) {
.code-content {
font-size: 0.75rem;
padding: 1rem;
}
}
</style>
<div class="code-container">
<div class="code-header">
<div class="file-info">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>
<span>${filename}</span>
</div>
<div style="display: flex; align-items: center; gap: 0.75rem;">
<span class="language-badge">${language}</span>
<button class="copy-btn" id="copyBtn">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
<span>Copy</span>
`;
}, 2000);
});
});
}
}
customElements.define('code-snippet', CodeSnippet);
="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
<span>Copy</span>
</button>
</div>
</div>
<pre class="code-content"><code>${highlightedCode}</code></pre>
</div>
`;
// Copy functionality
const copyBtn = this.shadowRoot.getElementById('copyBtn');
copyBtn.addEventListener('click', () => {
navigator.clipboard.writeText(rawCode).then(() => {
copyBtn.classList.add('copied');
copyBtn.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
<span>Copied!</span>
`;
setTimeout(() => {
copyBtn.classList.remove('copied');
copyBtn.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d