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:
@@ -2,9 +2,9 @@
|
||||
|
||||
> 轻量、零依赖、精致美观的 Markdown Editor 库。单文件,开箱即用,中文优先。
|
||||
|
||||
[](https://www.npmjs.com/package/@metona-team/metona-editor)
|
||||
[](https://www.npmjs.com/package/@metona-team/metona-editor)
|
||||
[](./LICENSE)
|
||||
[](./tests)
|
||||
[](./tests)
|
||||
[](./tests)
|
||||
|
||||
---
|
||||
@@ -17,7 +17,7 @@
|
||||
- **易维护** — 模块化源码,JSDoc 注释完整,TypeScript 类型声明,425 个单元测试覆盖
|
||||
- **易使用** — 工厂函数 `create()` 一行接入,链式 API,中文优先文档与翻译
|
||||
- **安全** — 内置 XSS 防护(`javascript:`/`vbscript:`/`file:` 协议过滤),HTML 转义,`safeUrl` 净化
|
||||
- **内置解析器** — 自研 CommonMark 子集 + GFM 扩展(表格含列对齐、任务列表、上下标、数学公式、脚注、嵌套列表、emoji 短码等),可整体替换
|
||||
- **内置解析器** — 自研 CommonMark 子集 + GFM 扩展(表格含列对齐、任务列表、上下标、数学公式、脚注、嵌套列表、emoji 短码、三重强调、反斜杠转义等),可整体替换;v0.1.15 新增 parseTokens/renderTokens 分离 API + registerBlockHandler 块级扩展
|
||||
- **三模式视图** — edit / split / preview 自由切换,分屏拖拽调整比例,滚动同步,模式切换保持滚动位置
|
||||
- **编辑体验** — 语法高亮编辑区、行号装订线 + 当前行高亮、智能 Enter、括号闭合、拖放文件、大纲面板、Zen 专注模式、预览链接拦截
|
||||
- **主题系统** — light / dark / auto / warm 四套预设,CSS 变量定制,实例级主题隔离,外部主题跟随(syncWithElement / adoptFromParent),主题继承(extends),跟随系统主题,@media print 打印样式
|
||||
@@ -684,6 +684,7 @@ MetonaEditor 内置自研轻量解析器,支持 CommonMark 子集 + GFM 扩展
|
||||
| Setext 标题 | `H1\n===` | `<h1>` / `<h2>` |
|
||||
| 段落 | 纯文本 | `<p>` |
|
||||
| 粗体 | `**bold**` `__bold__` | `<strong>` |
|
||||
| 粗斜体 | `***text***` `___text___` | `<em><strong>` ← v0.1.15 |
|
||||
| 斜体 | `*italic*` `_italic_` | `<em>` |
|
||||
| 删除线 | `~~text~~` | `<del>` |
|
||||
| 高亮标记 | `==text==` | `<mark>` |
|
||||
@@ -691,7 +692,7 @@ MetonaEditor 内置自研轻量解析器,支持 CommonMark 子集 + GFM 扩展
|
||||
| 下标 | `H~2~O` | `<sub>` |
|
||||
| 行内代码 | `` `code` `` | `<code>` |
|
||||
| 代码块 | ` ```lang ` | `<pre><code class="language-lang">` |
|
||||
| 缩进代码块 | ` code` | `<pre><code>` |
|
||||
| 缩进代码块 | ` code` / `\tcode` | `<pre><code>` |
|
||||
| 引用 | `> quote` | `<blockquote>` |
|
||||
| 无序列表 | `- item` / `* item` / `+ item` | `<ul><li>` |
|
||||
| 嵌套列表 | `- p\n - sub` | 多级 `<ul>/<ol>` |
|
||||
@@ -706,9 +707,61 @@ MetonaEditor 内置自研轻量解析器,支持 CommonMark 子集 + GFM 扩展
|
||||
| 数学公式 | `$E=mc^2$` `$$\int$$` | `<span>/<div>` |
|
||||
| 脚注 | `text[^1]` | `<sup>` + 底部定义 |
|
||||
| Emoji 短码 | `:smile:` `:rainbow:` | 😊 🌈(150+ 常用) |
|
||||
| 反斜杠转义 | `\* \_ \\` | 取消标点符号特殊含义 ← v0.1.15 |
|
||||
| HTML 注释 | `<!-- note -->` | 透传 |
|
||||
| 实体引用保护 | `&` `©` | 不被二次转义 |
|
||||
|
||||
### 链接内文本格式化(v0.1.15 新增)
|
||||
|
||||
```javascript
|
||||
parseMarkdown('[**粗体链接**](https://example.com)');
|
||||
// => '<a href="..."><strong>粗体链接</strong></a>'
|
||||
// 链接文本内支持粗体、斜体、行内代码等格式
|
||||
```
|
||||
|
||||
### parseTokens / renderTokens 分离 API(v0.1.15 新增)
|
||||
|
||||
```javascript
|
||||
import { parseTokens, renderTokens } from '@metona-team/metona-editor';
|
||||
|
||||
// 第一步:解析为中间 Token 数组
|
||||
const { tokens, footnotes } = parseTokens('# Hello\n\n**world**');
|
||||
// tokens = [
|
||||
// { type: 'heading', level: 1, text: 'Hello' },
|
||||
// { type: 'paragraph', text: '**world**' }
|
||||
// ]
|
||||
|
||||
// 你可以在渲染前变换 token 数组
|
||||
tokens.unshift({ type: 'hr' }); // 在最前面插入分隔线
|
||||
|
||||
// 第二步:从 token 渲染 HTML
|
||||
const html = renderTokens(tokens, env, footnotes);
|
||||
```
|
||||
|
||||
### registerBlockHandler 自定义块级语法(v0.1.15 新增)
|
||||
|
||||
```javascript
|
||||
import { registerBlockHandler } from '@metona-team/metona-editor';
|
||||
|
||||
registerBlockHandler({
|
||||
name: 'customAlert',
|
||||
priority: 8.5, // 数字越小越先尝试,插在表格(8)和列表(9)之间
|
||||
test: (line) => line.match(/^:::(\w+)/), // 检测 :::info / :::warning
|
||||
parse: (lines, i, match) => {
|
||||
// 返回 { token: {...}, newIndex: 下一个待处理行号 }
|
||||
const type = match[1];
|
||||
const content = [];
|
||||
let j = i + 1;
|
||||
while (j < lines.length && !lines[j].startsWith(':::')) {
|
||||
content.push(lines[j]);
|
||||
j++;
|
||||
}
|
||||
if (j < lines.length) j++; // 跳过 :::
|
||||
return { token: { type: 'alert', alertType: type, content: content.join('\n') }, newIndex: j };
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### XSS 防护
|
||||
|
||||
```javascript
|
||||
|
||||
Reference in New Issue
Block a user