feat(parser): v0.1.15 — parser short+medium term improvements
Short-term fixes: - Fix ***bold italic*** / ___bold italic___ triple emphasis - Fix link text inline formatting (recursive renderInline on [**bold**](url)) - Fix backtick inline code nesting (CommonMark-compliant extractInlineCodes) - Fix tab indentation stripping in indented code blocks Medium-term improvements: - parseTokens() / renderTokens() separation API for token-level transform - registerBlockHandler() table-driven block handler registry - Backslash escape support (\* \_ \) Also: - Add 48 new test cases (583 total, 7 suites, all passing) - Parser coverage: 95.43% stmts / 91.38% branches / 100% funcs / 98.25% lines - Update README.md, site/, package.json to v0.1.15
This commit is contained in:
+45
-4
@@ -176,7 +176,7 @@
|
||||
|
||||
<header class="docs-header">
|
||||
<h1><span class="grad">文档</span></h1>
|
||||
<p class="sub">MetonaEditor v0.1.14 完整 API、配置与使用指南</p>
|
||||
<p class="sub">MetonaEditor v0.1.15 完整 API、配置与使用指南</p>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
@@ -201,6 +201,7 @@
|
||||
<a href="#static-api">顶层函数</a>
|
||||
<div class="toc-group">语法参考</div>
|
||||
<a href="#syntax">解析器语法</a>
|
||||
<a href="#parser-api">解析器 API(v0.1.15)</a>
|
||||
<div class="toc-group">插件</div>
|
||||
<a href="#plugins">插件约定</a>
|
||||
<a href="#preset-plugins">预设插件</a>
|
||||
@@ -475,6 +476,7 @@ MeEditor<span class="c-punc">.</span><span class="c-fn">destroy</span><span clas
|
||||
<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>
|
||||
@@ -488,16 +490,55 @@ MeEditor<span class="c-punc">.</span><span class="c-fn">destroy</span><span clas
|
||||
<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>链接 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>😊 🚀(80+ 常用)</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>
|
||||
</table>
|
||||
|
||||
<h3>XSS 防护</h3>
|
||||
<p>所有文本经 HTML 转义。URL 自动过滤 <code>javascript:</code> <code>vbscript:</code> <code>file:</code> 及非图片 <code>data:</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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
@@ -619,7 +660,7 @@ i18nUtils<span class="c-punc">.</span><span class="c-fn">formatDate</span><span
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
MetonaEditor v0.1.14 · <a href="https://git.metona.cn/MetonaTeam/MetonaEditor" target="_blank" rel="noopener">源码仓库</a> · MIT License
|
||||
MetonaEditor v0.1.15 · <a href="https://git.metona.cn/MetonaTeam/MetonaEditor" target="_blank" rel="noopener">源码仓库</a> · MIT License
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user