docs: rewrite README.md and site/ for v0.2.0

- README.md: full API reference, syntax table, plugin/theme/i18n docs
- site/index.html: v0.2.0 hero, live demo, feature cards, API overview
- site/docs.html: sidebar nav, full config, instance API tables, parser reference
- site/demo.html: all-syntax demo with TS code samples
This commit is contained in:
2026-07-24 22:42:42 +08:00
parent e83fc211dc
commit 16464af0ae
4 changed files with 980 additions and 1936 deletions
+107 -116
View File
@@ -23,7 +23,6 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Micr
.toolbar-strip select{padding:4px 8px;border:1px solid var(--app-border);border-radius:6px;font-size:12px;background:var(--app-bg);color:var(--app-text);cursor:pointer}
.toolbar-strip button{padding:5px 12px;border:1px solid var(--app-border);border-radius:6px;font-size:12px;font-weight:500;background:var(--app-card);color:var(--app-text);cursor:pointer;transition:all .15s;white-space:nowrap}
.toolbar-strip button:hover{background:var(--app-accent);color:#fff;border-color:var(--app-accent)}
.toolbar-strip button.accent{background:var(--app-accent);color:#fff;border-color:var(--app-accent)}
.toolbar-strip button.on{background:var(--app-accent);color:#fff;border-color:var(--app-accent)}
.toolbar-strip .spacer{flex:1}
@@ -37,6 +36,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Micr
.info-card .icon{font-size:22px;margin-bottom:6px}
.info-card h4{font-size:13px;font-weight:650;margin-bottom:3px}
.info-card p{font-size:12px;color:var(--app-text);opacity:.65;margin:0}
.footer{text-align:center;padding:28px 24px;font-size:13px;color:var(--app-text);opacity:.5}
.footer a{color:var(--app-accent);text-decoration:none}
@media(max-width:768px){.header h1{font-size:1.4rem}.toolbar-strip{padding:6px 10px;gap:4px}.toolbar-strip button{padding:4px 8px;font-size:11px}.info-grid{grid-template-columns:1fr 1fr}}
@@ -45,13 +45,13 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Micr
<body>
<header class="header">
<h1><span class="grad">Metona</span>Editor</h1>
<h1><span class="grad">Metona</span>Editor v0.2.0</h1>
<div class="badges">
<span class="badge">v0.2.0</span>
<span class="badge">TypeScript</span>
<span class="badge">583 tests</span>
<span class="badge">6 插件</span>
<span class="badge">中文优先</span>
<span class="badge">零运行时依赖</span>
<span class="badge">610 tests</span>
<span class="badge">6 个插件</span>
<span class="badge">桌面端优先</span>
</div>
</header>
@@ -67,11 +67,11 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Micr
<button data-cmd="mode" data-arg="preview">预览</button>
<div class="spacer"></div>
<button data-cmd="zen" title="Zen 专注模式">🧘 Zen</button>
<button data-cmd="outline" title="切换大纲面板">📋 大纲</button>
<button data-cmd="wrap" title="切换自动换行">↩ 换行</button>
<button data-cmd="toast" title="Toast 通知演示">💬 Toast</button>
<button data-cmd="openFile" title="打开磁盘文件">📂 打开</button>
<button data-cmd="saveFile" title="保存到磁盘">💾 保存</button>
<button data-cmd="outline" title="大纲面板">📋 大纲</button>
<button data-cmd="wrap" title="切换换行">↩ 换行</button>
<button data-cmd="toast" title="Toast 通知">💬 Toast</button>
<button data-cmd="openFile" title="打开文件">📂 打开</button>
<button data-cmd="saveFile" title="保存文件">💾 保存</button>
</div>
<div class="editor-section">
@@ -79,22 +79,18 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Micr
</div>
<div class="info-grid">
<div class="info-card"><div class="icon">🎨</div><h4>三重强调 + 链接内格式</h4><p>***粗斜体*** / [**粗体链接**](url) 等语法正确渲染 ← v0.1.15</p></div>
<div class="info-card"><div class="icon">🔧</div><h4>块级处理器表驱动</h4><p>registerBlockHandler 注册自定义语法,parseTokens/renderTokens 分离</p></div>
<div class="info-card"><div class="icon">📂</div><h4>磁盘文件读写</h4><p>File System Access API 打开/保存真实磁盘 .md 文件</p></div>
<div class="info-card"><div class="icon">🏗️</div><h4>TypeScript 全模块重构</h4><p>12 个 .ts 源文件,严格模式,完整类型导出</p></div>
<div class="info-card"><div class="icon">📝</div><h4>自研解析器 99% 行覆盖</h4><p>CommonMark + GFM:粗斜体、链接内格式、脚注、数学公式等</p></div>
<div class="info-card"><div class="icon">📂</div><h4>磁盘文件读写</h4><p>File System Access API 打开 / 保存真实 .md 文件</p></div>
<div class="info-card"><div class="icon">🔢</div><h4>行号装订线</h4><p>当前行高亮,与编辑区滚动同步</p></div>
<div class="info-card"><div class="icon">🧘</div><h4>Zen 专注模式</h4><p>工具栏自动隐藏,鼠标移到顶部滑入</p></div>
<div class="info-card"><div class="icon">⌨️</div><h4>快捷键面板</h4><p>按 ? 查看全部快捷键,Ctrl+F/H 搜索替换</p></div>
<div class="info-card"><div class="icon">📊</div><h4>Mermaid 图表</h4><p>```mermaid 代码块,加载 Mermaid.js 即可渲染</p></div>
<div class="info-card"><div class="icon">🔌</div><h4>6 个预设插件</h4><p>autoSave / exportTool / searchReplace / imagePaste / shortcutHelp / fileSystem</p></div>
<div class="info-card"><div class="icon">🛡️</div><h4>XSS 安全防护</h4><p>HTML 转义 · URL 协议过滤 · sanitize 钩子</p></div>
</div>
<footer class="footer">
MetonaEditor v0.1.15 ·
<a href="index.html">首页</a> ·
<a href="docs.html">API 文档</a> ·
<a href="https://git.metona.cn/MetonaTeam/MetonaEditor" target="_blank" rel="noopener">源码仓库</a> · MIT
MetonaEditor v0.2.0 · TypeScript · <a href="index.html">首页</a> · <a href="docs.html">API 文档</a> · <a href="https://git.metona.cn/MetonaTeam/MetonaEditor" target="_blank" rel="noopener">源码仓库</a> · MIT
</footer>
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
@@ -102,53 +98,60 @@ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Micr
<script>
(function(){
var demoMd=[
'# 🚀 MetonaEditor 全功能演示',
'# 🚀 MetonaEditor v0.2.0 全功能演示',
'',
'> 轻量、零依赖、中文优先的 **Markdown Editor** 库。',
'> 单文件打包,开箱即用。所有功能均在此页面启用。',
'> TypeScript 重构 · 零运行时依赖 · **桌面端** Markdown Editor 库。',
'> 全模块 TypeScript 严格模式,12 个源文件,610 个测试全部通过。',
'',
'## ✨ 核心特性',
'## ✨ v0.2.0 新特性',
'',
'- 语法高亮编辑区(源码实时着色',
'- 行号装订线 + 当前行高亮',
'- 智能 Enter(列表/引用自动延续)',
'- 括号/引号自动闭合',
'- 拖放图片/文件到编辑区',
'- Zen 专注模式 + 大纲面板',
'- 磁盘文件读写(File System Access API',
'- 6 个预设插件开箱即用',
'- TypeScript 全模块重构(严格模式 + 完整类型导出',
'- 解析器 99% 行覆盖率 · 表驱动块级处理器',
'- ***粗斜体*** / [**粗体链接**](https://example.com) 正确渲染',
'- 反斜杠转义 \\* \\_ \\\\ 支持',
'- parseTokens / renderTokens 解析渲染分离',
'- registerBlockHandler 自定义块语法注册',
'- 610 个测试 · 7 个套件全部通过',
'',
'## 📐 数学公式',
'## 📐 文本样式',
'',
'- **粗体** / __另一种粗体__',
'- ***粗斜体*** / ___另一种粗斜体___',
'- *斜体* / _另一种斜体_',
'- ~~删除线~~ / ==高亮标记==',
'- 链接内格式: [**粗体链接**](https://example.com)',
'- 化学:H~2~O / 数学:x^2^',
'- 代码:`const x = 42;`',
'- Emoji:smile: :rocket: :fire: :rainbow: :coffee:',
'',
'## 📊 数学公式 & 图表',
'',
'行内:$E = mc^2$',
'块级:$$\\int_{0}^{\\infty} e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}$$',
'',
'## 📊 Mermaid 图表(需加载 Mermaid.js',
'',
'```mermaid',
'graph TD',
' A[Markdown] --> B[解析器]',
' B --> C[HTML]',
' C --> D[预览]',
' A[TypeScript] --> B[Rollup]',
' B --> C[UMD/ESM/CJS]',
' C --> D[Browser]',
'```',
'',
'## 📋 表格与对齐',
'',
'| 版本 | 日期 | 测试 | 主题 |',
'| :--- | :---: | ---: | --- |',
'| v0.1.15 | 2026-07 | 558 | 三重强调+链接格式+转义+Token分离+块级表驱动 |',
'| v0.1.14 | 2026-07 | 535+ | 语法高亮+Mermaid+文件系统 |',
'| v0.1.12 | 2026-07 | 535 | A11y+Zen+滚动同步 |',
'| v0.1.7 | 2026-07 | 532 | 编辑体验 |',
'| v0.2.0 | 2026-07 | 610 | TypeScript 重构 |',
'| v0.1.15 | 2026-07 | 583 | 解析器增强 |',
'| v0.1.14 | 2026-07 | 535 | 语法高亮+Mermaid |',
'',
'## ✅ 任务列表',
'',
'- [x] 解析器增强(数学公式/脚注/嵌套列表等)',
'- [x] 主题系统(实例隔离 + 外部跟随)',
'- [x] 插件 v2 + i18n 增强',
'- [x] 编辑体验(行号/自动格式化/括号闭合)',
'- [x] 语法高亮 + 文件系统 + Mermaid',
'- [ ] vs-code 插件',
'- [x] TypeScript 全模块重构',
'- [x] 解析器 99% 行覆盖率',
'- [x] parseTokens / renderTokens 分离',
'- [x] registerBlockHandler 扩展',
'- [x] 6 个预设插件完整测试',
'- [ ] VS Code 扩展',
'',
'## 🎯 嵌套列表',
'',
@@ -162,28 +165,24 @@ var demoMd=[
'',
'## 💻 代码块',
'',
'```js',
'```ts',
'import MeEditor from "@metona-team/metona-editor";',
'',
'const editor = MeEditor.create("#editor", {',
' mode: "split",',
' syntaxHighlight: true,',
' theme: "dark",',
' lineNumbers: true,',
' autoBrackets: true,',
' plugins: ["autoSave","fileSystem","shortcutHelp"],',
' plugins: ["autoSave", "fileSystem", "shortcutHelp"],',
' onChange: (value, editor) => {',
' console.log("changed:", value.length, "chars");',
' },',
'});',
'',
'// 链式 API',
'editor.exec("bold").exec("h1").focus();',
'```',
'',
'## 🎨 文本样式',
'',
'- **粗体** / __另一种粗体__',
'- ***粗斜体*** / ___另一种粗斜体___ ← v0.1.15',
'- *斜体* / _另一种斜体_',
'- ~~删除线~~ / ==高亮标记==',
'- 链接内格式:[**粗体链接**](https://example.com) ← v0.1.15',
'- 化学:H~2~O / 数学:x^2^',
'- 代码:`const x = 42;`',
'- Emoji:smile: :rocket: :fire: :rainbow: :coffee: :hamburger:',
'',
'## 📌 脚注',
'',
'这是一个带脚注的句子[^1],另一个脚注[^note]。',
@@ -193,86 +192,78 @@ var demoMd=[
'',
'---',
'',
'> **提示:** 按 `?` 查看快捷键 · 拖放图片到编辑区 · Ctrl+F 搜索 · Ctrl+H 替换',
'> **提示:** 按 `?` 查看快捷键 · 拖放文件到编辑区 · Ctrl+F 查找 · Ctrl+H 替换',
'> 在列表行尾 Enter 体验智能延续 · 选中文字后按 `(` 体验自动包裹',
'> 点击「打开」按钮加载磁盘 .md 文件 · 点击「保存」写入磁盘',
'> 点击「📂 打开」加载磁盘 .md 文件 · 点击「💾 保存」写入磁盘',
].join('\n');
var editor=MeEditor.create('#editor',{
value:demoMd,
mode:'split',height:620,
lineNumbers:true,autoBrackets:true,wordCount:true,
theme:'auto',locale:'zh-CN',
outline:false,
plugins:['autoSave','exportTool','searchReplace','imagePaste','shortcutHelp','fileSystem'],
onLinkClick:function(uri,text,ed){
ed.toast('链接: '+uri,{type:'info',duration:2000});
var editor = MeEditor.create('#editor',{
value: demoMd,
mode: 'split', height: 620,
lineNumbers: true, autoBrackets: true, wordCount: true,
theme: 'auto', locale: 'zh-CN', outline: false,
plugins: ['autoSave','exportTool','searchReplace','imagePaste','shortcutHelp','fileSystem'],
onLinkClick: function(uri, text, ed){
ed.toast('链接: ' + uri, { type: 'info', duration: 2000 });
}
});
// ===== 控制栏按钮 =====
var bar=document.getElementById('bar');
// Control bar
var bar = document.getElementById('bar');
// 主题
document.getElementById('selTheme').addEventListener('change',function(){
document.getElementById('selTheme').addEventListener('change', function(){
editor.setTheme(this.value);
});
// 语言
document.getElementById('selLocale').addEventListener('change',function(){
document.getElementById('selLocale').addEventListener('change', function(){
editor.setLocale(this.value);
});
// 通用按钮
bar.addEventListener('click',function(e){
var btn=e.target.closest('button[data-cmd]');
if(!btn)return;
var cmd=btn.dataset.cmd;
if(cmd==='mode'){editor.setMode(btn.dataset.arg);updateModeBtns(btn.dataset.arg);}
else if(cmd==='zen'){editor.toggleZen();btn.classList.toggle('on',editor.isZen());}
else if(cmd==='outline'){toggleOutline(btn);}
else if(cmd==='wrap'){editor.toggleWordWrap();btn.classList.toggle('on',!editor.isWordWrap());}
else if(cmd==='toast'){
var types=['success','error','warning','info'];
var msgs={success:'✅ 操作成功',error:'❌ 操作失败',warning:'⚠️ 注意',info:'️ 提示信息'};
var t=types[Math.floor(Math.random()*4)];
editor.toast(msgs[t],{type:t,duration:2000});
bar.addEventListener('click', function(e){
var btn = e.target.closest('button[data-cmd]');
if (!btn) return;
var cmd = btn.dataset.cmd;
if (cmd === 'mode') { editor.setMode(btn.dataset.arg); updateModeBtns(btn.dataset.arg); }
else if (cmd === 'zen') { editor.toggleZen(); btn.classList.toggle('on', editor.isZen()); }
else if (cmd === 'outline') { toggleOutline(btn); }
else if (cmd === 'wrap') { editor.toggleWordWrap(); btn.classList.toggle('on', !editor.isWordWrap()); }
else if (cmd === 'toast') {
var types = ['success','error','warning','info'];
var msgs = { success: '✅ 操作成功', error: '❌ 操作失败', warning: '⚠️ 注意', info: '️ 提示信息' };
editor.toast(msgs[types[Math.floor(Math.random()*4)]], { type: types[Math.floor(Math.random()*4)], duration: 2000 });
}
else if(cmd==='openFile'){editor.openFile?.();}
else if(cmd==='saveFile'){editor.saveFile?.();}
else if (cmd === 'openFile') { editor.openFile?.(); }
else if (cmd === 'saveFile') { editor.saveFile?.(); }
});
function updateModeBtns(mode){
bar.querySelectorAll('[data-cmd=mode]').forEach(function(b){b.classList.toggle('on',b.dataset.arg===mode)});
bar.querySelectorAll('[data-cmd=mode]').forEach(function(b){ b.classList.toggle('on', b.dataset.arg === mode); });
}
function toggleOutline(btn){
editor.config.outline=!editor.config.outline;
if(editor.config.outline){editor._buildOutline();btn.classList.add('on')}
else{var p=editor.el.querySelector('.me-outline');if(p)p.remove();btn.classList.remove('on')}
editor.config.outline = !editor.config.outline;
if (editor.config.outline) { editor._buildOutline(); btn.classList.add('on'); }
else { var p = editor.el.querySelector('.me-outline'); if (p) p.remove(); btn.classList.remove('on'); }
}
// 快捷键
editor.registerShortcut('Ctrl+Shift+T',function(){
editor.toast('自定义快捷键已触发!',{type:'info'});
},'Toast 通知演示');
// Custom shortcut
editor.registerShortcut('Ctrl+Shift+T', function(){
editor.toast('自定义快捷键已触发!', { type: 'info' });
}, 'Toast 通知演示');
// 事件监听
editor.on('themeChange',function(d){document.getElementById('selTheme').value=d.theme});
editor.on('modeChange',function(m){updateModeBtns(m)});
editor.on('fileOpened',function(d){editor.toast('已打开: '+d.name,{type:'success'})});
editor.on('fileSaved',function(){editor.toast('文件已保存',{type:'success'})});
editor.on('linkClick',function(d){editor.toast('链接点击: '+d.href,{type:'info',duration:1500})});
// Events
editor.on('themeChange', function(d){ document.getElementById('selTheme').value = d.theme; });
editor.on('modeChange', function(m){ updateModeBtns(m); });
editor.on('fileOpened', function(d){ editor.toast('已打开: ' + d.name, { type: 'success' }); });
editor.on('fileSaved', function(){ editor.toast('文件已保存', { type: 'success' }); });
// Mermaid 图表渲染(v0.1.14
// Mermaid
function renderMermaid(){
if(typeof mermaid==='undefined')return;
try{mermaid.run({querySelector:'.me-mermaid .mermaid'})}catch(e){}
if (typeof mermaid === 'undefined') return;
try { mermaid.run({ querySelector: '.me-mermaid .mermaid' }); } catch(e) {}
}
mermaid.initialize({startOnLoad:false,theme:'default'});
editor.on('afterRender',renderMermaid);
setTimeout(renderMermaid,300);
mermaid.initialize({ startOnLoad: false, theme: 'default' });
editor.on('afterRender', renderMermaid);
setTimeout(renderMermaid, 300);
})();
</script>
</body>