Arrow functions in code examples were unescaped, causing parse errors in some browsers. Script block arrow functions preserved.
622 lines
42 KiB
HTML
622 lines
42 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||
<title>MetonaEditor · 文档</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; }
|
||
|
||
/* 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 */
|
||
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; }
|
||
|
||
/* 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); }
|
||
|
||
/* 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 */
|
||
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; }
|
||
|
||
/* 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%; }
|
||
}
|
||
</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>
|
||
</div>
|
||
</nav>
|
||
|
||
<header class="docs-header">
|
||
<h1><span class="grad">文档</span></h1>
|
||
<p class="sub">MetonaEditor v0.1.3 完整 API、配置与使用指南</p>
|
||
</header>
|
||
|
||
<div class="container">
|
||
<div class="docs-layout">
|
||
<div class="sidebar" id="sidebar">
|
||
<div class="toc-group">快速入门</div>
|
||
<a href="#quickstart">安装与引入</a>
|
||
<div class="toc-group">配置</div>
|
||
<a href="#config">全部配置项</a>
|
||
<a href="#toolbar">工具栏</a>
|
||
<div class="toc-group">实例 API</div>
|
||
<a href="#api-content">内容操作</a>
|
||
<a href="#api-exec">命令执行</a>
|
||
<a href="#api-history">历史栈</a>
|
||
<a href="#api-mode">模式与全屏</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>
|
||
<div class="toc-group">静态 API</div>
|
||
<a href="#static-api">顶层函数</a>
|
||
<div class="toc-group">语法参考</div>
|
||
<a href="#syntax">解析器语法</a>
|
||
<div class="toc-group">插件</div>
|
||
<a href="#plugins">插件约定</a>
|
||
<a href="#preset-plugins">预设插件</a>
|
||
<div class="toc-group">主题</div>
|
||
<a href="#themes">主题系统</a>
|
||
<div class="toc-group">国际化</div>
|
||
<a href="#i18n">i18n API</a>
|
||
</div>
|
||
|
||
<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-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"><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>
|
||
|
||
<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>
|
||
|
||
<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>
|
||
|
||
<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>
|
||
|
||
<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>
|
||
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>
|
||
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>
|
||
|
||
<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-punc">});</span></pre>
|
||
</section>
|
||
|
||
<!-- ======== 工具栏 ======== -->
|
||
<section id="toolbar">
|
||
<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>
|
||
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>
|
||
|
||
<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>
|
||
<span class="badge">h1</span><span class="badge">h2</span><span class="badge">h3</span><span class="badge">quote</span><span class="badge">ul</span><span class="badge">ol</span>
|
||
<span class="badge">indent</span><span class="badge">outdent</span><span class="badge">hr</span>
|
||
<span class="badge">link</span><span class="badge">image</span><span class="badge">table</span>
|
||
<span class="badge">undo</span><span class="badge">redo</span>
|
||
<span class="badge">edit</span><span class="badge">split</span><span class="badge">preview</span><span class="badge">fullscreen</span>
|
||
</p>
|
||
</section>
|
||
|
||
<!-- ======== 实例 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>
|
||
</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>
|
||
|
||
<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>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>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>
|
||
</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>
|
||
|
||
<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>
|
||
|
||
<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>
|
||
|
||
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>
|
||
</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>
|
||
|
||
<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><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>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>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>
|
||
</table>
|
||
|
||
<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>
|
||
</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>
|
||
|
||
<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>
|
||
|
||
<!-- ======== 静态 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>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>
|
||
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>
|
||
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>
|
||
</section>
|
||
|
||
<!-- ======== 语法参考 ======== -->
|
||
<section id="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>斜体</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>链接</td><td><code>[text](url)</code></td><td><code><a></code></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>😊 🚀(80+ 常用)</td></tr>
|
||
</table>
|
||
|
||
<h3>XSS 防护</h3>
|
||
<p>所有文本经 HTML 转义。URL 自动过滤 <code>javascript:</code> <code>vbscript:</code> <code>file:</code> 及非图片 <code>data:</code> 协议。</p>
|
||
</section>
|
||
|
||
<!-- ======== 插件 ======== -->
|
||
<section id="plugins">
|
||
<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>
|
||
<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>
|
||
|
||
<!-- ======== 主题 ======== -->
|
||
<section id="themes">
|
||
<h2>主题系统</h2>
|
||
|
||
<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">// 注册自定义主题</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>
|
||
bg<span class="c-punc">:</span> <span class="c-str">'#001122'</span><span class="c-punc">,</span> text<span class="c-punc">:</span> <span class="c-str">'#aabbcc'</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-punc">});</span>
|
||
themeUtils<span class="c-punc">.</span><span class="c-fn">applyTheme</span><span class="c-punc">(</span><span class="c-str">'ocean'</span><span class="c-punc">);</span></pre>
|
||
|
||
<p>CSS 变量:主题变量限定在 <code>.me-wrapper</code> 元素上,不污染全局样式。支持 <code>@media print</code> 打印样式。</p>
|
||
</section>
|
||
|
||
<!-- ======== 国际化 ======== -->
|
||
<section id="i18n">
|
||
<h2>国际化</h2>
|
||
|
||
<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-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>
|
||
|
||
<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>
|
||
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>
|
||
</section>
|
||
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<footer>
|
||
<div class="container">
|
||
MetonaEditor v0.1.3 · <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);
|
||
});
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|