Snippets: MarkdownLive
CSS Before Head
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
HTML Head
* { margin: 0; padding: 0; box-sizing: border-box; font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; } /* 基础变量 - 亮色主题 */ :root { --body-bg: #f5f7fa; --top-bar-bg: #4299e1; --top-bar-text: #ffffff; --btn-bg: #ffffff; --btn-text: #4299e1; --btn-hover: #f0f7ff; --btn-disabled: #a0aec0; --dropdown-bg: #ffffff; --dropdown-border: #e2e8f0; --dropdown-hover: #f5f7fa; --panel-bg: #ffffff; --panel-border: #e2e8f0; --panel-shadow: 0 1px 3px rgba(0,0,0,0.05); --panel-title-bg: #f8f9fa; --panel-title-text: #2d3748; --input-bg: #ffffff; --input-text: #2d3748; --input-placeholder: #718096; --preview-text: #4a5568; --preview-title: #2d3748; --preview-title-border: #e2e8f0; --code-bg: #f7fafc; --code-text: #e53e3e; --pre-border: #e2e8f0; --blockquote-border: #4299e1; --blockquote-text: #718096; --table-border: #e2e8f0; --table-th-bg: #f7fafc; --table-th-text: #2d3748; --scrollbar-track: #f5f7fa; --scrollbar-thumb: #e2e8f0; --scrollbar-thumb-hover: #cbd5e1; /* 导出容器变量 */ --export-bg: #ffffff; --export-text: #2d3748; --export-title: #2d3748; --export-title-border: #e2e8f0; --export-code-bg: #f7fafc; --export-code-text: #e53e3e; } /* 暗色主题变量 */ [data-theme="dark"] { --body-bg: #1a1a2e; --top-bar-bg: #16213e; --top-bar-text: #e6e6ff; --btn-bg: #0f3460; --btn-text: #e6e6ff; --btn-hover: #1a508b; --btn-disabled: #2c3e50; --dropdown-bg: #12121f; --dropdown-border: #2c2c44; --dropdown-hover: #16213e; --panel-bg: #12121f; --panel-border: #2c2c44; --panel-shadow: 0 1px 3px rgba(0,0,0,0.3); --panel-title-bg: #16213e; --panel-title-text: #e6e6ff; --input-bg: #12121f; --input-text: #d1d1e0; --input-placeholder: #646480; --preview-text: #d1d1e0; --preview-title: #a9d1ff; --preview-title-border: #2c2c44; --code-bg: #16213e; --code-text: #ff7675; --pre-border: #2c2c44; --blockquote-border: #0f3460; --blockquote-text: #94a3b8; --table-border: #2c2c44; --table-th-bg: #16213e; --table-th-text: #a9d1ff; --scrollbar-track: #12121f; --scrollbar-thumb: #2c2c44; --scrollbar-thumb-hover: #3d3d66; /* 导出容器变量 */ --export-bg: #12121f; --export-text: #d1d1e0; --export-title: #a9d1ff; --export-title-border: #2c2c44; --export-code-bg: #16213e; --export-code-text: #ff7675; } body { background-color: var(--body-bg); height: 100vh; overflow: hidden; transition: background-color 0.3s ease; } /* 顶部固定栏 */ .top-bar { position: fixed; top: 0; left: 0; right: 0; height: 50px; background-color: var(--top-bar-bg); display: flex; justify-content: space-between; align-items: center; padding: 0 12px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); z-index: 100; transition: all 0.3s ease; } .top-bar .title { color: var(--top-bar-text); font-size: 1rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 55%; } .top-bar .func-group { display: flex; gap: 6px; align-items: center; position: relative; } /* 小巧的主题切换按钮 */ #theme-toggle { padding: 4px 8px; border: none; border-radius: 3px; background-color: var(--btn-bg); color: var(--btn-text); font-size: 0.75rem; cursor: pointer; transition: all 0.3s ease; } /* 导出下拉按钮 */ #export-dropdown-btn { padding: 4px 10px; border: none; border-radius: 3px; background-color: var(--btn-bg); color: var(--btn-text); font-size: 0.75rem; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; gap: 4px; } #theme-toggle:hover, #export-dropdown-btn:hover { background-color: var(--btn-hover); } /* 导出下拉菜单 */ .export-dropdown { position: absolute; top: calc(100% + 4px); right: 0; width: 120px; background-color: var(--dropdown-bg); border: 1px solid var(--dropdown-border); border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.2); list-style: none; display: none; z-index: 101; transition: all 0.3s ease; } .export-dropdown.show { display: block; } .export-dropdown li { padding: 6px 10px; font-size: 0.75rem; color: var(--input-text); cursor: pointer; transition: background-color 0.2s ease; } .export-dropdown li:hover { background-color: var(--dropdown-hover); } .loading-tip { color: var(--top-bar-text); font-size: 0.75rem; display: none; margin-left: 6px; white-space: nowrap; } /* 桌面端适配 */ @media (min-width: 768px) { .top-bar { height: 60px; padding: 0 20px; } .top-bar .title { font-size: 1.2rem; max-width: unset; } #theme-toggle { padding: 6px 10px; font-size: 0.85rem; } #export-dropdown-btn { padding: 6px 14px; font-size: 0.85rem; } .loading-tip { font-size: 0.85rem; } .export-dropdown { width: 140px; } .export-dropdown li { padding: 8px 12px; font-size: 0.85rem; } } /* 主体编辑区域 */ .main-container { position: absolute; top: 50px; left: 0; right: 0; bottom: 0; padding: 10px; display: flex; flex-direction: column; gap: 10px; } .editor-wrapper { flex: 1; display: flex; flex-direction: column; gap: 10px; border-radius: 8px; overflow: hidden; } @media (min-width: 768px) { .editor-wrapper { flex-direction: row; } } .editor-panel, .preview-panel { flex: 1; background-color: var(--panel-bg); border: 2px solid var(--panel-border); border-radius: 6px; overflow: hidden; box-shadow: var(--panel-shadow); transition: all 0.3s ease; } .panel-title { height: 40px; line-height: 40px; padding: 0 15px; background-color: var(--panel-title-bg); border-bottom: 1px solid var(--panel-border); color: var(--panel-title-text); font-size: 0.95rem; font-weight: 500; transition: all 0.3s ease; } #markdown-input { width: 100%; height: calc(100% - 40px); border: none; outline: none; padding: 20px; font-size: 1rem; resize: none; font-family: "Consolas", "Monaco", monospace; line-height: 1.6; background-color: var(--input-bg); color: var(--input-text); overflow-y: auto; transition: all 0.3s ease; } #markdown-input::placeholder { color: var(--input-placeholder); } #preview-area { width: 100%; height: calc(100% - 40px); padding: 20px; overflow-y: auto; color: var(--preview-text); transition: all 0.3s ease; } /* 导出容器 */ #full-preview-container { position: absolute; top: -9999px; left: -9999px; width: 900px; max-width: 100%; padding: 50px; background-color: var(--export-bg); color: var(--export-text); transition: all 0.3s ease; } /* Markdown通用样式 */ .markdown-style h1 { font-size: 2rem; margin: 20px 0; color: var(--preview-title); border-bottom: 1px solid var(--preview-title-border); padding-bottom: 10px; } .markdown-style h2 { font-size: 1.6rem; margin: 18px 0; color: var(--preview-title); } .markdown-style h3 { font-size: 1.3rem; margin: 15px 0; color: var(--preview-title); } .markdown-style p { line-height: 1.8; margin: 10px 0; color: var(--preview-text); font-size: 1rem; } .markdown-style ul, .markdown-style ol { padding-left: 30px; margin: 10px 0; color: var(--preview-text); line-height: 1.8; } .markdown-style code { background-color: var(--code-bg); padding: 3px 6px; border-radius: 4px; color: var(--code-text); font-family: "Consolas", monospace; font-size: 0.95rem; } .markdown-style pre { background-color: var(--code-bg); padding: 20px; border-radius: 8px; overflow-x: auto; margin: 15px 0; border: 1px solid var(--pre-border); } .markdown-style pre code { color: var(--preview-text); padding: 0; } .markdown-style blockquote { border-left: 4px solid var(--blockquote-border); padding-left: 15px; margin: 15px 0; color: var(--blockquote-text); } .markdown-style table { border-collapse: collapse; width: 100%; margin: 20px 0; } .markdown-style th, .markdown-style td { border: 1px solid var(--table-border); padding: 10px 15px; text-align: left; } .markdown-style th { background-color: var(--table-th-bg); color: var(--table-th-text); } /* 导出容器Markdown样式 */ #full-preview-container h1 { color: var(--export-title); border-bottom-color: var(--export-title-border); } #full-preview-container h2, #full-preview-container h3 { color: var(--export-title); } #full-preview-container code { background-color: var(--export-code-bg); color: var(--export-code-text); } /* 滚动条美化 */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: var(--scrollbar-track); border-radius: 4px; } ::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); }
CSS After Head
JS Before HTML Body
data-theme="dark"
HTML Body Attrs
<!-- 顶部固定栏 --> <div class="top-bar"> <div class="title">MarkdownLive</div> <div class="func-group"> <button id="theme-toggle">Light</button> <button id="export-dropdown-btn">Export ▼</button> <ul class="export-dropdown" id="export-dropdown"> <li id="export-md">MD</li> <li id="export-img">PNG</li> <li id="export-html">HTML</li> </ul> <span class="loading-tip" id="loading-tip">Generating...</span> </div> </div> <!-- 主体区域 --> <div class="main-container"> <div class="editor-wrapper"> <div class="editor-panel"> <div class="panel-title">Markdown</div> <textarea id="markdown-input" placeholder="请输入Markdown内容,右侧实时预览..."></textarea> </div> <div class="preview-panel"> <div class="panel-title">Preview</div> <div id="preview-area" class="markdown-style"> <p style="text-align: center; color: var(--input-placeholder); margin-top: 80px;">输入内容后此处实时渲染</p> </div> </div> </div> </div> <!-- 完整导出容器 --> <div id="full-preview-container" class="markdown-style"></div>
HTML Body
HTML Foot
// 获取DOM元素 const body = document.body; const themeToggle = document.getElementById('theme-toggle'); const exportDropdownBtn = document.getElementById('export-dropdown-btn'); const exportDropdown = document.getElementById('export-dropdown'); const exportImg = document.getElementById('export-img'); const exportMD = document.getElementById('export-md'); const exportHtml = document.getElementById('export-html'); const markdownInput = document.getElementById('markdown-input'); const previewArea = document.getElementById('preview-area'); const fullPreviewContainer = document.getElementById('full-preview-container'); const loadingTip = document.getElementById('loading-tip'); // 主题切换逻辑 let isDark = body.getAttribute('data-theme') == "dark"; themeToggle.addEventListener('click', () => { isDark = !isDark; let setattr = isDark ? 'dark' : 'light'; let settext = isDark ? 'Light' : 'Dark'; body.setAttribute('data-theme', setattr); themeToggle.textContent = settext; syncContent(markdownInput.value.trim()); }); // 下拉菜单显示/隐藏 exportDropdownBtn.addEventListener('click', (e) => { e.stopPropagation(); exportDropdown.classList.toggle('show'); }); document.addEventListener('click', () => { exportDropdown.classList.remove('show'); }); exportDropdown.addEventListener('click', (e) => { e.stopPropagation(); }); // 实时同步Markdown内容 markdownInput.addEventListener('input', () => { syncContent(markdownInput.value.trim()); }); function syncContent(content) { if (content) { const html = marked.parse(content); previewArea.innerHTML = html; fullPreviewContainer.innerHTML = html; } else { previewArea.innerHTML = `<p style="text-align: center; color: var(--input-placeholder); margin-top: 80px;">输入内容后此处实时渲染</p>`; fullPreviewContainer.innerHTML = ''; } } // 显示/隐藏加载提示 function showLoading() { loadingTip.style.display = 'block'; exportDropdownBtn.disabled = true; themeToggle.disabled = true; } function hideLoading() { loadingTip.style.display = 'none'; exportDropdownBtn.disabled = false; themeToggle.disabled = false; exportDropdown.classList.remove('show'); } // 1. 导出长图 exportImg.addEventListener('click', async () => { const content = markdownInput.value.trim(); if (!content) { alert('请先输入Markdown内容!'); return; } showLoading(); try { await new Promise(resolve => setTimeout(resolve, 400)); const canvas = await html2canvas(fullPreviewContainer, { scale: 2, useCORS: true, backgroundColor: getComputedStyle(fullPreviewContainer).backgroundColor }); const link = document.createElement('a'); const theme = isDark ? 'dark' : 'light'; link.download = `markdown-img-${theme}-${Date.now()}.png`; link.href = canvas.toDataURL('image/png', 1.0); link.click(); alert(`已导出${theme}主题长图!`); } catch (err) { alert(`长图导出失败:${err.message}`); } hideLoading(); }); // 2. 导出Markdown为MD exportMD.addEventListener('click', () => { const content = markdownInput.value.trim(); if (!content) { alert('请先输入Markdown内容!'); return; } showLoading(); try { const blob = new Blob([content], { type: 'text/plain;charset=utf-8' }); const link = document.createElement('a'); link.download = `markdown-text-${Date.now()}.md`; link.href = URL.createObjectURL(blob); link.click(); URL.revokeObjectURL(link.href); alert('MD文件导出成功!'); } catch (err) { alert(`MD导出失败:${err.message}`); } hideLoading(); }); // 3. 导出预览为HTML exportHtml.addEventListener('click', () => { const content = markdownInput.value.trim(); if (!content) { alert('请先输入Markdown内容!'); return; } showLoading(); try { // 获取当前主题样式,生成完整HTML const theme = isDark ? 'dark' : 'light'; const htmlContent = ` <!DOCTYPE html> <html lang="zh-CN" data-theme="${theme}"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Markdown导出HTML</title> <style> :root { --text: #4a5568; --title: #2d3748; --code-bg: #f7fafc; --code-text: #e53e3e; --border: #e2e8f0; --th-bg: #f7fafc; } [data-theme="dark"] { --text: #d1d1e0; --title: #a9d1ff; --code-bg: #16213e; --code-text: #ff7675; --border: #2c2c44; --th-bg: #16213e; } body { background: ${isDark ? '#12121f' : '#ffffff'}; color: var(--text); padding: 50px; max-width: 900px; margin: 0 auto; font-family: "Segoe UI", "PingFang SC", sans-serif; line-height: 1.8; } h1 { color: var(--title); border-bottom: 1px solid var(--border); padding-bottom: 10px; } h2, h3 { color: var(--title); } code { background: var(--code-bg); padding: 3px 6px; border-radius: 4px; color: var(--code-text); font-family: Consolas, monospace; } pre { background: var(--code-bg); padding: 20px; border-radius: 8px; border: 1px solid var(--border); overflow-x: auto; } pre code { padding: 0; color: var(--text); } blockquote { border-left: 4px solid ${isDark ? '#0f3460' : '#4299e1'}; padding-left: 15px; color: ${isDark ? '#94a3b8' : '#718096'}; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid var(--border); padding: 10px 15px; } th { background: var(--th-bg); color: var(--title); } </style> </head> <body> ${marked.parse(content)} </body> </html> `; const blob = new Blob([htmlContent], { type: 'text/html;charset=utf-8' }); const link = document.createElement('a'); link.download = `markdown-html-${theme}-${Date.now()}.html`; link.href = URL.createObjectURL(blob); link.click(); URL.revokeObjectURL(link.href); alert(`已导出${theme}主题HTML文件!`); } catch (err) { alert(`HTML导出失败:${err.message}`); } hideLoading(); });
JS After HTML Body
Full HTML Code