Code Snippets

collect, organize & retrieve code fragments // localStorage persistence

snippets: 0 languages: 0
New Snippet
\n\n', created: Date.now() - 4000 }, { id: genId(), title: 'Bash Find and Replace', language: 'bash', tags: ['cli', 'text', 'utility'], code: '# Find files containing a pattern\ngrep -rl "old_text" ./src/\n\n# Replace in all matching files\nfind ./src -name "*.js" -exec \\\n sed -i \'s/old_text/new_text/g\' {} +\n\n# Preview changes first (dry run)\ngrep -rn "old_text" ./src/', created: Date.now() - 5000 }, { id: genId(), title: 'SQL Join Example', language: 'sql', tags: ['database', 'query', 'join'], code: 'SELECT\n u.name,\n u.email,\n COUNT(o.id) AS order_count,\n COALESCE(SUM(o.total), 0) AS total_spent\nFROM users u\nLEFT JOIN orders o ON o.user_id = u.id\nWHERE u.created_at >= \'2024-01-01\'\nGROUP BY u.id, u.name, u.email\nHAVING COUNT(o.id) > 0\nORDER BY total_spent DESC\nLIMIT 20;', created: Date.now() - 6000 }, { id: genId(), title: 'Rust Error Handling', language: 'rust', tags: ['error', 'result', 'pattern'], code: 'use std::fs;\nuse std::io;\n\nfn read_config(path: &str) -> Result {\n let content = fs::read_to_string(path)?;\n if content.is_empty() {\n return Err(io::Error::new(\n io::ErrorKind::InvalidData,\n "Config file is empty",\n ));\n }\n Ok(content)\n}\n\nfn main() {\n match read_config("config.toml") {\n Ok(cfg) => println!("Config: {}", cfg),\n Err(e) => eprintln!("Error: {}", e),\n }\n}', created: Date.now() - 7000 }, ]; } // --- Rendering --- function getAllTags() { const tags = {}; snippets.forEach(s => (s.tags || []).forEach(t => { tags[t] = (tags[t] || 0) + 1; })); return tags; } function getAllLangs() { const langs = new Set(); snippets.forEach(s => langs.add(s.language)); return [...langs].sort(); } function render() { const search = document.getElementById('csSearch').value.toLowerCase(); const langFilter = document.getElementById('csLangFilter').value; let filtered = snippets.filter(s => { if (langFilter && s.language !== langFilter) return false; if (activeTag && !(s.tags || []).includes(activeTag)) return false; if (search) { const haystack = (s.title + ' ' + (s.tags || []).join(' ') + ' ' + s.language).toLowerCase(); if (!haystack.includes(search)) return false; } return true; }); filtered.sort((a, b) => b.created - a.created); // Stats document.getElementById('csCount').textContent = snippets.length; document.getElementById('csLangCount').textContent = getAllLangs().length; // Language filter dropdown const langSelect = document.getElementById('csLangFilter'); const curLang = langSelect.value; const langs = getAllLangs(); langSelect.innerHTML = '' + langs.map(l => '').join(''); // Tag cloud const tags = getAllTags(); const tagCloud = document.getElementById('csTagCloud'); const sortedTags = Object.entries(tags).sort((a,b) => b[1] - a[1]); tagCloud.innerHTML = sortedTags.map(([t, c]) => '' + escHtml(t) + ' (' + c + ')' ).join(''); // Snippet list const list = document.getElementById('csList'); if (!filtered.length) { list.innerHTML = '
No snippets found. Add one or adjust your filters.
'; return; } list.innerHTML = filtered.map(s => { const tagsHtml = (s.tags || []).map(t => '' + escHtml(t) + '').join(''); return '
' + '
' + '

' + escHtml(s.title) + '

' + '' + escHtml(s.language) + '' + '
' + '' + '' + '' + '
' + '
' + (tagsHtml ? '
' + tagsHtml + '
' : '') + '
' + highlight(s.code, s.language) + '
' + '
'; }).join(''); } // --- Form --- function showForm(snippet) { const card = document.getElementById('csFormCard'); const title = document.getElementById('csFormTitle'); card.classList.add('visible'); if (snippet) { editingId = snippet.id; title.textContent = 'Edit Snippet'; document.getElementById('csInputTitle').value = snippet.title; document.getElementById('csInputLang').value = snippet.language; document.getElementById('csInputTags').value = (snippet.tags || []).join(', '); document.getElementById('csInputCode').value = snippet.code; } else { editingId = null; title.textContent = 'New Snippet'; document.getElementById('csInputTitle').value = ''; document.getElementById('csInputLang').value = 'javascript'; document.getElementById('csInputTags').value = ''; document.getElementById('csInputCode').value = ''; } document.getElementById('csInputTitle').focus(); } function hideForm() { document.getElementById('csFormCard').classList.remove('visible'); editingId = null; } function saveSnippet() { const titleVal = document.getElementById('csInputTitle').value.trim(); const langVal = document.getElementById('csInputLang').value; const tagsVal = document.getElementById('csInputTags').value.split(',').map(t => t.trim().toLowerCase()).filter(Boolean); const codeVal = document.getElementById('csInputCode').value; if (!titleVal) { toast('Title is required'); return; } if (!codeVal.trim()) { toast('Code is required'); return; } if (editingId) { const idx = snippets.findIndex(s => s.id === editingId); if (idx !== -1) { snippets[idx].title = titleVal; snippets[idx].language = langVal; snippets[idx].tags = tagsVal; snippets[idx].code = codeVal; toast('Snippet updated'); } } else { snippets.push({ id: genId(), title: titleVal, language: langVal, tags: tagsVal, code: codeVal, created: Date.now() }); toast('Snippet added'); } save(); hideForm(); render(); } // --- Actions --- function copySnippet(id) { const s = snippets.find(s => s.id === id); if (!s) return; navigator.clipboard.writeText(s.code).then(() => toast('Copied to clipboard')); } function editSnippet(id) { const s = snippets.find(s => s.id === id); if (s) showForm(s); } function deleteSnippet(id) { snippets = snippets.filter(s => s.id !== id); save(); render(); toast('Snippet deleted'); } function exportJSON() { const blob = new Blob([JSON.stringify(snippets, null, 2)], { type: 'application/json' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'snippets-export.json'; a.click(); URL.revokeObjectURL(a.href); toast('Exported ' + snippets.length + ' snippets'); } function importJSON(file) { const reader = new FileReader(); reader.onload = function(e) { try { const data = JSON.parse(e.target.result); if (!Array.isArray(data)) throw new Error('Invalid format'); let count = 0; data.forEach(item => { if (item.title && item.code) { snippets.push({ id: genId(), title: item.title, language: item.language || 'other', tags: item.tags || [], code: item.code, created: item.created || Date.now() }); count++; } }); save(); render(); toast('Imported ' + count + ' snippets'); } catch { toast('Invalid JSON file'); } }; reader.readAsText(file); } // --- Toast --- function toast(msg) { const el = document.getElementById('csToast'); el.textContent = msg; el.classList.add('show'); setTimeout(() => el.classList.remove('show'), 2000); } // --- Event listeners --- document.getElementById('csAddBtn').addEventListener('click', () => showForm(null)); document.getElementById('csSaveBtn').addEventListener('click', saveSnippet); document.getElementById('csCancelBtn').addEventListener('click', hideForm); document.getElementById('csSearch').addEventListener('input', render); document.getElementById('csLangFilter').addEventListener('change', render); document.getElementById('csExportBtn').addEventListener('click', exportJSON); document.getElementById('csImportBtn').addEventListener('click', () => document.getElementById('csFileInput').click()); document.getElementById('csFileInput').addEventListener('change', function() { if (this.files[0]) importJSON(this.files[0]); this.value = ''; }); // Tag cloud clicks document.getElementById('csTagCloud').addEventListener('click', function(e) { const pill = e.target.closest('.cs-tag-pill'); if (!pill) return; const tag = pill.dataset.tag; activeTag = (activeTag === tag) ? '' : tag; render(); }); // Snippet card action buttons (delegated) document.getElementById('csList').addEventListener('click', function(e) { const btn = e.target.closest('button'); if (!btn) return; const id = btn.dataset.id; if (btn.classList.contains('cs-copy-btn')) copySnippet(id); else if (btn.classList.contains('cs-edit-btn')) editSnippet(id); else if (btn.classList.contains('cs-del-btn')) deleteSnippet(id); }); // Allow Tab in textarea document.getElementById('csInputCode').addEventListener('keydown', function(e) { if (e.key === 'Tab') { e.preventDefault(); const start = this.selectionStart; const end = this.selectionEnd; this.value = this.value.substring(0, start) + ' ' + this.value.substring(end); this.selectionStart = this.selectionEnd = start + 2; } }); // Init load(); })();