Spaces:
Sleeping
Sleeping
| const { createApp, ref, onMounted, watch, nextTick } = Vue; | |
| const codeSnippets = { | |
| python: `def hello_world(): | |
| print("Hello, Trae!") | |
| return True | |
| # Build something amazing | |
| if __name__ == "__main__": | |
| hello_world()`, | |
| javascript: `function greet(name) { | |
| return \`Hello, \${name}!\`; | |
| } | |
| // Welcome to Code Snapshot Studio | |
| console.log(greet('Developer'));`, | |
| typescript: `interface User { | |
| id: number; | |
| name: string; | |
| } | |
| const user: User = { | |
| id: 1, | |
| name: "Trae User" | |
| }; | |
| console.log(user);`, | |
| html: `<!DOCTYPE html> | |
| <html lang="en"> | |
| <body> | |
| <h1>Hello World</h1> | |
| <p>Welcome to my website.</p> | |
| </body> | |
| </html>`, | |
| css: `.container { | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| height: 100vh; | |
| background: #f0f0f0; | |
| }`, | |
| java: `public class Main { | |
| public static void main(String[] args) { | |
| System.out.println("Hello, World!"); | |
| } | |
| }`, | |
| go: `package main | |
| import "fmt" | |
| func main() { | |
| fmt.Println("Hello, Go!") | |
| }`, | |
| rust: `fn main() { | |
| println!("Hello, Rust!"); | |
| }`, | |
| sql: `SELECT id, username, email | |
| FROM users | |
| WHERE status = 'active' | |
| ORDER BY created_at DESC;`, | |
| bash: `#!/bin/bash | |
| echo "Starting deployment..." | |
| npm install | |
| npm run build | |
| echo "Done!"`, | |
| json: `{ | |
| "name": "code-snapshot-studio", | |
| "version": "1.0.0", | |
| "private": true | |
| }` | |
| }; | |
| createApp({ | |
| setup() { | |
| const code = ref(codeSnippets.python); | |
| const language = ref('python'); | |
| const theme = ref('tomorrow'); | |
| const padding = ref(64); | |
| const showWindowControls = ref(true); | |
| const showLineNumbers = ref(true); | |
| const showShadow = ref(true); | |
| const windowTitle = ref('main.py'); | |
| const snapshotCard = ref(null); | |
| const codeBlock = ref(null); | |
| const isExporting = ref(false); | |
| const showSidebar = ref(true); // For mobile toggle | |
| // Background presets | |
| const backgrounds = [ | |
| { name: 'Gradient 1', value: 'linear-gradient(135deg, #FF9D6C 0%, #BB4E75 100%)' }, | |
| { name: 'Gradient 2', value: 'linear-gradient(135deg, #85FFBD 0%, #FFFB7D 100%)' }, | |
| { name: 'Gradient 3', value: 'linear-gradient(135deg, #8EC5FC 0%, #E0C3FC 100%)' }, | |
| { name: 'Gradient 4', value: 'linear-gradient(135deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%)' }, | |
| { name: 'Solid Dark', value: '#1e293b' }, | |
| { name: 'Solid Light', value: '#f8fafc' }, | |
| { name: 'Mesh Gradient', value: 'radial-gradient(at 40% 20%, hsla(28,100%,74%,1) 0px, transparent 50%), radial-gradient(at 80% 0%, hsla(189,100%,56%,1) 0px, transparent 50%), radial-gradient(at 0% 50%, hsla(355,100%,93%,1) 0px, transparent 50%)' } | |
| ]; | |
| const currentBg = ref(backgrounds[3]); | |
| const themeBgColor = ref('#2d2d2d'); // Default for Tomorrow | |
| const changeTheme = () => { | |
| const link = document.getElementById('prism-theme'); | |
| const baseUrl = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism'; | |
| if (theme.value === 'default') { | |
| link.href = `${baseUrl}.min.css`; | |
| themeBgColor.value = '#f5f2f0'; | |
| } else { | |
| link.href = `${baseUrl}-${theme.value}.min.css`; | |
| // Update bg color approximation | |
| if(theme.value === 'tomorrow') themeBgColor.value = '#2d2d2d'; | |
| if(theme.value === 'okaidia') themeBgColor.value = '#272822'; | |
| if(theme.value === 'solarizedlight') themeBgColor.value = '#fdf6e3'; | |
| if(theme.value === 'twilight') themeBgColor.value = '#141414'; | |
| } | |
| }; | |
| const refreshHighlight = () => { | |
| nextTick(() => { | |
| if (window.Prism) { | |
| Prism.highlightAll(); | |
| } | |
| }); | |
| }; | |
| // Auto-load snippet when language changes (if code is empty or matches another snippet) | |
| const onLanguageChange = () => { | |
| // Optional: You could ask user or just automatically switch if it's default | |
| // For now, let's just refresh highlight | |
| refreshHighlight(); | |
| }; | |
| const loadExample = () => { | |
| if (codeSnippets[language.value]) { | |
| code.value = codeSnippets[language.value]; | |
| } | |
| }; | |
| watch([code, language, showLineNumbers], () => { | |
| refreshHighlight(); | |
| }); | |
| onMounted(() => { | |
| refreshHighlight(); | |
| // Check screen size for initial sidebar state | |
| if (window.innerWidth < 1024) { | |
| showSidebar.value = false; | |
| } | |
| }); | |
| const clearCode = () => { | |
| code.value = ''; | |
| }; | |
| const copyImage = async () => { | |
| if (!snapshotCard.value || isExporting.value) return; | |
| isExporting.value = true; | |
| try { | |
| await nextTick(); | |
| const canvas = await html2canvas(snapshotCard.value, { | |
| scale: 2, | |
| useCORS: true, | |
| backgroundColor: null, | |
| logging: false, | |
| allowTaint: true | |
| }); | |
| canvas.toBlob(async (blob) => { | |
| try { | |
| await navigator.clipboard.write([ | |
| new ClipboardItem({ | |
| [blob.type]: blob | |
| }) | |
| ]); | |
| alert('图片已复制到剪贴板'); | |
| } catch (err) { | |
| console.error('Copy failed:', err); | |
| alert('复制失败,浏览器可能不支持此功能'); | |
| } | |
| }); | |
| } catch (err) { | |
| console.error('Render failed:', err); | |
| alert('生成图片失败,请重试'); | |
| } finally { | |
| isExporting.value = false; | |
| } | |
| }; | |
| const exportImage = async () => { | |
| if (!snapshotCard.value || isExporting.value) return; | |
| isExporting.value = true; | |
| try { | |
| // Wait for any renders | |
| await nextTick(); | |
| const canvas = await html2canvas(snapshotCard.value, { | |
| scale: 2, // Retina support | |
| useCORS: true, | |
| backgroundColor: null, | |
| logging: false, | |
| allowTaint: true | |
| }); | |
| const link = document.createElement('a'); | |
| link.download = `code-snapshot-${Date.now()}.png`; | |
| link.href = canvas.toDataURL('image/png'); | |
| link.click(); | |
| } catch (err) { | |
| console.error('Export failed:', err); | |
| alert('导出失败,请重试'); | |
| } finally { | |
| isExporting.value = false; | |
| } | |
| }; | |
| const toggleSidebar = () => { | |
| showSidebar.value = !showSidebar.value; | |
| }; | |
| return { | |
| code, | |
| language, | |
| theme, | |
| padding, | |
| showWindowControls, | |
| showLineNumbers, | |
| showShadow, | |
| windowTitle, | |
| backgrounds, | |
| currentBg, | |
| snapshotCard, | |
| codeBlock, | |
| copyImage, | |
| clearCode, | |
| exportImage, | |
| changeTheme, | |
| refreshHighlight, | |
| themeBgColor, | |
| onLanguageChange, | |
| loadExample, | |
| isExporting, | |
| showSidebar, | |
| toggleSidebar | |
| }; | |
| } | |
| }).mount('#app'); | |