Initial commit: MetonaEditor v0.1.0
This commit is contained in:
+728
@@ -0,0 +1,728 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>MetonaEditor — 现代化零依赖 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; }
|
||||
|
||||
/* 导航 */
|
||||
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;
|
||||
font-weight: 800; color: #fff; font-size: 15px;
|
||||
}
|
||||
.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; }
|
||||
}
|
||||
|
||||
/* 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: -0.02em;
|
||||
}
|
||||
.stat-label {
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Demo editor */
|
||||
#editor {
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
.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;
|
||||
}
|
||||
.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; }
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav>
|
||||
<div class="nav-inner">
|
||||
<a class="nav-brand" href="#">
|
||||
<span class="logo-mark">M</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 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">M</span> METONA EDITOR</div>
|
||||
<h1>现代化零依赖的<br/><span class="grad">Markdown 编辑器</span></h1>
|
||||
<p class="tagline">单文件开箱即用,内置轻量解析器、分屏预览、插件系统与中文优先的国际化。为中文场景与现代 Web 应用而生。</p>
|
||||
<div class="badges">
|
||||
<span class="badge accent">零依赖</span>
|
||||
<span class="badge">UMD / ESM / CJS</span>
|
||||
<span class="badge">TypeScript</span>
|
||||
<span class="badge">主题可定制</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>
|
||||
</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">390+</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>
|
||||
</header>
|
||||
|
||||
<section id="demo">
|
||||
<div class="container">
|
||||
<span class="section-eyebrow">Live Demo</span>
|
||||
<h2 class="section-title">立即体验</h2>
|
||||
<p class="section-sub">下面是一个真实可用的编辑器实例,试着在左侧编辑,右侧会实时预览。</p>
|
||||
<div id="editor"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="features">
|
||||
<div class="container">
|
||||
<span class="section-eyebrow">Features</span>
|
||||
<h2 class="section-title">为什么选择 MetonaEditor</h2>
|
||||
<p class="section-sub">为中文场景与现代 Web 应用而生,每一项特性都经过精心打磨。</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>内置自动保存、导出、查找替换插件;自定义插件只需实现 install / destroy 两个生命周期钩子。</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>基于 CSS 变量的主题系统,内置亮 / 暗 / 暖色三套主题;中英双语开箱即用,支持 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>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<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-key">script</span> <span class="c-fn">src</span>=<span class="c-str">"dist/metona-editor.js"</span>></<span class="c-key">script</span>>
|
||||
<<span class="c-key">div</span> <span class="c-fn">id</span>=<span class="c-str">"editor"</span>></<span class="c-key">div</span>>
|
||||
<<span class="c-key">script</span>>
|
||||
<span class="c-kw">const</span> editor = <span class="c-fn">MeEditor.create</span>(<span class="c-str">'#editor'</span>, {
|
||||
<span class="c-fn">mode</span>: <span class="c-str">'split'</span>,
|
||||
<span class="c-fn">value</span>: <span class="c-str">'# 你好,世界'</span>,
|
||||
<span class="c-fn">plugins</span>: [<span class="c-str">'autoSave'</span>, <span class="c-str">'exportTool'</span>]
|
||||
});
|
||||
</<span class="c-key">script</span>>
|
||||
|
||||
<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-kw">const</span> editor = <span class="c-fn">MeEditor.create</span>(container, {
|
||||
<span class="c-fn">mode</span>: <span class="c-str">'split'</span>,
|
||||
<span class="c-fn">theme</span>: <span class="c-str">'dark'</span>,
|
||||
<span class="c-fn">onChange</span>: (value) => <span class="c-fn">console.log</span>(value)
|
||||
});
|
||||
|
||||
<span class="c-com">// 链式 API</span>
|
||||
editor.<span class="c-fn">exec</span>(<span class="c-str">'bold'</span>).<span class="c-fn">exec</span>(<span class="c-str">'h1'</span>).<span class="c-fn">focus</span>();
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="api">
|
||||
<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>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="shortcuts">
|
||||
<div class="container">
|
||||
<span class="section-eyebrow">Keyboard Shortcuts</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>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<div class="footer-links">
|
||||
<a href="demo.html">在线演示</a>
|
||||
<a href="https://www.npmjs.com/package/@metona-team/metona-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>
|
||||
</footer>
|
||||
|
||||
<script src="../dist/metona-editor.js"></script>
|
||||
<script>
|
||||
MeEditor.themes.switchTheme('dark');
|
||||
MeEditor.create('#editor', {
|
||||
mode: 'split',
|
||||
height: 480,
|
||||
theme: 'dark',
|
||||
value: [
|
||||
'# 欢迎使用 MetonaEditor',
|
||||
'',
|
||||
'一个**现代化、零依赖**的 Markdown 编辑器库。',
|
||||
'',
|
||||
'## 核心特性',
|
||||
'',
|
||||
'- 分屏实时预览,滚动同步',
|
||||
'- 内置轻量解析器,支持 GFM',
|
||||
'- 插件系统:`autoSave` / `exportTool` / `searchReplace`',
|
||||
'- 主题与国际化,中文优先',
|
||||
'- 完整 XSS 防护,安全可靠',
|
||||
'',
|
||||
'## 代码示例',
|
||||
'',
|
||||
'```js',
|
||||
'const editor = MeEditor.create("#editor", {',
|
||||
' mode: "split",',
|
||||
' plugins: ["autoSave", "searchReplace"]',
|
||||
'});',
|
||||
'```',
|
||||
'',
|
||||
'> 试着在左侧编辑这段文字,右侧会实时更新预览。',
|
||||
'',
|
||||
'| 特性 | 说明 |',
|
||||
'| --- | --- |',
|
||||
'| 零依赖 | 无任何运行时第三方库 |',
|
||||
'| 分屏 | 编辑+预览同步滚动 |',
|
||||
'| 插件 | install/destroy 生命周期 |',
|
||||
'| 主题 | light/dark/warm/auto |',
|
||||
'',
|
||||
'### 任务列表示例',
|
||||
'',
|
||||
'- [x] 核心编辑器实现',
|
||||
'- [x] 解析器与 XSS 防护',
|
||||
'- [x] 插件系统',
|
||||
'- [ ] 更多预设插件',
|
||||
'',
|
||||
'1. 点击工具栏按钮快速插入格式',
|
||||
'2. 拖拽中间分隔条调整比例',
|
||||
'3. 按 `Ctrl+B` 加粗、`Ctrl+K` 插入链接',
|
||||
'4. 按 `Ctrl+F` 查找、`Ctrl+S` 保存',
|
||||
'',
|
||||
'享受写作 ✨'
|
||||
].join('\n')
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user