文本工具Markdown 阅读

Markdown 文档阅读器

桌面浏览器本地 Markdown 文档阅读器,左侧编辑右侧即时预览,4 阅读模式(沉浸 / 护眼 / 打印 / 公众号),一键复制公众号样式 HTML,支持 .md 文件拖拽。

Markdown 源
预览
0 字符 0 词 约 0 分钟阅读

使用说明

4 种阅读模式

  • 沉浸 — 思源宋体 + 黄金行宽 720px + 章节分隔,适合长文阅读
  • 护眼 — 米黄底色 + 深棕文字,降低对比度减少疲劳
  • 打印 — 11pt Georgia + 紧凑行距,适配打印 / 导出 PDF
  • 公众号 — 公众号编辑器风格,一键复制后直接粘贴到公众号后台

核心功能

  • 左侧编辑 / 右侧即时预览(实时同步,无延迟)
  • 拖入 .md 文件即时加载,也可点 载入示例 看效果
  • 自动统计字符数 / 词数 / 预估阅读时间
  • 自动生成 h1-h4 大纲(锚点跳转)
  • 一键复制公众号 HTML(带 inline style,粘贴即可发)
  • 导出 .md 文件 / 浏览器打印(自带 print CSS)
  • 完全本地处理,零上传,关闭页面即清除

支持语法

  • H1-H6 / 粗体 **text** / 斜体 *text* / 删除线 ~~text~~
  • 行内代码 `code` 和代码块 ```lang
  • 链接 / 图片 / 有序列表 / 无序列表 / 任务列表
  • GFM 表格 / 引用 / 分割线

运行环境

  • 纯前端工具,Agent 调用见下方 API 示例。

Agent API 调用示例

// Step 1: 读取工具 Schema
GET https://clawam.com/tools/md_reader/schema.json

// Step 2: 在浏览器中执行工具逻辑
// Markdown 解析 / 4 模式渲染 / 大纲生成 全部在工具页 JS 中实现
// Agent 可用 readFile 读取 md 源 → 复制到工具页 textarea → 触发 input 事件
'; if (navigator.clipboard && navigator.clipboard.write) { // 复制为 HTML + 纯文本双格式 (公众号编辑器可识别 HTML) var blobHtml = new Blob([wrapped], { type: 'text/html' }); var blobText = new Blob([preview.innerText], { type: 'text/plain' }); try { navigator.clipboard.write([new ClipboardItem({ 'text/html': blobHtml, 'text/plain': blobText })]).then(function() { flash($('btn-copy-html'), '已复制公众号 HTML'); }).catch(function() { fallbackCopy(wrapped); }); } catch (e) { fallbackCopy(wrapped); } } else { fallbackCopy(wrapped); } }); function fallbackCopy(text) { var ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.left = '-9999px'; document.body.appendChild(ta); ta.select(); try { document.execCommand('copy'); flash($('btn-copy-html'), '已复制'); } catch (e) { flash($('btn-copy-html'), '复制失败'); } document.body.removeChild(ta); } function flash(btn, msg) { var orig = btn.innerHTML; btn.innerHTML = msg; btn.disabled = true; setTimeout(function() { btn.innerHTML = orig; btn.disabled = false; }, 1500); } // 公众号专用 CSS (inline 风格) var WECHAT_CSS = 'body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;font-size:16px;line-height:1.85;color:#333;max-width:100%;margin:0;padding:22px 28px;background:#fff}h1{font-size:1.4em;color:#333;border-left:4px solid #42b983;padding-left:12px;margin:1.4em 0 0.6em}h2{font-size:1.25em;color:#333;border-left:3px solid #42b983;padding-left:10px;margin:1.3em 0 0.5em}h3{font-size:1.1em;color:#444;margin:1.2em 0 0.5em}p{margin:1em 0;letter-spacing:0.3px}code{background:#f4f4f4;border-radius:3px;padding:2px 6px;color:#c7254e;font-size:0.92em}pre{background:#2d2d2d;color:#f8f8f2;padding:14px 16px;border-radius:6px;overflow-x:auto;line-height:1.6}pre code{background:transparent;color:#f8f8f2;padding:0}blockquote{border-left:3px solid #ddd;color:#666;padding:4px 14px;margin:1em 0;background:#f9f9f9}table{border-collapse:collapse;width:100%;margin:1em 0;font-size:0.95em}th,td{padding:8px 12px;border:1px solid #ddd}th{background:#f4f4f4}ul,ol{padding-left:28px}a{color:#42b983;text-decoration:none;border-bottom:1px solid rgba(66,185,131,0.3)}img{max-width:100%;border-radius:4px}hr{border:none;border-top:1px solid #e5e5e5;margin:1.5em 0}'; // 复制 MD 源 $('btn-copy-md').addEventListener('click', function() { if (!lastMd) { alert('内容为空'); return; } if (navigator.clipboard) { navigator.clipboard.writeText(lastMd).then(function() { flash($('btn-copy-md'), 'MD 已复制'); }); } else { fallbackCopy(lastMd); } }); // 下载 .md $('btn-download-md').addEventListener('click', function() { if (!lastMd) { alert('内容为空'); return; } var blob = new Blob([lastMd], { type: 'text/markdown;charset=utf-8' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'document.md'; a.click(); URL.revokeObjectURL(url); }); // 打印 / PDF $('btn-print').addEventListener('click', function() { if (!lastMd) { alert('内容为空'); return; } // 切换到打印模式再打印 var prevMode = currentMode; var btns = modeTabs.querySelectorAll('button'); for (var i = 0; i < btns.length; i++) { btns[i].classList.toggle('active', btns[i].getAttribute('data-mode') === 'print'); } preview.className = 'md-preview mode-print'; setTimeout(function() { window.print(); // 打印后恢复 preview.className = 'md-preview mode-' + prevMode; for (var j = 0; j < btns.length; j++) { btns[j].classList.toggle('active', btns[j].getAttribute('data-mode') === prevMode); } }, 100); }); // 清空 $('btn-clear').addEventListener('click', function() { editor.value = ''; render(); editor.focus(); }); // 载入示例 $('btn-load-sample').addEventListener('click', function() { editor.value = SAMPLE_MD; render(); }); // 拖拽 .md 文件 var dropzone = $('dropzone'); ['dragenter', 'dragover'].forEach(function(evt) { dropzone.addEventListener(evt, function(e) { e.preventDefault(); e.stopPropagation(); dropzone.classList.add('drag-over'); }); }); ['dragleave', 'drop'].forEach(function(evt) { dropzone.addEventListener(evt, function(e) { e.preventDefault(); e.stopPropagation(); if (evt === 'dragleave' && e.target !== dropzone) return; dropzone.classList.remove('drag-over'); }); }); // === 打开本地 .md 文件 (按钮 + 隐藏 input 触发) === var fileInput = document.getElementById('md-file-input'); var btnOpen = document.getElementById('btn-open-file'); function handleFile(file) { if (!file) return; if (!/\.(md|markdown|txt)$/i.test(file.name)) { alert('请选择 .md / .markdown / .txt 文件'); return; } if (file.size > 5 * 1024 * 1024) { alert('文件超过 5MB,过大'); return; } var reader = new FileReader(); reader.onload = function(ev) { editor.value = ev.target.result; editor.scrollTop = 0; render(); // 焦点留在编辑器 editor.focus(); // 状态提示 var meta = document.querySelector('.reader-meta'); if (meta) { var prev = meta.textContent; meta.textContent = '已加载 ' + file.name + ' (' + ev.target.result.length + ' 字符)'; setTimeout(function() { meta.textContent = prev; }, 2500); } }; reader.onerror = function() { alert('读取文件失败'); }; reader.readAsText(file, 'UTF-8'); } if (btnOpen && fileInput) { btnOpen.addEventListener('click', function() { fileInput.click(); }); fileInput.addEventListener('change', function() { if (fileInput.files && fileInput.files[0]) { handleFile(fileInput.files[0]); // 清空 value, 允许同名文件再次选择 fileInput.value = ''; } }); } dropzone.addEventListener('drop', function(e) { var files = e.dataTransfer.files; if (!files || !files.length) return; handleFile(files[0]); }); // 示例 Markdown var SAMPLE_MD = '# Markdown 文档阅读器\n\n欢迎使用 **Markdown 文档阅读器**,这是一款专为长文阅读优化的浏览器工具。\n\n## 核心特性\n\n- 4 种阅读模式:沉浸 / 护眼 / 打印 / 公众号\n- 自动生成大纲(基于 h1-h4)\n- 一键复制公众号样式 HTML\n- 拖拽 .md 文件即时加载\n\n## 代码示例\n\n```javascript\nfunction greet(name) {\n console.log(`Hello, ${name}!`);\n}\n```\n\n## 表格示例\n\n| 模式 | 适合场景 | 字体 |\n|------|---------|------|\n| 沉浸 | 长文阅读 | 思源宋体 |\n| 护眼 | 长时间阅读 | Georgia |\n| 打印 | 打印 / PDF | Georgia 11pt |\n| 公众号 | 公众号发文 | 系统默认 |\n\n## 任务列表\n\n- [x] 编辑器实时同步\n- [x] 4 阅读模式切换\n- [x] 一键复制 HTML\n- [ ] 支持导出 EPUB(规划中)\n\n> 工具的核心不是功能堆叠,而是把一件事做穿。\n\n## 引用与链接\n\n参考 [Markdown 语法](https://commonmark.org) 学习更多。'; // 初始渲染示例 editor.value = SAMPLE_MD; render(); // === editor fullscreen === // === preview fullscreen === var pfsBtn = document.getElementById('btn-preview-fullscreen'); if (pfsBtn) { var pfsIconExpand = document.getElementById('preview-fs-icon-expand'); var pfsIconCollapse = document.getElementById('preview-fs-icon-collapse'); var pfsLabel = document.getElementById('preview-fs-label'); function setPreviewFullscreen(on) { if (on) { // 互斥: 退出 editor fullscreen document.body.classList.remove('editor-fullscreen'); // 同时改 editor 全屏按钮的 label 回到 "全屏" var edFsLabel = document.getElementById('fullscreen-label'); if (edFsLabel) edFsLabel.textContent = '全屏'; var edIconExp = document.getElementById('fullscreen-icon-expand'); var edIconCol = document.getElementById('fullscreen-icon-collapse'); if (edIconExp) edIconExp.style.display = ''; if (edIconCol) edIconCol.style.display = 'none'; } document.body.classList.toggle('preview-fullscreen', on); if (pfsIconExpand) pfsIconExpand.style.display = on ? 'none' : ''; if (pfsIconCollapse) pfsIconCollapse.style.display = on ? '' : 'none'; if (pfsLabel) pfsLabel.textContent = on ? '退出全屏' : '全屏'; } pfsBtn.addEventListener('click', function() { setPreviewFullscreen(!document.body.classList.contains('preview-fullscreen')); }); } var fsBtn = document.getElementById('btn-fullscreen'); if (fsBtn) { var fsIconExpand = document.getElementById('fullscreen-icon-expand'); var fsIconCollapse = document.getElementById('fullscreen-icon-collapse'); var fsLabel = document.getElementById('fullscreen-label'); function setFullscreen(on) { document.body.classList.toggle('editor-fullscreen', on); if (fsIconExpand) fsIconExpand.style.display = on ? 'none' : ''; if (fsIconCollapse) fsIconCollapse.style.display = on ? '' : 'none'; if (fsLabel) fsLabel.textContent = on ? '退出全屏' : '全屏'; if (on) { var mdInput = document.getElementById('md-input'); if (mdInput) mdInput.focus(); } } fsBtn.addEventListener('click', function() { setFullscreen(!document.body.classList.contains('editor-fullscreen')); }); window.addEventListener('keydown', function(e) { if (e.key !== 'Escape') return; if (document.body.classList.contains('editor-fullscreen')) { setFullscreen(false); e.preventDefault(); } else if (document.body.classList.contains('preview-fullscreen')) { setPreviewFullscreen(false); e.preventDefault(); } }, true); } })();