Tools Markdown Editor
Markdown 0 chars
Preview
`; const blob = new Blob([fullDoc], { type: 'text/html' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'markdown-export.html'; a.click(); URL.revokeObjectURL(url); }); /* ══════════════════════════════════════════════════ Resizable Divider ══════════════════════════════════════════════════ */ let isDragging = false; divider.addEventListener('mousedown', (e) => { isDragging = true; divider.classList.add('dragging'); document.body.style.cursor = 'col-resize'; document.body.style.userSelect = 'none'; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; const rect = editorWrap.getBoundingClientRect(); const isVertical = window.innerWidth <= 768; if (isVertical) { const pct = ((e.clientY - rect.top) / rect.height) * 100; const clamped = Math.max(15, Math.min(85, pct)); editorWrap.querySelector('.pane-editor').style.flex = `0 0 ${clamped}%`; editorWrap.querySelector('.pane-preview').style.flex = `0 0 ${100 - clamped}%`; } else { const pct = ((e.clientX - rect.left) / rect.width) * 100; const clamped = Math.max(15, Math.min(85, pct)); editorWrap.querySelector('.pane-editor').style.flex = `0 0 ${clamped}%`; editorWrap.querySelector('.pane-preview').style.flex = `0 0 ${100 - clamped}%`; } }); document.addEventListener('mouseup', () => { if (isDragging) { isDragging = false; divider.classList.remove('dragging'); document.body.style.cursor = ''; document.body.style.userSelect = ''; } }); // Touch support for mobile resize divider.addEventListener('touchstart', (e) => { isDragging = true; divider.classList.add('dragging'); e.preventDefault(); }, { passive: false }); document.addEventListener('touchmove', (e) => { if (!isDragging) return; const touch = e.touches[0]; const rect = editorWrap.getBoundingClientRect(); const isVertical = window.innerWidth <= 768; if (isVertical) { const pct = ((touch.clientY - rect.top) / rect.height) * 100; const clamped = Math.max(15, Math.min(85, pct)); editorWrap.querySelector('.pane-editor').style.flex = `0 0 ${clamped}%`; editorWrap.querySelector('.pane-preview').style.flex = `0 0 ${100 - clamped}%`; } else { const pct = ((touch.clientX - rect.left) / rect.width) * 100; const clamped = Math.max(15, Math.min(85, pct)); editorWrap.querySelector('.pane-editor').style.flex = `0 0 ${clamped}%`; editorWrap.querySelector('.pane-preview').style.flex = `0 0 ${100 - clamped}%`; } }, { passive: false }); document.addEventListener('touchend', () => { if (isDragging) { isDragging = false; divider.classList.remove('dragging'); } }); /* ══════════════════════════════════════════════════ Persist editor content ══════════════════════════════════════════════════ */ const STORAGE_KEY = 'md-editor-content'; function saveContent() { localStorage.setItem(STORAGE_KEY, editor.value); } // Load saved content or use sample const saved = localStorage.getItem(STORAGE_KEY); if (saved) { editor.value = saved; } else { editor.value = `# Markdown Editor Welcome to the **live preview** Markdown editor. Start typing on the left and see the rendered output on the right. ## Features - **Headings** (h1 through h6) - **Bold**, *italic*, and ***bold italic*** text - ~~Strikethrough~~ text - [Links](https://example.com) and ![images](https://picsum.photos/400/200) - Inline \`code\` and fenced code blocks - Blockquotes, lists, and task lists - Tables with alignment - Horizontal rules --- ## Code Block \`\`\`javascript function greet(name) { return \`Hello, \${name}!\`; } console.log(greet('World')); \`\`\` ## Blockquote > The best way to predict the future is to invent it. > -- Alan Kay ## Table | Feature | Supported | |:--------|:---------:| | Headings | Yes | | Bold/Italic | Yes | | Code blocks | Yes | | Tables | Yes | | Task lists | Yes | ## Task List - [x] Build the parser - [x] Add theme switching - [x] Export to HTML - [ ] Add even more features --- *Built with zero dependencies. Pure HTML, CSS, and JavaScript.* `; } // Auto-save on input editor.addEventListener('input', saveContent); // Initial render updatePreview(); })();