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:
+75
-84
@@ -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"],',
|
||||
' 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,37 +192,32 @@ 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,
|
||||
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 });
|
||||
}
|
||||
});
|
||||
|
||||
// ===== 控制栏按钮 =====
|
||||
// Control bar
|
||||
var bar = document.getElementById('bar');
|
||||
|
||||
// 主题
|
||||
document.getElementById('selTheme').addEventListener('change', function(){
|
||||
editor.setTheme(this.value);
|
||||
});
|
||||
|
||||
// 语言
|
||||
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;
|
||||
@@ -235,44 +229,41 @@ bar.addEventListener('click',function(e){
|
||||
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});
|
||||
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?.(); }
|
||||
});
|
||||
|
||||
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')}
|
||||
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'); }
|
||||
}
|
||||
|
||||
// 快捷键
|
||||
// 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){}
|
||||
try { mermaid.run({ querySelector: '.me-mermaid .mermaid' }); } catch(e) {}
|
||||
}
|
||||
mermaid.initialize({ startOnLoad: false, theme: 'default' });
|
||||
editor.on('afterRender', renderMermaid);
|
||||
setTimeout(renderMermaid, 300);
|
||||
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
+243
-478
@@ -4,179 +4,68 @@
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📖</text></svg>"/>
|
||||
<title>MetonaEditor · 文档</title>
|
||||
<title>MetonaEditor v0.2.0 · 文档</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
:root {
|
||||
--bg: #0f1117;
|
||||
--bg-soft: #161922;
|
||||
--card: #1c2029;
|
||||
--card-hover: #232834;
|
||||
--text: #e6e8eb;
|
||||
--muted: #9ca3af;
|
||||
--accent: #3b82f6;
|
||||
--accent-2: #8b5cf6;
|
||||
--accent-3: #ec4899;
|
||||
--accent-soft: rgba(59, 130, 246, 0.12);
|
||||
--border: rgba(255, 255, 255, 0.08);
|
||||
--gradient: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 50%, #ec4899 100%);
|
||||
--shadow: 0 20px 50px -20px rgba(0,0,0,0.5);
|
||||
}
|
||||
html { scroll-behavior: smooth; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.7;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.container { max-width: 1000px; margin: 0 auto; padding: 0 24px; }
|
||||
*{box-sizing:border-box;margin:0;padding:0}
|
||||
:root{--bg:#0f1117;--bg-soft:#161922;--card:#1c2029;--card-hover:#232834;--text:#e6e8eb;--muted:#9ca3af;--accent:#3b82f6;--accent-2:#8b5cf6;--accent-soft:rgba(59,130,246,.12);--border:rgba(255,255,255,.08);--gradient:linear-gradient(135deg,#3b82f6 0%,#8b5cf6 50%,#ec4899 100%)}
|
||||
html{scroll-behavior:smooth}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:var(--bg);color:var(--text);line-height:1.7;min-height:100vh}
|
||||
.container{max-width:1000px;margin:0 auto;padding:0 24px}
|
||||
nav{position:sticky;top:0;z-index:100;background:rgba(15,17,23,.85);backdrop-filter:blur(16px);border-bottom:1px solid var(--border)}
|
||||
.nav-inner{max-width:1000px;margin:0 auto;padding:12px 24px;display:flex;align-items:center;justify-content:space-between}
|
||||
.nav-brand{display:inline-flex;align-items:center;gap:10px;text-decoration:none;color:var(--text);font-weight:700;font-size:15px}
|
||||
.nav-brand .logo-mark{width:26px;height:26px;border-radius:6px;background:var(--gradient);display:flex;align-items:center;justify-content:center;flex-shrink:0}
|
||||
.logo-mark svg{display:block}
|
||||
.nav-links{display:flex;gap:22px;align-items:center}
|
||||
.nav-links a{color:var(--muted);text-decoration:none;font-size:13.5px;transition:color .15s}
|
||||
.nav-links a:hover,.nav-links a.active{color:var(--text)}
|
||||
.nav-links a.active{color:var(--accent);font-weight:600}
|
||||
|
||||
/* Nav */
|
||||
nav {
|
||||
position: sticky; top: 0; z-index: 100;
|
||||
background: rgba(15, 17, 23, 0.85);
|
||||
backdrop-filter: blur(16px);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.nav-inner {
|
||||
max-width: 1000px; margin: 0 auto; padding: 12px 24px;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
}
|
||||
.nav-brand {
|
||||
display: inline-flex; align-items: center; gap: 10px;
|
||||
text-decoration: none; color: var(--text);
|
||||
font-weight: 700; font-size: 15px;
|
||||
}
|
||||
.nav-brand .logo-mark {
|
||||
width: 26px; height: 26px; border-radius: 6px;
|
||||
background: var(--gradient);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.logo-mark svg { display: block; }
|
||||
.nav-links { display: flex; gap: 22px; align-items: center; }
|
||||
.nav-links a { color: var(--muted); text-decoration: none; font-size: 13.5px; transition: color .15s; }
|
||||
.nav-links a:hover, .nav-links a.active { color: var(--text); }
|
||||
.nav-links a.active { color: var(--accent); font-weight: 600; }
|
||||
header.docs-header{text-align:center;padding:64px 24px 40px;background:radial-gradient(ellipse 60% 50% at 50% 0%,var(--accent-soft),transparent 70%),var(--bg)}
|
||||
header h1{font-size:clamp(28px,4vw,44px);font-weight:800;letter-spacing:-.02em;margin-bottom:10px}
|
||||
header h1 .grad{background:var(--gradient);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
||||
header .sub{color:var(--muted);font-size:15px}
|
||||
|
||||
/* Header */
|
||||
header.docs-header {
|
||||
text-align: center; padding: 64px 24px 40px;
|
||||
background: radial-gradient(ellipse 60% 50% at 50% 0%, var(--accent-soft), transparent 70%), var(--bg);
|
||||
}
|
||||
header h1 { font-size: clamp(28px, 4vw, 44px); font-weight: 800; letter-spacing: -0.02em; margin-bottom: 10px; }
|
||||
header h1 .grad { background: var(--gradient); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
|
||||
header .sub { color: var(--muted); font-size: 15px; }
|
||||
.docs-layout{display:flex;gap:32px;padding:40px 0 80px}
|
||||
.sidebar{position:sticky;top:72px;width:200px;flex-shrink:0;max-height:calc(100vh - 100px);overflow-y:auto;padding-right:16px;border-right:1px solid var(--border)}
|
||||
.sidebar a{display:block;padding:6px 12px;border-radius:6px;color:var(--muted);text-decoration:none;font-size:13.5px;transition:background .15s,color .15s;margin-bottom:2px}
|
||||
.sidebar a:hover,.sidebar a.active{background:var(--card);color:var(--text)}
|
||||
.sidebar .toc-group{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;padding:16px 12px 6px;font-weight:600}
|
||||
.content{flex:1;min-width:0}
|
||||
.content section{margin-bottom:48px}
|
||||
.content h2{font-size:24px;font-weight:700;letter-spacing:-.02em;margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid var(--border)}
|
||||
.content h3{font-size:18px;font-weight:600;margin:28px 0 14px}
|
||||
.content h4{font-size:15px;font-weight:600;margin:20px 0 10px;color:var(--accent)}
|
||||
|
||||
/* Sidebar + Content Layout */
|
||||
.docs-layout { display: flex; gap: 32px; padding: 40px 0 80px; }
|
||||
.sidebar {
|
||||
position: sticky; top: 72px;
|
||||
width: 200px; flex-shrink: 0;
|
||||
max-height: calc(100vh - 100px); overflow-y: auto;
|
||||
padding-right: 16px;
|
||||
border-right: 1px solid var(--border);
|
||||
}
|
||||
.sidebar a {
|
||||
display: block; padding: 6px 12px; border-radius: 6px;
|
||||
color: var(--muted); text-decoration: none; font-size: 13.5px;
|
||||
transition: background .15s, color .15s;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.sidebar a:hover, .sidebar a.active { background: var(--card); color: var(--text); }
|
||||
.sidebar .toc-group { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; padding: 16px 12px 6px; font-weight: 600; }
|
||||
.content { flex: 1; min-width: 0; }
|
||||
.content section { margin-bottom: 48px; }
|
||||
.content h2 {
|
||||
font-size: 24px; font-weight: 700; letter-spacing: -0.02em;
|
||||
margin-bottom: 16px; padding-bottom: 10px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.content h3 { font-size: 18px; font-weight: 600; margin: 28px 0 14px; }
|
||||
.content h4 { font-size: 15px; font-weight: 600; margin: 20px 0 10px; color: var(--accent); }
|
||||
table{width:100%;border-collapse:collapse;margin:16px 0;font-size:13.5px}
|
||||
th,td{padding:10px 14px;text-align:left;border:1px solid var(--border)}
|
||||
th{background:var(--card);font-weight:600;color:var(--text)}
|
||||
td{color:var(--muted)}
|
||||
tr:nth-child(even) td{background:var(--bg-soft)}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
width: 100%; border-collapse: collapse; margin: 16px 0; font-size: 13.5px;
|
||||
}
|
||||
th, td {
|
||||
padding: 10px 14px; text-align: left;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
th { background: var(--card); font-weight: 600; color: var(--text); }
|
||||
td { color: var(--muted); }
|
||||
tr:nth-child(even) td { background: var(--bg-soft); }
|
||||
code{font-family:"SF Mono","Cascadia Code",Consolas,monospace;font-size:13px;padding:2px 6px;background:var(--card);border:1px solid var(--border);border-radius:4px;color:var(--accent)}
|
||||
pre{background:var(--bg-soft);border:1px solid var(--border);border-radius:10px;padding:18px 20px;overflow-x:auto;font-family:"SF Mono","Cascadia Code",Consolas,monospace;font-size:13px;line-height:1.8;color:#e6e8eb;margin:14px 0}
|
||||
.c-key{color:#c792ea}.c-str{color:#c3e88d}.c-fn{color:#82aaff}.c-com{color:#5c6370;font-style:italic}.c-kw{color:#89ddff}.c-num{color:#f78c6c}.c-punc{color:#89ddff;opacity:.7}
|
||||
.badge{display:inline-block;padding:3px 10px;background:var(--accent-soft);color:var(--accent);border-radius:999px;font-size:12px;font-weight:600;margin-right:6px;margin-bottom:4px}
|
||||
|
||||
/* Code */
|
||||
code {
|
||||
font-family: "SF Mono", "Cascadia Code", Consolas, monospace;
|
||||
font-size: 13px; padding: 2px 6px;
|
||||
background: var(--card); border: 1px solid var(--border);
|
||||
border-radius: 4px; color: var(--accent);
|
||||
}
|
||||
pre {
|
||||
background: var(--bg-soft); border: 1px solid var(--border);
|
||||
border-radius: 10px; padding: 18px 20px; overflow-x: auto;
|
||||
font-family: "SF Mono", "Cascadia Code", Consolas, monospace;
|
||||
font-size: 13px; line-height: 1.8;
|
||||
color: #e6e8eb; margin: 14px 0;
|
||||
}
|
||||
pre .c-key { color: #c792ea; }
|
||||
pre .c-str { color: #c3e88d; }
|
||||
pre .c-fn { color: #82aaff; }
|
||||
pre .c-com { color: #5c6370; font-style: italic; }
|
||||
pre .c-kw { color: #89ddff; }
|
||||
pre .c-num { color: #f78c6c; }
|
||||
pre .c-punc { color: #89ddff; opacity: 0.7; }
|
||||
footer{border-top:1px solid var(--border);padding:36px 24px;text-align:center;color:var(--muted);font-size:13px;background:var(--bg-soft)}
|
||||
footer a{color:var(--accent);text-decoration:none}
|
||||
|
||||
/* Badges */
|
||||
.badge {
|
||||
display: inline-block; padding: 3px 10px;
|
||||
background: var(--accent-soft); color: var(--accent);
|
||||
border-radius: 999px; font-size: 12px; font-weight: 600;
|
||||
margin-right: 6px; margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
border-top: 1px solid var(--border); padding: 36px 24px;
|
||||
text-align: center; color: var(--muted); font-size: 13px;
|
||||
background: var(--bg-soft);
|
||||
}
|
||||
footer a { color: var(--accent); text-decoration: none; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.docs-layout { flex-direction: column; }
|
||||
.sidebar {
|
||||
position: static; width: 100%; max-height: none;
|
||||
border-right: 0; border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 12px;
|
||||
display: flex; flex-wrap: wrap; gap: 4px;
|
||||
}
|
||||
.sidebar .toc-group { width: 100%; }
|
||||
}
|
||||
@media(max-width:768px){.docs-layout{flex-direction:column}.sidebar{position:static;width:100%;max-height:none;border-right:0;border-bottom:1px solid var(--border);padding-bottom:12px;display:flex;flex-wrap:wrap;gap:4px}.sidebar .toc-group{width:100%}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav>
|
||||
<div class="nav-inner">
|
||||
<a class="nav-brand" href="index.html">
|
||||
<span class="logo-mark" title="MetonaEditor"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19V6l7 8 7-8v13"/></svg></span>
|
||||
MetonaEditor
|
||||
</a>
|
||||
<div class="nav-links">
|
||||
<a href="index.html">首页</a>
|
||||
<a href="demo.html">演示</a>
|
||||
<a href="docs.html" class="active">文档</a>
|
||||
</div>
|
||||
<a class="nav-brand" href="index.html"><span class="logo-mark"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19V6l7 8 7-8v13"/></svg></span>MetonaEditor</a>
|
||||
<div class="nav-links"><a href="index.html">首页</a><a href="demo.html">演示</a><a href="docs.html" class="active">文档</a></div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<header class="docs-header">
|
||||
<h1><span class="grad">文档</span></h1>
|
||||
<p class="sub">MetonaEditor v0.1.15 完整 API、配置与使用指南</p>
|
||||
<h1><span class="grad">API 文档</span></h1>
|
||||
<p class="sub">MetonaEditor v0.2.0 · TypeScript · 完整配置、API 与使用指南</p>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
@@ -191,19 +80,20 @@
|
||||
<a href="#api-content">内容操作</a>
|
||||
<a href="#api-exec">命令执行</a>
|
||||
<a href="#api-history">历史栈</a>
|
||||
<a href="#api-mode">模式与全屏</a>
|
||||
<a href="#api-mode">模式 / 全屏 / Zen</a>
|
||||
<a href="#api-stats">统计与状态</a>
|
||||
<a href="#api-readonly">启用 / 禁用 / 只读</a>
|
||||
<a href="#api-events">事件系统</a>
|
||||
<a href="#api-plugin">插件管理</a>
|
||||
<a href="#api-lifecycle">生命周期</a>
|
||||
<a href="#api-shortcuts">快捷键管理</a>
|
||||
<a href="#api-destroy">生命周期</a>
|
||||
<div class="toc-group">静态 API</div>
|
||||
<a href="#static-api">顶层函数</a>
|
||||
<div class="toc-group">语法参考</div>
|
||||
<a href="#syntax">解析器语法</a>
|
||||
<a href="#parser-api">解析器 API(v0.1.15)</a>
|
||||
<a href="#static-api">全局函数</a>
|
||||
<div class="toc-group">解析器</div>
|
||||
<a href="#parser-syntax">语法参考</a>
|
||||
<a href="#parser-api">解析器 API</a>
|
||||
<div class="toc-group">插件</div>
|
||||
<a href="#plugins">插件约定</a>
|
||||
<a href="#plugins-convention">插件约定</a>
|
||||
<a href="#preset-plugins">预设插件</a>
|
||||
<div class="toc-group">主题</div>
|
||||
<a href="#themes">主题系统</a>
|
||||
@@ -213,94 +103,77 @@
|
||||
|
||||
<main class="content">
|
||||
|
||||
<!-- ======== 快速入门 ======== -->
|
||||
<!-- 快速入门 -->
|
||||
<section id="quickstart">
|
||||
<h2>安装与引入</h2>
|
||||
|
||||
<pre><span class="c-com"># npm 安装</span>
|
||||
<span class="c-kw">npm</span> install @metona-team/metona-editor
|
||||
|
||||
<span class="c-com"># ES Module</span>
|
||||
<span class="c-com">// TypeScript / ES Module</span>
|
||||
<span class="c-kw">import</span> MeEditor <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span>
|
||||
<span class="c-kw">const</span> editor <span class="c-punc">=</span> MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span><span class="c-str">'#editor'</span><span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
<span class="c-fn">value</span><span class="c-punc">:</span> <span class="c-str">'# Hello World'</span><span class="c-punc">,</span>
|
||||
<span class="c-fn">mode</span><span class="c-punc">:</span> <span class="c-str">'split'</span><span class="c-punc">,</span>
|
||||
<span class="c-punc">});</span>
|
||||
|
||||
<span class="c-com"># 浏览器 UMD</span>
|
||||
<span class="c-com">// 浏览器 UMD</span>
|
||||
<span class="c-com"><script src="dist/metona-editor.js"></script></span>
|
||||
<span class="c-com"><script></span>
|
||||
<span class="c-kw">const</span> editor <span class="c-punc">=</span> MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span><span class="c-str">'#editor'</span><span class="c-punc">);</span>
|
||||
<span class="c-com"></script></span></pre>
|
||||
</section>
|
||||
|
||||
<!-- ======== 配置项 ======== -->
|
||||
<!-- 配置 -->
|
||||
<section id="config">
|
||||
<h2>全部配置项</h2>
|
||||
<p style="color:var(--muted);margin-bottom:14px">所有配置均为可选,以下是默认值:</p>
|
||||
|
||||
<p style="color:var(--muted);margin-bottom:14px">所有配置均为可选。</p>
|
||||
<pre>MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span>container<span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
<span class="c-com">// 内容</span>
|
||||
value<span class="c-punc">:</span> <span class="c-str">''</span><span class="c-punc">,</span> <span class="c-com">// 初始 Markdown 文本</span>
|
||||
placeholder<span class="c-punc">:</span> <span class="c-str">''</span><span class="c-punc">,</span> <span class="c-com">// 占位符</span>
|
||||
value<span class="c-punc">:</span> <span class="c-str">''</span><span class="c-punc">,</span> placeholder<span class="c-punc">:</span> <span class="c-str">''</span><span class="c-punc">,</span>
|
||||
|
||||
<span class="c-com">// 视图</span>
|
||||
mode<span class="c-punc">:</span> <span class="c-str">'split'</span><span class="c-punc">,</span> <span class="c-com">// 'edit' | 'split' | 'preview'</span>
|
||||
height<span class="c-punc">:</span> <span class="c-num">400</span><span class="c-punc">,</span> <span class="c-com">// 数字为 px,字符串原样使用</span>
|
||||
toolbar<span class="c-punc">:</span> DEFAULT_TOOLBAR<span class="c-punc">,</span> <span class="c-com">// 工具栏配置,false 隐藏</span>
|
||||
wordCount<span class="c-punc">:</span> <span class="c-kw">true</span><span class="c-punc">,</span> <span class="c-com">// 字数统计状态栏</span>
|
||||
mode<span class="c-punc">:</span> <span class="c-str">'split'</span><span class="c-punc">,</span> height<span class="c-punc">:</span> <span class="c-num">400</span><span class="c-punc">,</span>
|
||||
toolbar<span class="c-punc">:</span> DEFAULT_TOOLBAR<span class="c-punc">,</span> wordCount<span class="c-punc">:</span> <span class="c-kw">true</span><span class="c-punc">,</span>
|
||||
lineNumbers<span class="c-punc">:</span> <span class="c-kw">true</span><span class="c-punc">,</span> outline<span class="c-punc">:</span> <span class="c-kw">false</span><span class="c-punc">,</span>
|
||||
|
||||
<span class="c-com">// 行为</span>
|
||||
autofocus<span class="c-punc">:</span> <span class="c-kw">false</span><span class="c-punc">,</span> <span class="c-com">// 自动聚焦</span>
|
||||
spellcheck<span class="c-punc">:</span> <span class="c-kw">false</span><span class="c-punc">,</span> <span class="c-com">// 拼写检查</span>
|
||||
readOnly<span class="c-punc">:</span> <span class="c-kw">false</span><span class="c-punc">,</span> <span class="c-com">// 只读模式</span>
|
||||
historyLimit<span class="c-punc">:</span> <span class="c-num">100</span><span class="c-punc">,</span> <span class="c-com">// 历史栈上限</span>
|
||||
historyDebounce<span class="c-punc">:</span> <span class="c-num">400</span><span class="c-punc">,</span> <span class="c-com">// 历史防抖延迟(ms)</span>
|
||||
syncScroll<span class="c-punc">:</span> <span class="c-kw">true</span><span class="c-punc">,</span> <span class="c-com">// 分屏模式同步滚动</span>
|
||||
tabSize<span class="c-punc">:</span> <span class="c-num">2</span><span class="c-punc">,</span> <span class="c-com">// 制表符空格数(0 表示 \t)</span>
|
||||
autofocus<span class="c-punc">:</span> <span class="c-kw">false</span><span class="c-punc">,</span> spellcheck<span class="c-punc">:</span> <span class="c-kw">false</span><span class="c-punc">,</span>
|
||||
readOnly<span class="c-punc">:</span> <span class="c-kw">false</span><span class="c-punc">,</span> tabSize<span class="c-punc">:</span> <span class="c-num">2</span><span class="c-punc">,</span>
|
||||
historyLimit<span class="c-punc">:</span> <span class="c-num">100</span><span class="c-punc">,</span> historyDebounce<span class="c-punc">:</span> <span class="c-num">400</span><span class="c-punc">,</span>
|
||||
syncScroll<span class="c-punc">:</span> <span class="c-kw">true</span><span class="c-punc">,</span> autoBrackets<span class="c-punc">:</span> <span class="c-kw">true</span><span class="c-punc">,</span>
|
||||
zenMode<span class="c-punc">:</span> <span class="c-kw">false</span><span class="c-punc">,</span> wordWrap<span class="c-punc">:</span> <span class="c-kw">true</span><span class="c-punc">,</span>
|
||||
|
||||
<span class="c-com">// 主题与国际化</span>
|
||||
theme<span class="c-punc">:</span> <span class="c-str">'auto'</span><span class="c-punc">,</span> <span class="c-com">// 'light' | 'dark' | 'auto' | 'warm' | 自定义</span>
|
||||
locale<span class="c-punc">:</span> <span class="c-str">'zh-CN'</span><span class="c-punc">,</span> <span class="c-com">// 'zh-CN' | 'en-US' | 自定义</span>
|
||||
<span class="c-com">// 主题 / 语言</span>
|
||||
theme<span class="c-punc">:</span> <span class="c-str">'auto'</span><span class="c-punc">,</span> locale<span class="c-punc">:</span> <span class="c-str">'zh-CN'</span><span class="c-punc">,</span>
|
||||
|
||||
<span class="c-com">// 自定义渲染</span>
|
||||
render<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (md, env) => html</span>
|
||||
highlight<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (code, lang) => html</span>
|
||||
sanitize<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (html) => safeHtml</span>
|
||||
<span class="c-com">// 钩子</span>
|
||||
render<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> highlight<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span>
|
||||
sanitize<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span>
|
||||
|
||||
<span class="c-com">// 外观</span>
|
||||
className<span class="c-punc">:</span> <span class="c-str">''</span><span class="c-punc">,</span> <span class="c-com">// 容器额外 class</span>
|
||||
style<span class="c-punc">:</span> <span class="c-punc">{},</span> <span class="c-com">// 内联样式</span>
|
||||
className<span class="c-punc">:</span> <span class="c-str">''</span><span class="c-punc">,</span> style<span class="c-punc">:</span> <span class="c-punc">{},</span>
|
||||
|
||||
<span class="c-com">// 插件与回调</span>
|
||||
plugins<span class="c-punc">:</span> <span class="c-punc">[],</span> <span class="c-com">// 实例级插件数组</span>
|
||||
onChange<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (value, editor) => void</span>
|
||||
onInput<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (value, editor) => void</span>
|
||||
onFocus<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (editor) => void</span>
|
||||
onBlur<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (editor) => void</span>
|
||||
onSave<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (value, editor) => void</span>
|
||||
onModeChange<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (mode, editor) => void</span>
|
||||
onFullscreen<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (fullscreen, editor) => void</span>
|
||||
onCreate<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (editor) => void</span>
|
||||
onDestroy<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> <span class="c-com">// (editor) => void</span>
|
||||
<span class="c-com">// 插件 / 回调</span>
|
||||
plugins<span class="c-punc">:</span> <span class="c-punc">[],</span>
|
||||
onChange<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> onInput<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span>
|
||||
onFocus<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> onBlur<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span>
|
||||
onSave<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> onModeChange<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span>
|
||||
onFullscreen<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> onCreate<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span>
|
||||
onDestroy<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span> onLinkClick<span class="c-punc">:</span> <span class="c-kw">null</span><span class="c-punc">,</span>
|
||||
<span class="c-punc">});</span></pre>
|
||||
</section>
|
||||
|
||||
<!-- ======== 工具栏 ======== -->
|
||||
<!-- 工具栏 -->
|
||||
<section id="toolbar">
|
||||
<h2>工具栏配置</h2>
|
||||
|
||||
<pre><span class="c-com">// 默认工具栏(完整按钮)</span>
|
||||
<h2>工具栏</h2>
|
||||
<pre><span class="c-com">// 默认完整工具栏</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span>container<span class="c-punc">,</span> <span class="c-punc">{</span> toolbar<span class="c-punc">:</span> <span class="c-kw">true</span> <span class="c-punc">});</span>
|
||||
|
||||
<span class="c-com">// 隐藏工具栏</span>
|
||||
<span class="c-com">// 隐藏</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span>container<span class="c-punc">,</span> <span class="c-punc">{</span> toolbar<span class="c-punc">:</span> <span class="c-kw">false</span> <span class="c-punc">});</span>
|
||||
|
||||
<span class="c-com">// 自定义工具栏 — '|' 为分隔符</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span>container<span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
toolbar<span class="c-punc">:</span> <span class="c-punc">[</span><span class="c-str">'bold'</span><span class="c-punc">,</span> <span class="c-str">'italic'</span><span class="c-punc">,</span> <span class="c-str">'|'</span><span class="c-punc">,</span> <span class="c-str">'h1'</span><span class="c-punc">,</span> <span class="c-str">'h2'</span><span class="c-punc">,</span> <span class="c-str">'|'</span><span class="c-punc">,</span> <span class="c-str">'undo'</span><span class="c-punc">,</span> <span class="c-str">'redo'</span><span class="c-punc">],</span>
|
||||
<span class="c-punc">});</span></pre>
|
||||
|
||||
<span class="c-com">// 自定义 | 为分隔符</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span>container<span class="c-punc">,</span> <span class="c-punc">{</span> toolbar<span class="c-punc">:</span> <span class="c-punc">[</span><span class="c-str">'bold'</span><span class="c-punc">,</span> <span class="c-str">'italic'</span><span class="c-punc">,</span> <span class="c-str">'|'</span><span class="c-punc">,</span> <span class="c-str">'undo'</span><span class="c-punc">,</span> <span class="c-str">'redo'</span><span class="c-punc">]</span> <span class="c-punc">});</span></pre>
|
||||
<p>可用动作:</p>
|
||||
<p>
|
||||
<span class="badge">bold</span><span class="badge">italic</span><span class="badge">strikethrough</span><span class="badge">underline</span><span class="badge">code</span>
|
||||
@@ -312,346 +185,244 @@ MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- ======== 实例 API ======== -->
|
||||
<section id="api-content">
|
||||
<h2>实例 API</h2>
|
||||
|
||||
<!-- 实例 API -->
|
||||
<section id="api-content"><h2>实例 API</h2>
|
||||
<h3>内容操作</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">getValue</span><span class="c-punc">();</span> <span class="c-com">// 获取 Markdown 文本</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">setValue</span><span class="c-punc">(</span>md<span class="c-punc">,</span> <span class="c-punc">{</span> silent <span class="c-punc">});</span> <span class="c-com">// 设置内容,silent 不触发 change</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getHTML</span><span class="c-punc">();</span> <span class="c-com">// 获取渲染后的 HTML</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">refresh</span><span class="c-punc">();</span> <span class="c-com">// 强制刷新预览(内容未变时)</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">insert</span><span class="c-punc">(</span>text<span class="c-punc">,</span> <span class="c-punc">{</span> replace <span class="c-punc">});</span> <span class="c-com">// 光标处插入 / 替换选区</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">wrap</span><span class="c-punc">(</span>before<span class="c-punc">,</span> after<span class="c-punc">);</span> <span class="c-com">// 选区包裹</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">focus</span><span class="c-punc">();</span> <span class="c-com">// 聚焦</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">blur</span><span class="c-punc">();</span> <span class="c-com">// 失焦</span></pre>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">getValue</span><span class="c-punc">();</span> <span class="c-com">// => string</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">setValue</span><span class="c-punc">(</span>md<span class="c-punc">,</span> <span class="c-punc">{</span> silent <span class="c-punc">});</span> <span class="c-com">// => this</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getHTML</span><span class="c-punc">();</span> <span class="c-com">// => string</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">refresh</span><span class="c-punc">();</span> <span class="c-com">// 强制重渲染</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">insert</span><span class="c-punc">(</span>text<span class="c-punc">,</span> <span class="c-punc">{</span> replace <span class="c-punc">});</span> <span class="c-com">// => this</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">wrap</span><span class="c-punc">(</span>before<span class="c-punc">,</span> after<span class="c-punc">);</span> <span class="c-com">// => this</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">focus</span><span class="c-punc">();</span> <span class="c-fn">blur</span><span class="c-punc">();</span></pre>
|
||||
</section>
|
||||
|
||||
<section id="api-exec">
|
||||
<h3>命令执行</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">exec</span><span class="c-punc">(</span>action<span class="c-punc">,</span> <span class="c-punc">...</span>args<span class="c-punc">);</span> <span class="c-com">// 执行命令,返回 this 链式调用</span>
|
||||
|
||||
editor<span class="c-punc">.</span><span class="c-fn">exec</span><span class="c-punc">(</span><span class="c-str">'bold'</span><span class="c-punc">).</span><span class="c-fn">exec</span><span class="c-punc">(</span><span class="c-str">'h1'</span><span class="c-punc">);</span> <span class="c-com">// 链式调用</span></pre>
|
||||
|
||||
<section id="api-exec"><h3>命令执行</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">exec</span><span class="c-punc">(</span>action<span class="c-punc">)</span> <span class="c-com">// => this, 支持链式</span></pre>
|
||||
<table>
|
||||
<tr><th>action</th><th>效果</th><th>快捷键</th></tr>
|
||||
<tr><td><code>bold</code></td><td>加粗 **text**</td><td>Ctrl+B</td></tr>
|
||||
<tr><td><code>italic</code></td><td>斜体 *text*</td><td>Ctrl+I</td></tr>
|
||||
<tr><td><code>strikethrough</code></td><td>删除线 ~~text~~</td><td>—</td></tr>
|
||||
<tr><td><code>underline</code></td><td>下划线 <u>text</u></td><td>Ctrl+U</td></tr>
|
||||
<tr><td><code>code</code></td><td>行内代码 `text`</td><td>Ctrl+E</td></tr>
|
||||
<tr><td><code>h1</code>/<code>h2</code>/<code>h3</code></td><td>标题 # / ## / ###</td><td>Ctrl+1/2/3</td></tr>
|
||||
<tr><td><code>quote</code></td><td>引用 ></td><td>Ctrl+Q</td></tr>
|
||||
<tr><td><code>ul</code>/<code>ol</code></td><td>无序/有序列表</td><td>—</td></tr>
|
||||
<tr><td><code>indent</code>/<code>outdent</code></td><td>缩进/反缩进</td><td>Tab/Shift+Tab</td></tr>
|
||||
<tr><td><code>hr</code></td><td>水平线 ---</td><td>—</td></tr>
|
||||
<tr><td><code>link</code></td><td>插入链接 [text](url)</td><td>Ctrl+K</td></tr>
|
||||
<tr><td><code>image</code></td><td>插入图片 </td><td>—</td></tr>
|
||||
<tr><td><code>bold</code></td><td>**text**</td><td>Ctrl+B</td></tr>
|
||||
<tr><td><code>italic</code></td><td>*text*</td><td>Ctrl+I</td></tr>
|
||||
<tr><td><code>strikethrough</code></td><td>~~text~~</td><td>—</td></tr>
|
||||
<tr><td><code>underline</code></td><td><u>text</u></td><td>Ctrl+U</td></tr>
|
||||
<tr><td><code>code</code></td><td>`text`</td><td>Ctrl+E</td></tr>
|
||||
<tr><td><code>h1</code>/<code>h2</code>/<code>h3</code></td><td># / ## / ###</td><td>Ctrl+1/2/3</td></tr>
|
||||
<tr><td><code>quote</code></td><td>> text</td><td>Ctrl+Q</td></tr>
|
||||
<tr><td><code>ul</code>/<code>ol</code></td><td>- / 1. 列表</td><td>—</td></tr>
|
||||
<tr><td><code>link</code></td><td>[text](url)</td><td>Ctrl+K</td></tr>
|
||||
<tr><td><code>image</code></td><td></td><td>—</td></tr>
|
||||
<tr><td><code>table</code></td><td>插入表格</td><td>—</td></tr>
|
||||
<tr><td><code>undo</code>/<code>redo</code></td><td>撤销/重做</td><td>Ctrl+Z / Ctrl+Y</td></tr>
|
||||
<tr><td><code>hr</code></td><td>---水平线</td><td>—</td></tr>
|
||||
<tr><td><code>indent</code>/<code>outdent</code></td><td>缩进/反缩进</td><td>Tab / Shift+Tab</td></tr>
|
||||
<tr><td><code>undo</code>/<code>redo</code></td><td>撤销/重做</td><td>Ctrl+Z / Y</td></tr>
|
||||
<tr><td><code>edit</code>/<code>split</code>/<code>preview</code></td><td>切换模式</td><td>—</td></tr>
|
||||
<tr><td><code>fullscreen</code></td><td>切换全屏</td><td>—</td></tr>
|
||||
<tr><td><code>fullscreen</code></td><td>全屏</td><td>—</td></tr>
|
||||
<tr><td><code>zen</code></td><td>Zen 模式</td><td>—</td></tr>
|
||||
<tr><td><code>wordwrap</code></td><td>自动换行</td><td>—</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section id="api-history">
|
||||
<h3>历史栈</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">undo</span><span class="c-punc">();</span> <span class="c-com">// 撤销</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">redo</span><span class="c-punc">();</span> <span class="c-com">// 重做</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">canUndo</span><span class="c-punc">();</span> <span class="c-com">// 是否可撤销</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">canRedo</span><span class="c-punc">();</span> <span class="c-com">// 是否可重做</span></pre>
|
||||
<section id="api-history"><h3>历史栈</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">undo</span><span class="c-punc">();</span> editor<span class="c-punc">.</span><span class="c-fn">redo</span><span class="c-punc">();</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">canUndo</span><span class="c-punc">();</span> editor<span class="c-punc">.</span><span class="c-fn">canRedo</span><span class="c-punc">();</span></pre>
|
||||
</section>
|
||||
|
||||
<section id="api-mode">
|
||||
<h3>模式与全屏</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">setMode</span><span class="c-punc">(</span><span class="c-str">'split'</span><span class="c-punc">);</span> <span class="c-com">// 设置模式:edit | split | preview</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getMode</span><span class="c-punc">();</span> <span class="c-com">// 获取当前模式</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">toggleFullscreen</span><span class="c-punc">();</span> <span class="c-com">// 切换全屏</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">exitFullscreen</span><span class="c-punc">();</span> <span class="c-com">// 退出全屏</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">isFullscreen</span><span class="c-punc">();</span> <span class="c-com">// 是否全屏</span></pre>
|
||||
<section id="api-mode"><h3>模式 / 全屏 / Zen</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">setMode</span><span class="c-punc">(</span><span class="c-str">'split'</span><span class="c-punc">);</span> editor<span class="c-punc">.</span><span class="c-fn">getMode</span><span class="c-punc">();</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">toggleFullscreen</span><span class="c-punc">();</span> <span class="c-fn">isFullscreen</span><span class="c-punc">();</span> <span class="c-fn">exitFullscreen</span><span class="c-punc">();</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">toggleZen</span><span class="c-punc">();</span> <span class="c-fn">isZen</span><span class="c-punc">();</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">toggleWordWrap</span><span class="c-punc">();</span> <span class="c-fn">setWordWrap</span><span class="c-punc">(</span><span class="c-kw">true</span><span class="c-punc">);</span> <span class="c-fn">isWordWrap</span><span class="c-punc">();</span></pre>
|
||||
</section>
|
||||
|
||||
<section id="api-stats">
|
||||
<h3>统计与状态</h3>
|
||||
<section id="api-stats"><h3>统计与状态</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">getStats</span><span class="c-punc">();</span>
|
||||
<span class="c-com">// => { characters, words, chineseChars, englishWords, lines, readingTime }</span>
|
||||
|
||||
<span class="c-com">// => { characters, words, chineseChars, englishWords, lines, readingTime }</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getStatus</span><span class="c-punc">();</span>
|
||||
<span class="c-com">// => { id, mode, theme, locale, fullscreen, readOnly, disabled, destroyed, plugins }</span></pre>
|
||||
<span class="c-com">// => { id, mode, theme, locale, fullscreen, readOnly, disabled, destroyed, plugins }</span></pre>
|
||||
</section>
|
||||
|
||||
<section id="api-readonly">
|
||||
<h3>启用/禁用/只读</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">enable</span><span class="c-punc">();</span> <span class="c-com">// 启用</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">disable</span><span class="c-punc">();</span> <span class="c-com">// 禁用</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">isDisabled</span><span class="c-punc">();</span> <span class="c-com">// 是否禁用</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">setReadOnly</span><span class="c-punc">(</span><span class="c-kw">true</span><span class="c-punc">);</span> <span class="c-com">// 只读模式</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">isReadOnly</span><span class="c-punc">();</span> <span class="c-com">// 是否只读</span></pre>
|
||||
<section id="api-readonly"><h3>启用 / 禁用 / 只读</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">enable</span><span class="c-punc">();</span> <span class="c-fn">disable</span><span class="c-punc">();</span> <span class="c-fn">isDisabled</span><span class="c-punc">();</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">setReadOnly</span><span class="c-punc">(</span><span class="c-kw">true</span><span class="c-punc">);</span> <span class="c-fn">isReadOnly</span><span class="c-punc">();</span></pre>
|
||||
</section>
|
||||
|
||||
<section id="api-events">
|
||||
<h3>事件系统</h3>
|
||||
|
||||
<section id="api-events"><h3>事件系统</h3>
|
||||
<table>
|
||||
<tr><th>事件名</th><th>触发时机</th><th>回调参数</th></tr>
|
||||
<tr><td><code>input</code></td><td>textarea 原生 input</td><td><code>(value, editor)</code></td></tr>
|
||||
<tr><th>事件</th><th>触发时机</th><th>参数</th></tr>
|
||||
<tr><td><code>input</code></td><td>textarea 输入</td><td><code>(value, editor)</code></td></tr>
|
||||
<tr><td><code>change</code></td><td>内容变化</td><td><code>(value, editor)</code></td></tr>
|
||||
<tr><td><code>focus</code></td><td>聚焦</td><td><code>(editor)</code></td></tr>
|
||||
<tr><td><code>blur</code></td><td>失焦</td><td><code>(editor)</code></td></tr>
|
||||
<tr><td><code>save</code></td><td>Ctrl+S</td><td><code>(value, editor)</code></td></tr>
|
||||
<tr><td><code>focus</code> / <code>blur</code></td><td>聚焦/失焦</td><td><code>(editor)</code></td></tr>
|
||||
<tr><td><code>save</code></td><td>Ctrl+S</td><td><code>(editor)</code></td></tr>
|
||||
<tr><td><code>modeChange</code></td><td>模式切换</td><td><code>(mode, editor)</code></td></tr>
|
||||
<tr><td><code>fullscreen</code></td><td>全屏切换</td><td><code>(fullscreen, editor)</code></td></tr>
|
||||
<tr><td><code>themeChange</code></td><td>主题变更</td><td><code>({ theme, resolved, config })</code></td></tr>
|
||||
<tr><td><code>localeChange</code></td><td>语言变更</td><td><code>({ locale, direction })</code></td></tr>
|
||||
<tr><td><code>zenChange</code></td><td>Zen 切换</td><td><code>(zen, editor)</code></td></tr>
|
||||
<tr><td><code>destroy</code></td><td>销毁</td><td><code>()</code></td></tr>
|
||||
<tr><td><code>autosave</code></td><td>autoSave 保存</td><td><code>({ key, value })</code></td></tr>
|
||||
<tr><td><code>beforeRender</code></td><td>渲染前</td><td><code>(editor)</code></td></tr>
|
||||
<tr><td><code>afterRender</code></td><td>渲染后</td><td><code>(editor)</code></td></tr>
|
||||
<tr><td><code>beforeRender</code> / <code>afterRender</code></td><td>渲染前后</td><td><code>(editor)</code></td></tr>
|
||||
<tr><td><code>autosave</code></td><td>autoSave 触发</td><td><code>({ key, value })</code></td></tr>
|
||||
<tr><td><code>linkClick</code></td><td>预览链接点击</td><td><code>({ href, text })</code></td></tr>
|
||||
</table>
|
||||
|
||||
<h4>全局钩子(所有实例共享)</h4>
|
||||
<h4>全局钩子</h4>
|
||||
<table>
|
||||
<tr><th>钩子</th><th>触发时机</th></tr>
|
||||
<tr><td><code>beforeCreate</code></td><td>构造函数初始化前</td></tr>
|
||||
<tr><td><code>afterCreate</code></td><td>构造函数初始化完成</td></tr>
|
||||
<tr><td><code>beforeRender</code></td><td>每次渲染前(全局)</td></tr>
|
||||
<tr><td><code>afterRender</code></td><td>每次渲染后(全局)</td></tr>
|
||||
<tr><td><code>beforeDestroy</code></td><td>destroy 前</td></tr>
|
||||
<tr><td><code>afterDestroy</code></td><td>destroy 后</td></tr>
|
||||
<tr><td><code>beforeCreate</code> / <code>afterCreate</code></td><td>实例构造前后</td></tr>
|
||||
<tr><td><code>beforeRender</code> / <code>afterRender</code></td><td>全局渲染前后</td></tr>
|
||||
<tr><td><code>beforeDestroy</code> / <code>afterDestroy</code></td><td>销毁前后</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section id="api-plugin">
|
||||
<h3>插件管理</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span>plugin<span class="c-punc">,</span> options<span class="c-punc">);</span> <span class="c-com">// 安装插件</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getPlugins</span><span class="c-punc">();</span> <span class="c-com">// 获取已安装插件列表</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">addToolbarButton</span><span class="c-punc">(</span>config<span class="c-punc">);</span> <span class="c-com">// 追加工具栏按钮</span></pre>
|
||||
<section id="api-plugin"><h3>插件管理</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span>plugin<span class="c-punc">,</span> options<span class="c-punc">);</span> <span class="c-com">// 安装</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">unuse</span><span class="c-punc">(</span>name<span class="c-punc">);</span> <span class="c-com">// 卸载</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getPlugins</span><span class="c-punc">();</span> <span class="c-com">// 已安装列表</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">addToolbarButton</span><span class="c-punc">(</span>config<span class="c-punc">);</span> <span class="c-com">// 追加按钮</span></pre>
|
||||
</section>
|
||||
|
||||
<section id="api-lifecycle">
|
||||
<h3>生命周期</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">destroy</span><span class="c-punc">();</span> <span class="c-com">// 销毁实例</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">isDestroyed</span><span class="c-punc">();</span> <span class="c-com">// 是否已销毁</span></pre>
|
||||
<section id="api-shortcuts"><h3>快捷键管理</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">registerShortcut</span><span class="c-punc">(</span><span class="c-str">'Ctrl+Shift+T'</span><span class="c-punc">,</span> handler<span class="c-punc">,</span> <span class="c-str">'desc'</span><span class="c-punc">);</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">unregisterShortcut</span><span class="c-punc">(</span><span class="c-str">'Ctrl+Shift+T'</span><span class="c-punc">);</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getShortcuts</span><span class="c-punc">();</span></pre>
|
||||
</section>
|
||||
|
||||
<!-- ======== 静态 API ======== -->
|
||||
<section id="static-api">
|
||||
<h2>静态 API</h2>
|
||||
<section id="api-destroy"><h3>生命周期 / Toast</h3>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">destroy</span><span class="c-punc">();</span> <span class="c-fn">isDestroyed</span><span class="c-punc">();</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">toast</span><span class="c-punc">(</span>msg<span class="c-punc">,</span> <span class="c-punc">{</span> type<span class="c-punc">,</span> duration<span class="c-punc">,</span> animation <span class="c-punc">});</span></pre>
|
||||
</section>
|
||||
|
||||
<!-- 静态 API -->
|
||||
<section id="static-api"><h2>静态 API</h2>
|
||||
<pre><span class="c-kw">import</span> MeEditor <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span>
|
||||
|
||||
<span class="c-com">// 工厂函数</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span>container<span class="c-punc">,</span> options<span class="c-punc">);</span>
|
||||
|
||||
<span class="c-com">// 全局默认插件</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span>presetPlugins<span class="c-punc">.</span>autoSave<span class="c-punc">,</span> <span class="c-punc">{</span> delay<span class="c-punc">:</span> <span class="c-num">2000</span> <span class="c-punc">});</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span><span class="c-str">'searchReplace'</span><span class="c-punc">);</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span><span class="c-str">'autoSave'</span><span class="c-punc">,</span> <span class="c-punc">{</span> delay<span class="c-punc">:</span> <span class="c-num">2000</span> <span class="c-punc">});</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span>customPlugin<span class="c-punc">);</span>
|
||||
|
||||
<span class="c-com">// 全局事件钩子</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">on</span><span class="c-punc">(</span><span class="c-str">'beforeCreate'</span><span class="c-punc">,</span> <span class="c-punc">(</span>editor<span class="c-punc">)</span> <span class="c-punc">=></span> <span class="c-punc">{});</span>
|
||||
<span class="c-com">// 全局钩子</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">on</span><span class="c-punc">(</span><span class="c-str">'beforeCreate'</span><span class="c-punc">,</span> <span class="c-punc">(</span>editor<span class="c-punc">)</span> <span class="c-punc">=></span> <span class="c-punc">{});</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">off</span><span class="c-punc">(</span><span class="c-str">'beforeCreate'</span><span class="c-punc">,</span> handler<span class="c-punc">);</span>
|
||||
|
||||
<span class="c-com">// 主题与语言</span>
|
||||
<span class="c-com">// 全局主题 / 语言</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span><span class="c-str">'dark'</span><span class="c-punc">);</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">setLocale</span><span class="c-punc">(</span><span class="c-str">'en-US'</span><span class="c-punc">);</span>
|
||||
|
||||
<span class="c-com">// 状态查询</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">getStatus</span><span class="c-punc">();</span> <span class="c-com">// => { version, theme, locale, globalPlugins, presetPlugins }</span>
|
||||
|
||||
<span class="c-com">// 销毁全局资源</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">destroy</span><span class="c-punc">();</span>
|
||||
|
||||
<span class="c-com">// 内置解析器</span>
|
||||
<span class="c-kw">import</span> <span class="c-punc">{</span> parseMarkdown<span class="c-punc">,</span> safeUrl<span class="c-punc">,</span> slugify <span class="c-punc">}</span> <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span>
|
||||
<span class="c-fn">parseMarkdown</span><span class="c-punc">(</span><span class="c-str">'# Hello'</span><span class="c-punc">);</span> <span class="c-com">// => '<h1 id="hello">Hello</h1>'</span>
|
||||
<span class="c-fn">safeUrl</span><span class="c-punc">(</span><span class="c-str">'javascript:alert(1)'</span><span class="c-punc">);</span> <span class="c-com">// => ''</span>
|
||||
<span class="c-fn">slugify</span><span class="c-punc">(</span><span class="c-str">'Hello World'</span><span class="c-punc">);</span> <span class="c-com">// => 'hello-world'</span></pre>
|
||||
<span class="c-com">// 解析器独立使用</span>
|
||||
<span class="c-kw">import</span> <span class="c-punc">{</span> parseMarkdown<span class="c-punc">,</span> parseTokens<span class="c-punc">,</span> renderTokens <span class="c-punc">}</span> <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span></pre>
|
||||
</section>
|
||||
|
||||
<!-- ======== 语法参考 ======== -->
|
||||
<section id="syntax">
|
||||
<h2>解析器语法参考</h2>
|
||||
|
||||
<!-- 解析器语法 -->
|
||||
<section id="parser-syntax"><h2>解析器语法参考</h2>
|
||||
<table>
|
||||
<tr><th>语法</th><th>示例</th><th>输出</th></tr>
|
||||
<tr><td>标题</td><td><code># H1</code> ~ <code>###### H6</code></td><td><code><h1></code> ~ <code><h6></code></td></tr>
|
||||
<tr><td>段落</td><td>纯文本</td><td><code><p></code></td></tr>
|
||||
<tr><td>粗体</td><td><code>**bold**</code> <code>__bold__</code></td><td><code><strong></code></td></tr>
|
||||
<tr><td>粗斜体 <span class="badge">v0.1.15</span></td><td><code>***text***</code> <code>___text___</code></td><td><code><em><strong></code></td></tr>
|
||||
<tr><td>斜体</td><td><code>*italic*</code> <code>_italic_</code></td><td><code><em></code></td></tr>
|
||||
<tr><td>删除线</td><td><code>~~text~~</code></td><td><code><del></code></td></tr>
|
||||
<tr><td>高亮标记</td><td><code>==text==</code></td><td><code><mark></code></td></tr>
|
||||
<tr><td>上标</td><td><code>x^2^</code></td><td><code><sup></code></td></tr>
|
||||
<tr><td>下标</td><td><code>H~2~O</code></td><td><code><sub></code></td></tr>
|
||||
<tr><td>行内代码</td><td><code>`code`</code></td><td><code><code></code></td></tr>
|
||||
<tr><td>代码块</td><td><code>```lang</code></td><td><code><pre><code></code></td></tr>
|
||||
<tr><td>引用</td><td><code>> quote</code></td><td><code><blockquote></code></td></tr>
|
||||
<tr><td>无序列表</td><td><code>- item</code></td><td><code><ul><li></code></td></tr>
|
||||
<tr><td>有序列表</td><td><code>1. item</code></td><td><code><ol><li></code></td></tr>
|
||||
<tr><td>任务列表</td><td><code>- [x] done</code></td><td><code><li class="me-task-item"></code></td></tr>
|
||||
<tr><td>水平线</td><td><code>---</code> <code>***</code> <code>___</code></td><td><code><hr></code></td></tr>
|
||||
<tr><td>表格</td><td><code>| a | b |</code></td><td><code><table></code>(支持 <code>:---:</code> 列对齐)</td></tr>
|
||||
<tr><td>链接 v0.1.15</td><td><code>[**text**](url)</code></td><td>链接文本内支持行内格式</td></tr>
|
||||
<tr><td>图片</td><td><code></code></td><td><code><img></code></td></tr>
|
||||
<tr><td>自动链接</td><td><code><https://...></code></td><td><code><a></code></td></tr>
|
||||
<tr><td>Emoji</td><td><code>:smile:</code> <code>:rocket:</code></td><td>😊 🚀(150+ 常用)</td></tr>
|
||||
<tr><td>反斜杠转义 <span class="badge">v0.1.15</span></td><td><code>\*</code> <code>\_</code> <code>\\</code></td><td>取消标点特殊含义</td></tr>
|
||||
<tr><td>标题</td><td><code># H1</code> ~ <code>###### H6</code></td><td><h1> ~ <h6></td></tr>
|
||||
<tr><td>Setext 标题</td><td><code>H1\n===</code></td><td><h1> / <h2></td></tr>
|
||||
<tr><td>粗体</td><td><code>**bold**</code> <code>__bold__</code></td><td><strong></td></tr>
|
||||
<tr><td>粗斜体 <span class="badge">v0.1.15</span></td><td><code>***text***</code> <code>___text___</code></td><td><em><strong></td></tr>
|
||||
<tr><td>斜体</td><td><code>*italic*</code> <code>_italic_</code></td><td><em></td></tr>
|
||||
<tr><td>删除线 / 高亮</td><td><code>~~del~~</code> <code>==mark==</code></td><td><del> / <mark></td></tr>
|
||||
<tr><td>上标 / 下标</td><td><code>x^2^</code> <code>H~2~O</code></td><td><sup> / <sub></td></tr>
|
||||
<tr><td>行内代码</td><td><code>`code`</code></td><td><code></td></tr>
|
||||
<tr><td>代码块</td><td><code>```lang</code></td><td><pre><code></td></tr>
|
||||
<tr><td>缩进代码块</td><td><code> code</code></td><td><pre><code></td></tr>
|
||||
<tr><td>引用</td><td><code>> quote</code></td><td><blockquote></td></tr>
|
||||
<tr><td>无序列表</td><td><code>- * + item</code></td><td><ul><li></td></tr>
|
||||
<tr><td>有序列表</td><td><code>1. item</code></td><td><ol><li></td></tr>
|
||||
<tr><td>嵌套列表</td><td>多级缩进</td><td>多级 <ul>/<ol></td></tr>
|
||||
<tr><td>任务列表</td><td><code>- [x] done</code></td><td><li class="me-task-item"></td></tr>
|
||||
<tr><td>水平线</td><td><code>---</code> <code>***</code> <code>___</code></td><td><hr></td></tr>
|
||||
<tr><td>表格</td><td><code>| a | b |</code></td><td><table> + 列对齐</td></tr>
|
||||
<tr><td>链接 <span class="badge">v0.1.15</span></td><td><code>[**t**](url)</code></td><td>文本内支持行内格式</td></tr>
|
||||
<tr><td>图片</td><td><code></code></td><td><img></td></tr>
|
||||
<tr><td>自动链接</td><td><code><https://...></code></td><td><a></td></tr>
|
||||
<tr><td>数学公式</td><td><code>$E=mc^2$</code></td><td><span> / <div></td></tr>
|
||||
<tr><td>脚注</td><td><code>text[^1]</code></td><td><sup> + 底部</td></tr>
|
||||
<tr><td>定义列表</td><td><code>Term\n: def</code></td><td><dl><dt><dd></td></tr>
|
||||
<tr><td>Emoji</td><td><code>:smile:</code> <code>:rocket:</code></td><td>😊 🚀(150+)</td></tr>
|
||||
<tr><td>反斜杠转义 <span class="badge">v0.1.15</span></td><td><code>\*</code> <code>\_</code></td><td>取消标点特殊含义</td></tr>
|
||||
</table>
|
||||
|
||||
<h3>XSS 防护</h3>
|
||||
<p>所有文本经 HTML 转义。URL 自动过滤 <code>javascript:</code> <code>vbscript:</code> <code>file:</code> 及非图片 <code>data:</code> 协议。</p>
|
||||
<h4>XSS 防护</h4>
|
||||
<p>所有文本经 <code>escapeHTML</code> 转义,URL 过滤 <code>javascript:</code> / <code>vbscript:</code> / <code>file:</code> / 非图片 <code>data:</code>,提供 <code>sanitize</code> 钩子。</p>
|
||||
</section>
|
||||
|
||||
<!-- ======== 解析器 API v0.1.15 ======== -->
|
||||
<section id="parser-api">
|
||||
<h2>解析器 API <span class="badge">v0.1.15 新增</span></h2>
|
||||
|
||||
<h3>parseTokens / renderTokens(解析与渲染分离)</h3>
|
||||
<p>将 Markdown 解析为中间 Token 数组,可在渲染前变换,再输出 HTML。</p>
|
||||
<section id="parser-api"><h2>解析器 API</h2>
|
||||
<h3>parseTokens / renderTokens</h3>
|
||||
<pre><span class="c-kw">import</span> <span class="c-punc">{</span> parseTokens<span class="c-punc">,</span> renderTokens <span class="c-punc">}</span> <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span>
|
||||
|
||||
<span class="c-com">// 解析为 Token 数组</span>
|
||||
<span class="c-kw">const</span> <span class="c-punc">{</span> tokens<span class="c-punc">,</span> footnotes <span class="c-punc">}</span> <span class="c-punc">=</span> <span class="c-fn">parseTokens</span><span class="c-punc">(</span><span class="c-str">'# Hello\n\n**world**'</span><span class="c-punc">);</span>
|
||||
<span class="c-com">// tokens = [</span>
|
||||
<span class="c-com">// { type: 'heading', level: 1, text: 'Hello' },</span>
|
||||
<span class="c-com">// { type: 'paragraph', text: '**world**' }</span>
|
||||
<span class="c-com">// ]</span>
|
||||
|
||||
<span class="c-com">// 你可以在渲染前变换 token 数组</span>
|
||||
tokens<span class="c-punc">.</span><span class="c-fn">unshift</span><span class="c-punc">({</span> type<span class="c-punc">:</span> <span class="c-str">'hr'</span> <span class="c-punc">});</span>
|
||||
|
||||
<span class="c-com">// 渲染为 HTML</span>
|
||||
tokens<span class="c-punc">.</span><span class="c-fn">unshift</span><span class="c-punc">({</span> type<span class="c-punc">:</span> <span class="c-str">'hr'</span> <span class="c-punc">});</span> <span class="c-com">// 渲染前变换</span>
|
||||
<span class="c-kw">const</span> html <span class="c-punc">=</span> <span class="c-fn">renderTokens</span><span class="c-punc">(</span>tokens<span class="c-punc">,</span> env<span class="c-punc">,</span> footnotes<span class="c-punc">);</span></pre>
|
||||
|
||||
<h3>registerBlockHandler(注册自定义块级语法)</h3>
|
||||
<p>无需替换整个解析器,按优先级注册自定义块级语法处理器。</p>
|
||||
<h3>registerBlockHandler</h3>
|
||||
<pre><span class="c-kw">import</span> <span class="c-punc">{</span> registerBlockHandler <span class="c-punc">}</span> <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span>
|
||||
|
||||
<span class="c-fn">registerBlockHandler</span><span class="c-punc">({</span>
|
||||
name<span class="c-punc">:</span> <span class="c-str">'customAlert'</span><span class="c-punc">,</span>
|
||||
priority<span class="c-punc">:</span> <span class="c-num">8.5</span><span class="c-punc">,</span> <span class="c-com">// 越小越先尝试</span>
|
||||
test<span class="c-punc">:</span> <span class="c-punc">(</span>line<span class="c-punc">)</span> <span class="c-punc">=></span> line<span class="c-punc">.</span><span class="c-fn">match</span><span class="c-punc">(</span><span class="c-re">/^:::(\w+)/</span><span class="c-punc">),</span>
|
||||
parse<span class="c-punc">:</span> <span class="c-punc">(</span>lines<span class="c-punc">,</span> i<span class="c-punc">,</span> match<span class="c-punc">)</span> <span class="c-punc">=></span> <span class="c-punc">{</span>
|
||||
<span class="c-com">// 返回 { token: {...}, newIndex }</span>
|
||||
<span class="c-kw">return</span> <span class="c-punc">{</span> token<span class="c-punc">:</span> <span class="c-punc">{</span> type<span class="c-punc">:</span> <span class="c-str">'alert'</span><span class="c-punc">,</span> alertType<span class="c-punc">:</span> match<span class="c-punc">[</span><span class="c-num">1</span><span class="c-punc">]</span> <span class="c-punc">},</span> newIndex<span class="c-punc">:</span> j <span class="c-punc">};</span>
|
||||
<span class="c-punc">},</span>
|
||||
name<span class="c-punc">:</span> <span class="c-str">'custom'</span><span class="c-punc">,</span> priority<span class="c-punc">:</span> <span class="c-num">8.5</span><span class="c-punc">,</span>
|
||||
test<span class="c-punc">:</span> <span class="c-punc">(</span>line<span class="c-punc">)</span> <span class="c-punc">=></span> line<span class="c-punc">.</span><span class="c-fn">match</span><span class="c-punc">(</span><span class="c-re">/^:::/</span><span class="c-punc">),</span>
|
||||
parse<span class="c-punc">:</span> <span class="c-punc">(</span>lines<span class="c-punc">,</span> i<span class="c-punc">,</span> match<span class="c-punc">)</span> <span class="c-punc">=></span> <span class="c-punc">({</span> token<span class="c-punc">:</span> <span class="c-punc">{</span> type<span class="c-punc">:</span> <span class="c-str">'alert'</span> <span class="c-punc">},</span> newIndex<span class="c-punc">:</span> j <span class="c-punc">})</span>
|
||||
<span class="c-punc">});</span></pre>
|
||||
|
||||
<p>TIP:如果自定义 token 的 <code>type</code> 不被 <code>renderTokens</code> 识别,可以在渲染前通过 <code>tokens.map()</code> 转换为已知 type,或自行实现渲染逻辑。</p>
|
||||
</section>
|
||||
|
||||
<!-- ======== 插件 ======== -->
|
||||
<section id="plugins">
|
||||
<h2>插件约定</h2>
|
||||
|
||||
<!-- 插件 -->
|
||||
<section id="plugins-convention"><h2>插件约定</h2>
|
||||
<pre><span class="c-kw">const</span> myPlugin <span class="c-punc">=</span> <span class="c-punc">{</span>
|
||||
name<span class="c-punc">:</span> <span class="c-str">'myPlugin'</span><span class="c-punc">,</span>
|
||||
description<span class="c-punc">:</span> <span class="c-str">'我的自定义插件'</span><span class="c-punc">,</span>
|
||||
|
||||
<span class="c-fn">install</span><span class="c-punc">(</span>editor<span class="c-punc">,</span> options<span class="c-punc">)</span> <span class="c-punc">{</span>
|
||||
<span class="c-com">// this 指向插件对象本身</span>
|
||||
<span class="c-kw">this</span><span class="c-punc">.</span>_timer <span class="c-punc">=</span> <span class="c-kw">null</span><span class="c-punc">;</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">on</span><span class="c-punc">(</span><span class="c-str">'change'</span><span class="c-punc">,</span> <span class="c-kw">this</span><span class="c-punc">.</span>_onChange<span class="c-punc">);</span>
|
||||
<span class="c-punc">},</span>
|
||||
|
||||
<span class="c-fn">destroy</span><span class="c-punc">(</span>editor<span class="c-punc">)</span> <span class="c-punc">{</span>
|
||||
<span class="c-kw">if</span> <span class="c-punc">(</span><span class="c-kw">this</span><span class="c-punc">.</span>_timer<span class="c-punc">)</span> <span class="c-fn">clearTimeout</span><span class="c-punc">(</span><span class="c-kw">this</span><span class="c-punc">.</span>_timer<span class="c-punc">);</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">off</span><span class="c-punc">(</span><span class="c-str">'change'</span><span class="c-punc">,</span> <span class="c-kw">this</span><span class="c-punc">.</span>_onChange<span class="c-punc">);</span>
|
||||
<span class="c-punc">},</span>
|
||||
name<span class="c-punc">:</span> <span class="c-str">'myPlugin'</span><span class="c-punc">,</span> description<span class="c-punc">:</span> <span class="c-str">'我的插件'</span><span class="c-punc">,</span>
|
||||
<span class="c-fn">install</span><span class="c-punc">(</span>editor<span class="c-punc">)</span> <span class="c-punc">{</span> editor<span class="c-punc">.</span><span class="c-fn">on</span><span class="c-punc">(</span><span class="c-str">'change'</span><span class="c-punc">,</span> <span class="c-kw">this</span><span class="c-punc">.</span>_onChange<span class="c-punc">);</span> <span class="c-punc">},</span>
|
||||
<span class="c-fn">destroy</span><span class="c-punc">(</span>editor<span class="c-punc">)</span> <span class="c-punc">{</span> editor<span class="c-punc">.</span><span class="c-fn">off</span><span class="c-punc">(</span><span class="c-str">'change'</span><span class="c-punc">,</span> <span class="c-kw">this</span><span class="c-punc">.</span>_onChange<span class="c-punc">);</span> <span class="c-punc">},</span>
|
||||
<span class="c-punc">};</span></pre>
|
||||
</section>
|
||||
|
||||
<section id="preset-plugins">
|
||||
<h3>预设插件</h3>
|
||||
|
||||
<h4>autoSave — 自动保存草稿</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span>presetPlugins<span class="c-punc">.</span>autoSave<span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
key<span class="c-punc">:</span> <span class="c-str">'me-draft-'</span> <span class="c-punc">+</span> editor<span class="c-punc">.</span>id<span class="c-punc">,</span> <span class="c-com">// localStorage key</span>
|
||||
delay<span class="c-punc">:</span> <span class="c-num">1000</span><span class="c-punc">,</span> <span class="c-com">// 防抖延迟(ms)</span>
|
||||
<span class="c-punc">});</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">restoreDraft</span><span class="c-punc">();</span> <span class="c-com">// 恢复草稿</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">clearDraft</span><span class="c-punc">();</span> <span class="c-com">// 清除草稿</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getDraftKey</span><span class="c-punc">();</span> <span class="c-com">// 获取存储 key</span></pre>
|
||||
|
||||
<h4>exportTool — 导出文件</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span>presetPlugins<span class="c-punc">.</span>exportTool<span class="c-punc">);</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">exportMarkdown</span><span class="c-punc">(</span><span class="c-str">'my-doc.md'</span><span class="c-punc">);</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">exportHTML</span><span class="c-punc">(</span><span class="c-str">'my-doc.html'</span><span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
title<span class="c-punc">:</span> <span class="c-str">'文档标题'</span><span class="c-punc">,</span>
|
||||
css<span class="c-punc">:</span> <span class="c-str">'body { font-family: sans-serif; }'</span><span class="c-punc">,</span>
|
||||
lang<span class="c-punc">:</span> <span class="c-str">'zh-CN'</span><span class="c-punc">,</span>
|
||||
<span class="c-punc">});</span></pre>
|
||||
|
||||
<h4>searchReplace — 查找替换</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span>presetPlugins<span class="c-punc">.</span>searchReplace<span class="c-punc">);</span>
|
||||
<span class="c-com">// Ctrl+F → 查找 Ctrl+H → 替换</span>
|
||||
<span class="c-com">// Enter → 下一个 Shift+Enter → 上一个 Escape → 关闭</span></pre>
|
||||
|
||||
<h4>imagePaste — 粘贴图片转 base64</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span>presetPlugins<span class="c-punc">.</span>imagePaste<span class="c-punc">);</span>
|
||||
<span class="c-com">// 在编辑区 Ctrl+V 粘贴剪贴板图片</span>
|
||||
<span class="c-com">// 自动插入 </span></pre>
|
||||
<section id="preset-plugins"><h3>预设插件</h3>
|
||||
<h4>autoSave</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span><span class="c-str">'autoSave'</span><span class="c-punc">,</span> <span class="c-punc">{</span> key<span class="c-punc">:</span> <span class="c-str">'draft-key'</span><span class="c-punc">,</span> delay<span class="c-punc">:</span> <span class="c-num">1000</span> <span class="c-punc">});</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">restoreDraft</span><span class="c-punc">();</span> editor<span class="c-punc">.</span><span class="c-fn">clearDraft</span><span class="c-punc">();</span></pre>
|
||||
<h4>exportTool</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span><span class="c-str">'exportTool'</span><span class="c-punc">);</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">exportMarkdown</span><span class="c-punc">(</span><span class="c-str">'doc.md'</span><span class="c-punc">);</span> editor<span class="c-punc">.</span><span class="c-fn">exportHTML</span><span class="c-punc">(</span><span class="c-str">'doc.html'</span><span class="c-punc">);</span></pre>
|
||||
<h4>searchReplace</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span><span class="c-str">'searchReplace'</span><span class="c-punc">);</span>
|
||||
<span class="c-com">// Ctrl+F 查找 / Ctrl+H 替换</span></pre>
|
||||
<h4>imagePaste</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span><span class="c-str">'imagePaste'</span><span class="c-punc">);</span> <span class="c-com">// 粘贴图片自动转 base64</span></pre>
|
||||
<h4>shortcutHelp</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span><span class="c-str">'shortcutHelp'</span><span class="c-punc">);</span> <span class="c-com">// 按 ? 弹出快捷键面板</span></pre>
|
||||
<h4>fileSystem</h4>
|
||||
<pre>editor<span class="c-punc">.</span><span class="c-fn">use</span><span class="c-punc">(</span><span class="c-str">'fileSystem'</span><span class="c-punc">);</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">openFile</span><span class="c-punc">();</span> editor<span class="c-punc">.</span><span class="c-fn">saveFile</span><span class="c-punc">();</span> editor<span class="c-punc">.</span><span class="c-fn">saveFileAs</span><span class="c-punc">();</span></pre>
|
||||
</section>
|
||||
|
||||
<!-- ======== 主题 ======== -->
|
||||
<section id="themes">
|
||||
<h2>主题系统</h2>
|
||||
<!-- 主题 -->
|
||||
<section id="themes"><h2>主题系统</h2>
|
||||
<pre><span class="c-com">// 实例级</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span><span class="c-str">'dark'</span><span class="c-punc">);</span> editor<span class="c-punc">.</span><span class="c-fn">getTheme</span><span class="c-punc">();</span>
|
||||
|
||||
<pre><span class="c-com">// 全局切换主题</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span><span class="c-str">'light'</span><span class="c-punc">);</span> <span class="c-com">// 亮色</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span><span class="c-str">'dark'</span><span class="c-punc">);</span> <span class="c-com">// 暗色</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span><span class="c-str">'warm'</span><span class="c-punc">);</span> <span class="c-com">// 暖色</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span><span class="c-str">'auto'</span><span class="c-punc">);</span> <span class="c-com">// 自动(默认)</span>
|
||||
|
||||
<span class="c-com">// 实例级主题(v0.1.5,每个编辑器独立)</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span><span class="c-str">'dark'</span><span class="c-punc">);</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getTheme</span><span class="c-punc">();</span> <span class="c-com">// 'dark'</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">on</span><span class="c-punc">(</span><span class="c-str">'themeChange'</span><span class="c-punc">,</span> <span class="c-punc">({</span> theme <span class="c-punc">})</span> <span class="c-punc">=></span> <span class="c-punc">{});</span>
|
||||
|
||||
<span class="c-com">// 注册自定义主题(v0.1.5: 支持继承)</span>
|
||||
<span class="c-com">// 注册自定义</span>
|
||||
<span class="c-kw">import</span> <span class="c-punc">{</span> themeUtils <span class="c-punc">}</span> <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span>
|
||||
themeUtils<span class="c-punc">.</span><span class="c-fn">registerTheme</span><span class="c-punc">(</span><span class="c-str">'ocean'</span><span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
extends<span class="c-punc">:</span> <span class="c-str">'dark'</span><span class="c-punc">,</span> <span class="c-com">// 继承 dark 主题</span>
|
||||
accent<span class="c-punc">:</span> <span class="c-str">'#00ddff'</span><span class="c-punc">,</span>
|
||||
<span class="c-punc">});</span>
|
||||
themeUtils<span class="c-punc">.</span><span class="c-fn">registerTheme</span><span class="c-punc">(</span><span class="c-str">'ocean'</span><span class="c-punc">,</span> <span class="c-punc">{</span> extends<span class="c-punc">:</span> <span class="c-str">'dark'</span><span class="c-punc">,</span> accent<span class="c-punc">:</span> <span class="c-str">'#00ddff'</span> <span class="c-punc">});</span>
|
||||
|
||||
<span class="c-com">// 外部主题跟随(v0.1.5)</span>
|
||||
themeUtils<span class="c-punc">.</span><span class="c-fn">followExternalTheme</span><span class="c-punc">(</span>
|
||||
<span class="c-punc">{</span> element<span class="c-punc">:</span> document<span class="c-punc">.</span>body<span class="c-punc">,</span> attr<span class="c-punc">:</span> <span class="c-str">'data-theme'</span> <span class="c-punc">},</span>
|
||||
<span class="c-punc">(</span>theme<span class="c-punc">)</span> <span class="c-punc">=></span> editor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span>theme<span class="c-punc">)</span>
|
||||
<span class="c-punc">);</span>
|
||||
|
||||
<span class="c-com">// 从父容器继承主题</span>
|
||||
themeUtils<span class="c-punc">.</span><span class="c-fn">adoptFromParent</span><span class="c-punc">(</span>editor<span class="c-punc">.</span>container<span class="c-punc">,</span>
|
||||
<span class="c-punc">(</span>theme<span class="c-punc">)</span> <span class="c-punc">=></span> editor<span class="c-punc">.</span><span class="c-fn">setTheme</span><span class="c-punc">(</span>theme<span class="c-punc">)</span>
|
||||
<span class="c-punc">);</span>
|
||||
<span class="c-com">// 外部跟随</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">getThemeContext</span><span class="c-punc">().</span><span class="c-fn">adopt</span><span class="c-punc">();</span> <span class="c-com">// 从父容器继承</span>
|
||||
|
||||
<span class="c-com">// CSS 变量导出</span>
|
||||
themeUtils<span class="c-punc">.</span><span class="c-fn">exportCSSVars</span><span class="c-punc">();</span> <span class="c-com">// { '--md-bg': '#fff', ... }</span>
|
||||
themeUtils<span class="c-punc">.</span><span class="c-fn">getCSSVariable</span><span class="c-punc">(</span><span class="c-str">'accent'</span><span class="c-punc">);</span> <span class="c-com">// '#3b82f6'</span></pre>
|
||||
|
||||
<p>CSS 变量限定在 <code>.me-wrapper</code> 元素上,不污染全局。支持 <code>@media print</code> 打印样式。v0.1.5 新增实例级主题隔离、外部跟随、主题继承。</p>
|
||||
themeUtils<span class="c-punc">.</span><span class="c-fn">exportCSSVars</span><span class="c-punc">();</span> themeUtils<span class="c-punc">.</span><span class="c-fn">getCSSVariable</span><span class="c-punc">(</span><span class="c-str">'accent'</span><span class="c-punc">);</span></pre>
|
||||
</section>
|
||||
|
||||
<!-- ======== 国际化 ======== -->
|
||||
<section id="i18n">
|
||||
<h2>国际化</h2>
|
||||
<!-- 国际化 -->
|
||||
<section id="i18n"><h2>国际化</h2>
|
||||
<pre><span class="c-com">// 切换</span>
|
||||
editor<span class="c-punc">.</span><span class="c-fn">setLocale</span><span class="c-punc">(</span><span class="c-str">'en-US'</span><span class="c-punc">);</span> MeEditor<span class="c-punc">.</span><span class="c-fn">setLocale</span><span class="c-punc">(</span><span class="c-str">'zh-CN'</span><span class="c-punc">);</span>
|
||||
|
||||
<pre><span class="c-com">// 切换语言</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">setLocale</span><span class="c-punc">(</span><span class="c-str">'en-US'</span><span class="c-punc">);</span>
|
||||
MeEditor<span class="c-punc">.</span><span class="c-fn">setLocale</span><span class="c-punc">(</span><span class="c-str">'zh-CN'</span><span class="c-punc">);</span>
|
||||
|
||||
<span class="c-com">// 翻译函数</span>
|
||||
<span class="c-com">// 添加翻译</span>
|
||||
<span class="c-kw">import</span> <span class="c-punc">{</span> i18nUtils <span class="c-punc">}</span> <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">t</span><span class="c-punc">(</span><span class="c-str">'bold'</span><span class="c-punc">);</span> <span class="c-com">// => '粗体'(zh-CN)</span>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">t</span><span class="c-punc">(</span><span class="c-str">'bold'</span><span class="c-punc">);</span> <span class="c-com">// => 'Bold'(en-US)</span>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">addTranslations</span><span class="c-punc">(</span><span class="c-str">'ja'</span><span class="c-punc">,</span> <span class="c-punc">{</span> bold<span class="c-punc">:</span> <span class="c-str">'太字'</span> <span class="c-punc">});</span>
|
||||
|
||||
<span class="c-com">// 添加语言</span>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">addTranslations</span><span class="c-punc">(</span><span class="c-str">'ja'</span><span class="c-punc">,</span> <span class="c-punc">{</span> bold<span class="c-punc">:</span> <span class="c-str">'太字'</span><span class="c-punc">,</span> italic<span class="c-punc">:</span> <span class="c-str">'斜体'</span> <span class="c-punc">});</span>
|
||||
<span class="c-com">// 远程加载</span>
|
||||
<span class="c-kw">await</span> i18nUtils<span class="c-punc">.</span><span class="c-fn">loadRemote</span><span class="c-punc">(</span><span class="c-str">'/locales/ja.json'</span><span class="c-punc">,</span> <span class="c-str">'ja'</span><span class="c-punc">);</span>
|
||||
|
||||
<span class="c-com">// 格式化</span>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">formatNumber</span><span class="c-punc">(</span><span class="c-num">1234567</span><span class="c-punc">);</span> <span class="c-com">// => '1,234,567'</span>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">formatCurrency</span><span class="c-punc">(</span><span class="c-num">99.99</span><span class="c-punc">,</span> <span class="c-str">'USD'</span><span class="c-punc">);</span> <span class="c-com">// => '$99.99'</span>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">formatDate</span><span class="c-punc">(</span><span class="c-str">'2024-01-15'</span><span class="c-punc">);</span> <span class="c-com">// => '1/15/2024'</span></pre>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">formatNumber</span><span class="c-punc">(</span><span class="c-num">1234567</span><span class="c-punc">);</span>
|
||||
i18nUtils<span class="c-punc">.</span><span class="c-fn">formatDate</span><span class="c-punc">(</span><span class="c-str">'2024-01-15'</span><span class="c-punc">);</span></pre>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
@@ -660,24 +431,18 @@ i18nUtils<span class="c-punc">.</span><span class="c-fn">formatDate</span><span
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
MetonaEditor v0.1.15 · <a href="https://git.metona.cn/MetonaTeam/MetonaEditor" target="_blank" rel="noopener">源码仓库</a> · MIT License
|
||||
MetonaEditor v0.2.0 · TypeScript · <a href="https://git.metona.cn/MetonaTeam/MetonaEditor" target="_blank" rel="noopener">源码仓库</a> · MIT License
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// 高亮当前 section 的侧边栏链接
|
||||
const sections = document.querySelectorAll('section[id]');
|
||||
const links = document.querySelectorAll('.sidebar a');
|
||||
window.addEventListener('scroll', () => {
|
||||
let current = '';
|
||||
sections.forEach(s => {
|
||||
if (window.scrollY >= s.offsetTop - 100) current = s.id;
|
||||
});
|
||||
links.forEach(a => {
|
||||
a.classList.toggle('active', a.getAttribute('href') === '#' + current);
|
||||
});
|
||||
sections.forEach(s => { if (window.scrollY >= s.offsetTop - 100) current = s.id; });
|
||||
links.forEach(a => { a.classList.toggle('active', a.getAttribute('href') === '#' + current); });
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+145
-609
@@ -6,432 +6,122 @@
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🚀</text></svg>"/>
|
||||
<title>MetonaEditor v0.2.0 · TypeScript · 桌面端 Markdown 编辑器</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
:root {
|
||||
--bg: #0f1117;
|
||||
--bg-soft: #161922;
|
||||
--card: #1c2029;
|
||||
--card-hover: #232834;
|
||||
--text: #e6e8eb;
|
||||
--muted: #9ca3af;
|
||||
--accent: #3b82f6;
|
||||
--accent-2: #8b5cf6;
|
||||
--accent-3: #ec4899;
|
||||
--accent-soft: rgba(59, 130, 246, 0.12);
|
||||
--border: rgba(255, 255, 255, 0.08);
|
||||
--gradient: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 50%, #ec4899 100%);
|
||||
--shadow: 0 20px 50px -20px rgba(0,0,0,0.5);
|
||||
}
|
||||
html { scroll-behavior: smooth; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.container { max-width: 1080px; margin: 0 auto; padding: 0 24px; }
|
||||
*{box-sizing:border-box;margin:0;padding:0}
|
||||
:root{--bg:#0f1117;--bg-soft:#161922;--card:#1c2029;--card-hover:#232834;--text:#e6e8eb;--muted:#9ca3af;--accent:#3b82f6;--accent-2:#8b5cf6;--accent-3:#ec4899;--accent-soft:rgba(59,130,246,.12);--border:rgba(255,255,255,.08);--gradient:linear-gradient(135deg,#3b82f6 0%,#8b5cf6 50%,#ec4899 100%);--shadow:0 20px 50px -20px rgba(0,0,0,.5)}
|
||||
html{scroll-behavior:smooth}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:var(--bg);color:var(--text);line-height:1.6;min-height:100vh;overflow-x:hidden}
|
||||
.container{max-width:1080px;margin:0 auto;padding:0 24px}
|
||||
nav{position:sticky;top:0;z-index:100;background:rgba(15,17,23,.85);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);border-bottom:1px solid var(--border)}
|
||||
.nav-inner{max-width:1080px;margin:0 auto;padding:14px 24px;display:flex;align-items:center;justify-content:space-between}
|
||||
.nav-brand{display:inline-flex;align-items:center;gap:10px;text-decoration:none;color:var(--text);font-weight:700;font-size:16px}
|
||||
.nav-brand .logo-mark{width:28px;height:28px;border-radius:7px;background:var(--gradient);display:flex;align-items:center;justify-content:center;flex-shrink:0}
|
||||
.logo-mark svg{display:block}
|
||||
.nav-links{display:flex;gap:28px;align-items:center}
|
||||
.nav-links a{color:var(--muted);text-decoration:none;font-size:14px;transition:color .15s}
|
||||
.nav-links a:hover{color:var(--text)}
|
||||
.nav-cta{padding:7px 16px;border-radius:8px;background:var(--accent-soft);color:var(--accent)!important;border:1px solid rgba(59,130,246,.3);font-weight:500}
|
||||
@media(max-width:640px){.nav-links a:not(.nav-cta){display:none}}
|
||||
|
||||
/* 导航 */
|
||||
nav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
background: rgba(15, 17, 23, 0.85);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.nav-inner {
|
||||
max-width: 1080px;
|
||||
margin: 0 auto;
|
||||
padding: 14px 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.nav-brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
text-decoration: none;
|
||||
color: var(--text);
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
}
|
||||
.nav-brand .logo-mark {
|
||||
width: 28px; height: 28px;
|
||||
border-radius: 7px;
|
||||
background: var(--gradient);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.logo .logo-mark {
|
||||
width: 32px; height: 32px;
|
||||
border-radius: 8px;
|
||||
background: var(--gradient);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.logo-mark svg { display: block; }
|
||||
.nav-links { display: flex; gap: 28px; align-items: center; }
|
||||
.nav-links a {
|
||||
color: var(--muted);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
.nav-links a:hover { color: var(--text); }
|
||||
.nav-cta {
|
||||
padding: 7px 16px;
|
||||
border-radius: 8px;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent) !important;
|
||||
border: 1px solid rgba(59,130,246,0.3);
|
||||
font-weight: 500;
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.nav-links a:not(.nav-cta) { display: none; }
|
||||
}
|
||||
header.hero{text-align:center;padding:96px 24px 64px;background:radial-gradient(ellipse 80% 60% at 50% 0%,var(--accent-soft),transparent 70%),radial-gradient(ellipse 60% 40% at 80% 20%,rgba(139,92,246,.08),transparent 70%),var(--bg);position:relative}
|
||||
.hero-deco{position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;overflow:hidden}
|
||||
.hero-deco::before,.hero-deco::after{content:'';position:absolute;width:500px;height:500px;border-radius:50%;filter:blur(80px);opacity:.15}
|
||||
.hero-deco::before{background:var(--accent);top:-200px;left:-100px}
|
||||
.hero-deco::after{background:var(--accent-3);top:-100px;right:-150px}
|
||||
.hero>*{position:relative;z-index:1}
|
||||
.logo{display:inline-flex;align-items:center;gap:10px;font-size:14px;color:var(--muted);letter-spacing:.08em;text-transform:uppercase;margin-bottom:28px}
|
||||
.logo .logo-mark{width:32px;height:32px;border-radius:8px;background:var(--gradient);display:flex;align-items:center;justify-content:center;flex-shrink:0}
|
||||
h1{font-size:clamp(40px,6vw,68px);font-weight:800;letter-spacing:-.03em;line-height:1.05;margin-bottom:22px}
|
||||
h1 .grad{background:var(--gradient);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
||||
.tagline{font-size:clamp(17px,2vw,21px);color:var(--muted);max-width:640px;margin:0 auto 40px}
|
||||
.badges{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-bottom:44px}
|
||||
.badge{padding:6px 14px;background:var(--card);border:1px solid var(--border);border-radius:999px;font-size:13px;color:var(--text);transition:border-color .2s,color .2s}
|
||||
.badge:hover{border-color:var(--accent);color:var(--accent)}
|
||||
.badge.accent{border-color:var(--accent);color:var(--accent)}
|
||||
.cta{display:flex;gap:14px;justify-content:center;flex-wrap:wrap}
|
||||
.btn{display:inline-flex;align-items:center;gap:8px;padding:13px 26px;border-radius:10px;font-size:15px;font-weight:600;text-decoration:none;transition:transform .15s,box-shadow .15s;cursor:pointer;border:0}
|
||||
.btn-primary{background:var(--gradient);color:#fff;box-shadow:0 8px 24px -8px rgba(59,130,246,.6)}
|
||||
.btn-primary:hover{transform:translateY(-2px);box-shadow:0 12px 32px -8px rgba(59,130,246,.7)}
|
||||
.btn-ghost{background:var(--card);color:var(--text);border:1px solid var(--border)}
|
||||
.btn-ghost:hover{border-color:var(--accent);color:var(--accent);transform:translateY(-2px)}
|
||||
|
||||
/* Hero */
|
||||
header.hero {
|
||||
text-align: center;
|
||||
padding: 96px 24px 64px;
|
||||
background:
|
||||
radial-gradient(ellipse 80% 60% at 50% 0%, var(--accent-soft), transparent 70%),
|
||||
radial-gradient(ellipse 60% 40% at 80% 20%, rgba(139,92,246,0.08), transparent 70%),
|
||||
var(--bg);
|
||||
position: relative;
|
||||
}
|
||||
.hero-deco {
|
||||
position: absolute;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
.hero-deco::before, .hero-deco::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 500px; height: 500px;
|
||||
border-radius: 50%;
|
||||
filter: blur(80px);
|
||||
opacity: 0.15;
|
||||
}
|
||||
.hero-deco::before {
|
||||
background: var(--accent);
|
||||
top: -200px; left: -100px;
|
||||
}
|
||||
.hero-deco::after {
|
||||
background: var(--accent-3);
|
||||
top: -100px; right: -150px;
|
||||
}
|
||||
.hero > * { position: relative; z-index: 1; }
|
||||
.logo {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-size: 14px;
|
||||
color: var(--muted);
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
h1 {
|
||||
font-size: clamp(40px, 6vw, 68px);
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
line-height: 1.05;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
h1 .grad {
|
||||
background: var(--gradient);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
.tagline {
|
||||
font-size: clamp(17px, 2vw, 21px);
|
||||
color: var(--muted);
|
||||
max-width: 640px;
|
||||
margin: 0 auto 40px;
|
||||
}
|
||||
.badges {
|
||||
display: flex; flex-wrap: wrap; justify-content: center; gap: 10px;
|
||||
margin-bottom: 44px;
|
||||
}
|
||||
.badge {
|
||||
padding: 6px 14px;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 999px;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
transition: border-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
.badge:hover { border-color: var(--accent); color: var(--accent); }
|
||||
.badge.accent { border-color: var(--accent); color: var(--accent); }
|
||||
.cta { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
|
||||
.btn {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
padding: 13px 26px;
|
||||
border-radius: 10px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
||||
cursor: pointer; border: 0;
|
||||
}
|
||||
.btn-primary { background: var(--gradient); color: #fff; box-shadow: 0 8px 24px -8px rgba(59,130,246,0.6); }
|
||||
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 12px 32px -8px rgba(59,130,246,0.7); }
|
||||
.btn-ghost { background: var(--card); color: var(--text); border: 1px solid var(--border); }
|
||||
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px); }
|
||||
.stats{display:flex;justify-content:center;gap:48px;flex-wrap:wrap;margin-top:56px;padding-top:40px;border-top:1px solid var(--border)}
|
||||
.stat{text-align:center}
|
||||
.stat-num{font-size:32px;font-weight:800;background:var(--gradient);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:-.02em}
|
||||
.stat-label{font-size:13px;color:var(--muted);margin-top:4px}
|
||||
|
||||
/* 统计条 */
|
||||
.stats {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 48px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 56px;
|
||||
padding-top: 40px;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
.stat { text-align: center; }
|
||||
.stat-num {
|
||||
font-size: 32px;
|
||||
font-weight: 800;
|
||||
background: var(--gradient);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
.stat-label {
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
margin-top: 4px;
|
||||
}
|
||||
section{padding:72px 0}
|
||||
.section-eyebrow{display:inline-block;font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--accent);margin-bottom:12px;font-weight:600}
|
||||
.section-title{font-size:clamp(26px,3vw,34px);font-weight:700;letter-spacing:-.02em;margin-bottom:14px}
|
||||
.section-sub{color:var(--muted);margin-bottom:40px;font-size:16px;max-width:600px}
|
||||
|
||||
/* Section */
|
||||
section { padding: 72px 0; }
|
||||
.section-eyebrow {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.section-title {
|
||||
font-size: clamp(26px, 3vw, 34px);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.section-sub {
|
||||
color: var(--muted);
|
||||
margin-bottom: 40px;
|
||||
font-size: 16px;
|
||||
max-width: 600px;
|
||||
}
|
||||
#editor{border-radius:14px;overflow:hidden;box-shadow:var(--shadow);border:1px solid var(--border)}
|
||||
|
||||
/* Demo editor */
|
||||
#editor {
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.features{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:18px}
|
||||
.feature{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:28px 26px;transition:border-color .2s,transform .2s,background .2s}
|
||||
.feature:hover{border-color:var(--accent);transform:translateY(-4px);background:var(--card-hover)}
|
||||
.feature-icon{width:44px;height:44px;border-radius:11px;background:var(--accent-soft);color:var(--accent);display:flex;align-items:center;justify-content:center;margin-bottom:18px}
|
||||
.feature h3{font-size:17px;margin-bottom:8px;font-weight:600}
|
||||
.feature p{color:var(--muted);font-size:14px;line-height:1.65}
|
||||
|
||||
/* Features */
|
||||
.features { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 18px; }
|
||||
.feature {
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
padding: 28px 26px;
|
||||
transition: border-color 0.2s ease, transform 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
.feature:hover {
|
||||
border-color: var(--accent);
|
||||
transform: translateY(-4px);
|
||||
background: var(--card-hover);
|
||||
}
|
||||
.feature-icon {
|
||||
width: 44px; height: 44px;
|
||||
border-radius: 11px;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.feature h3 { font-size: 17px; margin-bottom: 8px; font-weight: 600; }
|
||||
.feature p { color: var(--muted); font-size: 14px; line-height: 1.65; }
|
||||
.code-block{background:var(--bg-soft);border:1px solid var(--border);border-radius:12px;padding:24px 26px;overflow-x:auto;font-family:"SF Mono","Cascadia Code",Consolas,monospace;font-size:13.5px;line-height:1.8;color:#e6e8eb;white-space:pre-wrap;tab-size:2}
|
||||
.c-key{color:#c792ea}.c-str{color:#c3e88d}.c-fn{color:#82aaff}.c-com{color:#5c6370;font-style:italic}.c-kw{color:#89ddff}.c-num{color:#f78c6c}.c-punc{color:#89ddff;opacity:.7}
|
||||
|
||||
/* Code */
|
||||
.code-block {
|
||||
background: var(--bg-soft);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 24px 26px;
|
||||
overflow-x: auto;
|
||||
font-family: "SF Mono", "Cascadia Code", Consolas, monospace;
|
||||
font-size: 13.5px;
|
||||
line-height: 1.8;
|
||||
color: #e6e8eb;
|
||||
white-space: pre-wrap;
|
||||
tab-size: 2;
|
||||
}
|
||||
.code-block .c-key { color: #c792ea; }
|
||||
.code-block .c-str { color: #c3e88d; }
|
||||
.code-block .c-fn { color: #82aaff; }
|
||||
.code-block .c-com { color: #5c6370; font-style: italic; }
|
||||
.code-block .c-kw { color: #89ddff; }
|
||||
.code-block .c-num { color: #f78c6c; }
|
||||
.code-block .c-punc { color: #89ddff; opacity: 0.7; }
|
||||
.api-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px}
|
||||
.api-card{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:22px}
|
||||
.api-card h4{font-size:14px;color:var(--accent);margin-bottom:14px;font-weight:600;letter-spacing:.02em}
|
||||
.api-card ul{list-style:none}
|
||||
.api-card li{font-family:"SF Mono",Consolas,monospace;font-size:13px;padding:5px 0;color:var(--text);border-bottom:1px solid rgba(255,255,255,.04)}
|
||||
.api-card li:last-child{border-bottom:0}
|
||||
.api-card li .ret{color:var(--muted);font-size:12px;float:right}
|
||||
|
||||
/* API 速览 */
|
||||
.api-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.api-card {
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 22px 22px;
|
||||
}
|
||||
.api-card h4 {
|
||||
font-size: 14px;
|
||||
color: var(--accent);
|
||||
margin-bottom: 14px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.api-card ul { list-style: none; }
|
||||
.api-card li {
|
||||
font-family: "SF Mono", Consolas, monospace;
|
||||
font-size: 13px;
|
||||
padding: 5px 0;
|
||||
color: var(--text);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.04);
|
||||
}
|
||||
.api-card li:last-child { border-bottom: 0; }
|
||||
.api-card li .ret {
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
float: right;
|
||||
}
|
||||
.shortcuts{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}
|
||||
.shortcut{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:var(--card);border:1px solid var(--border);border-radius:10px}
|
||||
.shortcut-label{font-size:14px;color:var(--text)}
|
||||
.keys{display:flex;gap:4px}
|
||||
.key{display:inline-flex;align-items:center;padding:3px 8px;background:var(--bg-soft);border:1px solid var(--border);border-bottom-width:2px;border-radius:5px;font-family:"SF Mono",Consolas,monospace;font-size:12px;color:var(--muted)}
|
||||
|
||||
/* 快捷键 */
|
||||
.shortcuts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.shortcut {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.shortcut-label { font-size: 14px; color: var(--text); }
|
||||
.keys { display: flex; gap: 4px; }
|
||||
.key {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 3px 8px;
|
||||
background: var(--bg-soft);
|
||||
border: 1px solid var(--border);
|
||||
border-bottom-width: 2px;
|
||||
border-radius: 5px;
|
||||
font-family: "SF Mono", Consolas, monospace;
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
}
|
||||
footer{border-top:1px solid var(--border);padding:48px 24px;text-align:center;color:var(--muted);font-size:14px;background:var(--bg-soft)}
|
||||
footer a{color:var(--accent);text-decoration:none}
|
||||
footer a:hover{text-decoration:underline}
|
||||
.footer-links{display:flex;justify-content:center;gap:24px;margin-bottom:16px;flex-wrap:wrap}
|
||||
|
||||
footer {
|
||||
border-top: 1px solid var(--border);
|
||||
padding: 48px 24px;
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
font-size: 14px;
|
||||
background: var(--bg-soft);
|
||||
}
|
||||
footer a { color: var(--accent); text-decoration: none; }
|
||||
footer a:hover { text-decoration: underline; }
|
||||
.footer-links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 24px;
|
||||
margin-bottom: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* 编辑器在深色页面里的适配:让 wrapper 跟随页面深色 */
|
||||
.me-wrapper { background: var(--card); }
|
||||
.me-wrapper{background:var(--card)}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav>
|
||||
<div class="nav-inner">
|
||||
<a class="nav-brand" href="#">
|
||||
<span class="logo-mark" title="MetonaEditor" aria-label="MetonaEditor Logo"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19V6l7 8 7-8v13"/></svg></span>
|
||||
MetonaEditor
|
||||
</a>
|
||||
<a class="nav-brand" href="#"><span class="logo-mark" title="MetonaEditor"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19V6l7 8 7-8v13"/></svg></span>MetonaEditor</a>
|
||||
<div class="nav-links">
|
||||
<a href="#features">特性</a>
|
||||
<a href="#demo">体验</a>
|
||||
<a href="#api">API</a>
|
||||
<a href="#shortcuts">快捷键</a>
|
||||
<a href="docs.html">文档</a>
|
||||
<a class="nav-cta" href="demo.html">在线演示</a>
|
||||
<a href="#features">特性</a><a href="#demo">体验</a><a href="#api">API</a><a href="#shortcuts">快捷键</a>
|
||||
<a href="docs.html">文档</a><a class="nav-cta" href="demo.html">在线演示</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<header class="hero">
|
||||
<div class="hero-deco"></div>
|
||||
<div class="logo"><span class="logo-mark" title="MetonaEditor" aria-label="MetonaEditor Logo"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19V6l7 8 7-8v13"/></svg></span> METONA EDITOR</div>
|
||||
<h1>现代化零依赖的<br/><span class="grad">Markdown 编辑器</span></h1>
|
||||
<p class="tagline">单文件开箱即用,内置轻量解析器、分屏预览、插件系统与中文优先的国际化。为中文场景与现代 Web 应用而生。</p>
|
||||
<div class="logo"><span class="logo-mark"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 19V6l7 8 7-8v13"/></svg></span>METONA EDITOR</div>
|
||||
<h1>TypeScript 重构 · 零依赖<br/><span class="grad">桌面端 Markdown 编辑器</span></h1>
|
||||
<p class="tagline">全模块 TypeScript 严格模式,内置自研解析器(99% 行覆盖率),6 个预设插件,中文优先。为桌面端现代 Web 应用而生。</p>
|
||||
<div class="badges">
|
||||
<span class="badge accent">零依赖</span>
|
||||
<span class="badge">UMD / ESM / CJS</span>
|
||||
<span class="badge accent">v0.2.0</span>
|
||||
<span class="badge">TypeScript</span>
|
||||
<span class="badge">主题可定制</span>
|
||||
<span class="badge">中文优先</span>
|
||||
<span class="badge">零运行时依赖</span>
|
||||
<span class="badge">610 tests</span>
|
||||
<span class="badge">桌面端优先</span>
|
||||
<span class="badge">MIT</span>
|
||||
</div>
|
||||
<div class="cta">
|
||||
<a class="btn btn-primary" href="demo.html">在线体验 →</a>
|
||||
<a class="btn btn-ghost" href="#features">了解特性</a>
|
||||
<a class="btn btn-ghost" href="docs.html">查阅文档</a>
|
||||
</div>
|
||||
<div class="stats">
|
||||
<div class="stat">
|
||||
<div class="stat-num">0</div>
|
||||
<div class="stat-label">运行时依赖</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-num">558+</div>
|
||||
<div class="stat-label">单元测试</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-num">80%+</div>
|
||||
<div class="stat-label">测试覆盖率</div>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<div class="stat-num">15KB</div>
|
||||
<div class="stat-label">gzip 体积</div>
|
||||
</div>
|
||||
<div class="stat"><div class="stat-num">0</div><div class="stat-label">运行时依赖</div></div>
|
||||
<div class="stat"><div class="stat-num">99%</div><div class="stat-label">解析器行覆盖</div></div>
|
||||
<div class="stat"><div class="stat-num">610</div><div class="stat-label">单元测试</div></div>
|
||||
<div class="stat"><div class="stat-num">~30KB</div><div class="stat-label">gzip 体积</div></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -439,7 +129,7 @@
|
||||
<div class="container">
|
||||
<span class="section-eyebrow">Live Demo</span>
|
||||
<h2 class="section-title">立即体验</h2>
|
||||
<p class="section-sub">下面是一个真实可用的编辑器实例,试着在左侧编辑,右侧会实时预览。</p>
|
||||
<p class="section-sub">真实可用的编辑器实例,支持粗斜体、链接内格式、数学公式、Mermaid 图表等全部语法。</p>
|
||||
<div id="editor"></div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -448,50 +138,14 @@
|
||||
<div class="container">
|
||||
<span class="section-eyebrow">Features</span>
|
||||
<h2 class="section-title">为什么选择 MetonaEditor</h2>
|
||||
<p class="section-sub">为中文场景与现代 Web 应用而生,每一项特性都经过精心打磨。</p>
|
||||
<p class="section-sub">为桌面端场景精心打磨,每一项特性都经过充分测试。</p>
|
||||
<div class="features">
|
||||
<div class="feature">
|
||||
<div class="feature-icon">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
|
||||
</div>
|
||||
<h3>真正的零依赖</h3>
|
||||
<p>整个库不依赖任何第三方运行时,打包后单文件可直接 <script> 引入,也支持 npm 安装。</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<div class="feature-icon">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="12" y1="3" x2="12" y2="21"/></svg>
|
||||
</div>
|
||||
<h3>分屏实时预览</h3>
|
||||
<p>编辑 / 分屏 / 预览三模式自由切换,分屏模式下可拖拽分隔条调整比例,滚动自动同步。</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<div class="feature-icon">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
|
||||
</div>
|
||||
<h3>内置增强解析器</h3>
|
||||
<p>自研 CommonMark + GFM 扩展解析器,覆盖数学公式、脚注、嵌套列表、定义列表、表格对齐、任务列表等丰富语法,也可整体替换。</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<div class="feature-icon">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
||||
</div>
|
||||
<h3>易扩展的插件系统</h3>
|
||||
<p>插件 v2 支持依赖拓扑排序、异步加载、动态卸载;自定义快捷键与工具栏,右键上下文菜单。</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<div class="feature-icon">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/></svg>
|
||||
</div>
|
||||
<h3>主题与国际化</h3>
|
||||
<p>实例级主题隔离、外部跟随同步、主题继承,内置 4 套预设;中英双语开箱即用,支持 RTL 布局。</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<div class="feature-icon">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
||||
</div>
|
||||
<h3>XSS 安全防护</h3>
|
||||
<p>所有文本经 HTML 转义,URL 过滤 javascript / vbscript / file 等危险协议,并提供 sanitize 钩子。</p>
|
||||
</div>
|
||||
<div class="feature"><div class="feature-icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg></div><h3>TypeScript 源码</h3><p>全模块 TypeScript 严格模式,完整类型导出,IDE 智能提示。无需额外安装 @types 包。</p></div>
|
||||
<div class="feature"><div class="feature-icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="12" y1="3" x2="12" y2="21"/></svg></div><h3>分屏实时预览</h3><p>edit / split / preview 三模式切换,拖拽分隔条调整比例,双向比例同步滚动。</p></div>
|
||||
<div class="feature"><div class="feature-icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg></div><h3>零运行时依赖</h3><p>不依赖任何第三方运行时库,打包后单文件,UMD / ESM / CJS 三种格式开箱即用。</p></div>
|
||||
<div class="feature"><div class="feature-icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></div><h3>6 个预设插件</h3><p>autoSave / exportTool / searchReplace / imagePaste / shortcutHelp / fileSystem,插件 v2 支持拓扑排序、异步、卸载。</p></div>
|
||||
<div class="feature"><div class="feature-icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/></svg></div><h3>主题 & i18n</h3><p>4 套预设主题 + CSS 变量定制 + 实例级隔离。中英双语开箱即用,支持远程加载翻译包。</p></div>
|
||||
<div class="feature"><div class="feature-icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg></div><h3>XSS 安全防护</h3><p>HTML 转义、危险协议过滤、sanitize 钩子、highlight 异常回退。多层防护,安全可靠。</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -500,25 +154,15 @@
|
||||
<div class="container">
|
||||
<span class="section-eyebrow">Quick Start</span>
|
||||
<h2 class="section-title">三行代码即可使用</h2>
|
||||
<p class="section-sub">CDN 引入或 npm 安装,都只需要极少的代码。</p>
|
||||
<div class="code-block"><span class="c-com"><!-- 浏览器直接引入 --></span>
|
||||
<span class="c-punc"><</span><span class="c-key">script</span> <span class="c-fn">src</span><span class="c-punc">=</span><span class="c-str">"../dist/metona-editor.js"</span><span class="c-punc">></</span><span class="c-key">script</span><span class="c-punc">></span>
|
||||
<span class="c-punc"><</span><span class="c-key">div</span> <span class="c-fn">id</span><span class="c-punc">=</span><span class="c-str">"editor"</span><span class="c-punc">></</span><span class="c-key">div</span><span class="c-punc">></span>
|
||||
<span class="c-punc"><</span><span class="c-key">script</span><span class="c-punc">></span>
|
||||
<span class="c-kw">const</span> editor <span class="c-punc">=</span> <span class="c-fn">MeEditor.create</span><span class="c-punc">(</span><span class="c-str">'#editor'</span><span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
<span class="c-fn">mode</span><span class="c-punc">:</span> <span class="c-str">'split'</span><span class="c-punc">,</span>
|
||||
<span class="c-fn">value</span><span class="c-punc">:</span> <span class="c-str">'# 你好,世界'</span><span class="c-punc">,</span>
|
||||
<span class="c-fn">plugins</span><span class="c-punc">:</span> <span class="c-punc">[</span><span class="c-str">'autoSave'</span><span class="c-punc">,</span> <span class="c-str">'exportTool'</span><span class="c-punc">]</span>
|
||||
<span class="c-punc">});</span>
|
||||
<span class="c-punc"></</span><span class="c-key">script</span><span class="c-punc">></span>
|
||||
|
||||
<span class="c-com">// 或 npm 安装</span>
|
||||
<p class="section-sub">TypeScript / npm / CDN 三种引入方式,都只需极少代码。</p>
|
||||
<div class="code-block"><span class="c-com">// npm 安装</span>
|
||||
<span class="c-kw">import</span> MeEditor <span class="c-kw">from</span> <span class="c-str">'@metona-team/metona-editor'</span><span class="c-punc">;</span>
|
||||
|
||||
<span class="c-kw">const</span> editor <span class="c-punc">=</span> <span class="c-fn">MeEditor.create</span><span class="c-punc">(</span>container<span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
<span class="c-kw">const</span> editor <span class="c-punc">=</span> MeEditor<span class="c-punc">.</span><span class="c-fn">create</span><span class="c-punc">(</span><span class="c-str">'#editor'</span><span class="c-punc">,</span> <span class="c-punc">{</span>
|
||||
<span class="c-fn">value</span><span class="c-punc">:</span> <span class="c-str">'# 你好,世界'</span><span class="c-punc">,</span>
|
||||
<span class="c-fn">mode</span><span class="c-punc">:</span> <span class="c-str">'split'</span><span class="c-punc">,</span>
|
||||
<span class="c-fn">theme</span><span class="c-punc">:</span> <span class="c-str">'dark'</span><span class="c-punc">,</span>
|
||||
<span class="c-fn">onChange</span><span class="c-punc">:</span> <span class="c-punc">(</span>value<span class="c-punc">)</span> <span class="c-punc">=></span> <span class="c-fn">console.log</span><span class="c-punc">(</span>value<span class="c-punc">)</span>
|
||||
<span class="c-fn">plugins</span><span class="c-punc">:</span> <span class="c-punc">[</span><span class="c-str">'autoSave'</span><span class="c-punc">,</span> <span class="c-str">'searchReplace'</span><span class="c-punc">]</span>
|
||||
<span class="c-punc">});</span>
|
||||
|
||||
<span class="c-com">// 链式 API</span>
|
||||
@@ -530,140 +174,34 @@
|
||||
<div class="container">
|
||||
<span class="section-eyebrow">API Reference</span>
|
||||
<h2 class="section-title">API 速览</h2>
|
||||
<p class="section-sub">完整 API 文档请参考 README.md,以下是最常用的方法。</p>
|
||||
<div class="api-grid">
|
||||
<div class="api-card">
|
||||
<h4>内容操作</h4>
|
||||
<ul>
|
||||
<li>getValue() <span class="ret">string</span></li>
|
||||
<li>setValue(md) <span class="ret">this</span></li>
|
||||
<li>getHTML() <span class="ret">string</span></li>
|
||||
<li>insert(text) <span class="ret">this</span></li>
|
||||
<li>wrap(before, after) <span class="ret">this</span></li>
|
||||
<li>focus() / blur() <span class="ret">this</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="api-card">
|
||||
<h4>命令执行</h4>
|
||||
<ul>
|
||||
<li>exec(action) <span class="ret">this</span></li>
|
||||
<li>undo() / redo() <span class="ret">this</span></li>
|
||||
<li>canUndo() <span class="ret">boolean</span></li>
|
||||
<li>canRedo() <span class="ret">boolean</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="api-card">
|
||||
<h4>模式与全屏</h4>
|
||||
<ul>
|
||||
<li>setMode(mode) <span class="ret">this</span></li>
|
||||
<li>getMode() <span class="ret">string</span></li>
|
||||
<li>toggleFullscreen() <span class="ret">this</span></li>
|
||||
<li>isFullscreen() <span class="ret">boolean</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="api-card">
|
||||
<h4>事件与插件</h4>
|
||||
<ul>
|
||||
<li>on(event, fn) <span class="ret">unsub</span></li>
|
||||
<li>off(event, fn) <span class="ret">void</span></li>
|
||||
<li>use(plugin) <span class="ret">this</span></li>
|
||||
<li>getPlugins() <span class="ret">Plugin[]</span></li>
|
||||
<li>addToolbarButton(cfg) <span class="ret">this</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="api-card">
|
||||
<h4>统计与状态</h4>
|
||||
<ul>
|
||||
<li>getStats() <span class="ret">Stats</span></li>
|
||||
<li>getStatus() <span class="ret">Status</span></li>
|
||||
<li>enable() / disable() <span class="ret">this</span></li>
|
||||
<li>destroy() <span class="ret">void</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="api-card">
|
||||
<h4>静态 API</h4>
|
||||
<ul>
|
||||
<li>MeEditor.create(el, opts) <span class="ret">Editor</span></li>
|
||||
<li>MeEditor.use(plugin) <span class="ret">void</span></li>
|
||||
<li>MeEditor.setTheme(name) <span class="ret">void</span></li>
|
||||
<li>MeEditor.setLocale(name) <span class="ret">void</span></li>
|
||||
<li>MeEditor.on(hook, fn) <span class="ret">void</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="api-card"><h4>内容操作</h4><ul><li>getValue() <span class="ret">string</span></li><li>setValue(md) <span class="ret">this</span></li><li>getHTML() <span class="ret">string</span></li><li>insert(text) <span class="ret">this</span></li><li>wrap(before, after) <span class="ret">this</span></li><li>focus() / blur() <span class="ret">this</span></li></ul></div>
|
||||
<div class="api-card"><h4>命令执行</h4><ul><li>exec(action) <span class="ret">this</span></li><li>undo() / redo() <span class="ret">this</span></li><li>canUndo() / canRedo() <span class="ret">boolean</span></li></ul></div>
|
||||
<div class="api-card"><h4>模式与全屏</h4><ul><li>setMode(mode) <span class="ret">this</span></li><li>getMode() <span class="ret">string</span></li><li>toggleFullscreen() <span class="ret">this</span></li><li>toggleZen() <span class="ret">this</span></li></ul></div>
|
||||
<div class="api-card"><h4>事件与插件</h4><ul><li>on(event, fn) <span class="ret">unsub</span></li><li>off(event, fn) <span class="ret">this</span></li><li>use(plugin) <span class="ret">this</span></li><li>unuse(name) <span class="ret">this</span></li><li>addToolbarButton(cfg) <span class="ret">this</span></li></ul></div>
|
||||
<div class="api-card"><h4>主题与语言</h4><ul><li>setTheme(name) <span class="ret">this</span></li><li>getTheme() <span class="ret">string</span></li><li>setLocale(loc) <span class="ret">this</span></li><li>getLocale() <span class="ret">string</span></li><li>t(key, params) <span class="ret">string</span></li></ul></div>
|
||||
<div class="api-card"><h4>统计与状态</h4><ul><li>getStats() <span class="ret">Stats</span></li><li>getStatus() <span class="ret">Status</span></li><li>enable() / disable() <span class="ret">this</span></li><li>refresh() <span class="ret">this</span></li><li>destroy() <span class="ret">void</span></li></ul></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="shortcuts">
|
||||
<div class="container">
|
||||
<span class="section-eyebrow">Keyboard Shortcuts</span>
|
||||
<span class="section-eyebrow">Keyboard</span>
|
||||
<h2 class="section-title">快捷键</h2>
|
||||
<p class="section-sub">Mac 用户请将 Ctrl 替换为 Cmd。</p>
|
||||
<div class="shortcuts">
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">加粗</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">B</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">斜体</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">I</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">行内代码</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">E</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">下划线</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">U</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">插入链接</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">K</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">标题 1/2/3</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">1/2/3</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">引用</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">Q</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">撤销</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">Z</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">重做</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">Shift+Z</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">保存</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">S</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">查找</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">F</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">查找替换</span>
|
||||
<div class="keys"><span class="key">Ctrl</span><span class="key">H</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">缩进 / 反缩进</span>
|
||||
<div class="keys"><span class="key">Tab</span><span class="key">Shift+Tab</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">下一个匹配</span>
|
||||
<div class="keys"><span class="key">Enter</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">上一个匹配</span>
|
||||
<div class="keys"><span class="key">Shift</span><span class="key">Enter</span></div>
|
||||
</div>
|
||||
<div class="shortcut">
|
||||
<span class="shortcut-label">关闭面板</span>
|
||||
<div class="keys"><span class="key">Esc</span></div>
|
||||
</div>
|
||||
<div class="shortcut"><span class="shortcut-label">粗体</span><div class="keys"><span class="key">Ctrl</span><span class="key">B</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">斜体</span><div class="keys"><span class="key">Ctrl</span><span class="key">I</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">行内代码</span><div class="keys"><span class="key">Ctrl</span><span class="key">E</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">下划线</span><div class="keys"><span class="key">Ctrl</span><span class="key">U</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">插入链接</span><div class="keys"><span class="key">Ctrl</span><span class="key">K</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">标题 1/2/3</span><div class="keys"><span class="key">Ctrl</span><span class="key">1/2/3</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">引用</span><div class="keys"><span class="key">Ctrl</span><span class="key">Q</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">撤销 / 重做</span><div class="keys"><span class="key">Ctrl</span><span class="key">Z/Y</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">保存</span><div class="keys"><span class="key">Ctrl</span><span class="key">S</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">查找 / 替换</span><div class="keys"><span class="key">Ctrl</span><span class="key">F/H</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">缩进 / 反缩进</span><div class="keys"><span class="key">Tab</span><span class="key">Shift+Tab</span></div></div>
|
||||
<div class="shortcut"><span class="shortcut-label">快捷键帮助</span><div class="keys"><span class="key">?</span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -673,11 +211,10 @@
|
||||
<div class="footer-links">
|
||||
<a href="demo.html">在线演示</a>
|
||||
<a href="docs.html">文档</a>
|
||||
<a href="https://git.metona.cn/MetonaTeam/-/packages/npm/@metona-team%2Fmetona-editor" target="_blank" rel="noopener">npm</a>
|
||||
<a href="https://git.metona.cn/MetonaTeam/MetonaEditor" target="_blank" rel="noopener">源码仓库</a>
|
||||
<a href="https://git.metona.cn/MetonaTeam/MetonaEditor/issues" target="_blank" rel="noopener">问题反馈</a>
|
||||
</div>
|
||||
<div>MetonaEditor · MIT License · 由 <a href="https://git.metona.cn/MetonaTeam" target="_blank" rel="noopener">Metona Team</a> 出品</div>
|
||||
<div>MetonaEditor v0.2.0 · TypeScript · MIT License · MetonaTeam</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -685,56 +222,55 @@
|
||||
<script>
|
||||
MeEditor.themes.switchTheme('dark');
|
||||
MeEditor.create('#editor', {
|
||||
mode: 'split',
|
||||
height: 480,
|
||||
theme: 'dark',
|
||||
mode: 'split', height: 480, theme: 'dark',
|
||||
value: [
|
||||
'# 欢迎使用 MetonaEditor',
|
||||
'# 欢迎使用 MetonaEditor v0.2.0',
|
||||
'',
|
||||
'一个**现代化、零依赖**的 Markdown 编辑器库。',
|
||||
'一个 **TypeScript 重构 · 零运行时依赖** 的桌面端 Markdown 编辑器。',
|
||||
'',
|
||||
'## 核心特性',
|
||||
'',
|
||||
'- 分屏实时预览,滚动同步',
|
||||
'- 内置轻量解析器,支持 GFM',
|
||||
'- 插件系统:`autoSave` / `exportTool` / `searchReplace`',
|
||||
'- 主题与国际化,中文优先',
|
||||
'- 完整 XSS 防护,安全可靠',
|
||||
'- TypeScript 严格模式,完整类型导出',
|
||||
'- 分屏实时预览,双向滚动同步',
|
||||
'- 自研解析器:***粗斜体*** 、[**粗体链接**](https://example.com)',
|
||||
'- 6 个预设插件:`autoSave` `searchReplace` `fileSystem` 等',
|
||||
'- 4 套主题 + CSS 变量定制 + 实例级隔离',
|
||||
'- 行号装订线 · Zen 专注模式 · 大纲面板',
|
||||
'',
|
||||
'## 代码示例',
|
||||
'',
|
||||
'```js',
|
||||
'```ts',
|
||||
'import MeEditor from "@metona-team/metona-editor";',
|
||||
'const editor = MeEditor.create("#editor", {',
|
||||
' mode: "split",',
|
||||
' plugins: ["autoSave", "searchReplace"]',
|
||||
' theme: "dark",',
|
||||
' plugins: ["autoSave", "fileSystem"],',
|
||||
'});',
|
||||
'```',
|
||||
'',
|
||||
'> 试着在左侧编辑这段文字,右侧会实时更新预览。',
|
||||
'## 语法示例',
|
||||
'',
|
||||
'| 特性 | 说明 |',
|
||||
'| 语法 | 说明 |',
|
||||
'| --- | --- |',
|
||||
'| 零依赖 | 无任何运行时第三方库 |',
|
||||
'| 分屏 | 编辑+预览同步滚动 |',
|
||||
'| 插件 | install/destroy 生命周期 |',
|
||||
'| 主题 | light/dark/warm/auto |',
|
||||
'| **粗体** / *斜体* / ***粗斜体*** | 强调 |',
|
||||
'| `code` / ``` ```lang ``` | 代码 |',
|
||||
'| [链接](url) /  | 链接 |',
|
||||
'| $E=mc^2$ / $$\int$$ | 数学公式 |',
|
||||
'| - [x] 任务列表 | GFM |',
|
||||
'| :rocket: :fire: | Emoji 短码 |',
|
||||
'',
|
||||
'### 任务列表示例',
|
||||
'### 任务列表',
|
||||
'',
|
||||
'- [x] 核心编辑器实现',
|
||||
'- [x] 解析器与 XSS 防护',
|
||||
'- [x] 插件系统',
|
||||
'- [ ] 更多预设插件',
|
||||
'- [x] TypeScript 重构完成',
|
||||
'- [x] 解析器覆盖率 99%',
|
||||
'- [x] 6 个预设插件',
|
||||
'- [ ] VS Code 扩展',
|
||||
'',
|
||||
'1. 点击工具栏按钮快速插入格式',
|
||||
'2. 拖拽中间分隔条调整比例',
|
||||
'3. 按 `Ctrl+B` 加粗、`Ctrl+K` 插入链接',
|
||||
'4. 按 `Ctrl+F` 查找、`Ctrl+S` 保存',
|
||||
'> **提示**:按 `?` 查看快捷键 · 拖放文件到编辑区 · Ctrl+F 搜索 · Ctrl+H 替换',
|
||||
'',
|
||||
'享受写作 ✨'
|
||||
].join('\n')
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user