feat: v0.4.0 — 安全修复×6 + 增量性能×3 + Playwright E2E + 实例级 i18n
CI / test-parser (push) Successful in 9m27s
CI / test-core (push) Successful in 9m34s
CI / test-rest (push) Successful in 9m27s
CI / e2e (push) Failing after 5m15s
CI / verify (20.x) (push) Successful in 9m54s
CI / verify (18.x) (push) Successful in 9m56s
CI / verify (24.x) (push) Successful in 9m48s
CI / test-parser (push) Successful in 9m27s
CI / test-core (push) Successful in 9m34s
CI / test-rest (push) Successful in 9m27s
CI / e2e (push) Failing after 5m15s
CI / verify (20.x) (push) Successful in 9m54s
CI / verify (18.x) (push) Successful in 9m56s
CI / verify (24.x) (push) Successful in 9m48s
0.3.0 修复版: - 脚注 id 属性注入 XSS 防护(行内引用 + 脚注区) - 全局插件注入移至 afterCreate(searchReplace 等依赖 textarea 的插件真正生效)+ use() 同名防重 - 行内渲染缓存附加 refs 指纹,防跨文档引用链接串数据 - 白名单裸标签 <u>/</u> 透传,underline(Ctrl+U)预览可见 - getStatus()/渲染 env 使用实例 locale;replaceAll 替换文本按字面处理 - replaceAllRegex 保留 $1 捕获组语义 0.3.1 性能版: - 高亮规则按语言缓存(registerLanguage 覆盖失效),bench +33% - 统计增量计算:字数/词数/行数差异区间,击键零全量扫描 - outline 树构建 O(n²) → 迭代栈 O(n) - 拖放图片 >500KB 拦截、scrollToLine 真实行高、undo/redo 光标恢复 - selectionChange/cursorMove 与浮动工具栏解耦、unregisterShortcut 大小写归一 - toast 接入 7 种 ANIMATIONS、实例主题订阅随 destroy 断开(dispose) 0.4.0 工程版: - Playwright 真实浏览器冒烟测试(e2e/,22 项断言)+ CI e2e job - sideEffects: false 便于 tree-shaking - MeEditor.destroy() 全面复位(全局钩子清理 + 内部注入钩子重建) - 实例 locale 统一作用于全部 UI 文案(状态栏/工具栏/右键菜单/大纲) 测试 782 → 826,全绿;typecheck/lint/build 通过
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
|
||||
> TypeScript 重构 · 零运行时依赖 · 轻量级桌面端 Markdown Editor 库
|
||||
|
||||
[](https://git.metona.cn/MetonaTeam/-/packages/npm/@metona-team%2Fmetona-editor)
|
||||
[](https://git.metona.cn/MetonaTeam/-/packages/npm/@metona-team%2Fmetona-editor)
|
||||
[](./LICENSE)
|
||||
[](./tests)
|
||||
[](./tests)
|
||||
[](./tests)
|
||||
[](./tsconfig.json)
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
- **主题系统** — light / dark / warm / auto,CSS 变量可定制,实例级隔离,主题继承,外部跟随
|
||||
- **国际化** — zh-CN / en-US / ja / ko / fr / de 六种语言完整翻译,实例级语言隔离,远程加载翻译包
|
||||
- **编辑体验** — 行号装订线、智能 Enter、括号自动闭合、拖放文件、大纲面板、Zen 专注模式、右键上下文菜单
|
||||
- **内置语法高亮** — 零依赖轻量高亮器,js/ts/python/bash/css/html 等 13 种语言,`MeEditor.highlight` 即插即用
|
||||
- **安全** — HTML 转义,XSS 协议过滤(javascript / vbscript / file / data),属性级注入防护,sanitize 钩子
|
||||
- **内置语法高亮** — 零依赖轻量高亮器,js/ts/python/bash/css/html 等 16 个语言标识,规则缓存零重建开销,`MeEditor.highlight` 即插即用
|
||||
- **性能** — 字数 / 词数 / 行数差异增量统计,击键零全量扫描;大纲 O(n) 线性构建,长文档即时响应
|
||||
- **安全** — HTML 转义,XSS 协议过滤(javascript / vbscript / file / data),属性级注入防护(含脚注 id),白名单裸标签透传,sanitize 钩子
|
||||
- **工程化** — 826 个单元测试 + Playwright 真实浏览器冒烟测试,CI 并行 4 job,`sideEffects: false` 便于 tree-shaking
|
||||
- **桌面端优先** — 纯电脑端设计,无移动端冗余代码
|
||||
- **引用链接** — 支持 `[text][ref]` / `![alt][ref]` 引用式链接和图片,含 title 属性
|
||||
- **RTL 支持** — 完整的从右到左布局适配(阿拉伯语、希伯来语等)
|
||||
@@ -77,10 +79,10 @@ const editor = MeEditor.create('#editor', { mode: 'split' });
|
||||
|
||||
```html
|
||||
<!-- jsDelivr CDN (推荐) -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@metona-team/metona-editor@0.2.5/dist/metona-editor.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@metona-team/metona-editor@0.4.0/dist/metona-editor.min.js"></script>
|
||||
|
||||
<!-- unpkg CDN -->
|
||||
<script src="https://unpkg.com/@metona-team/metona-editor@0.2.5/dist/metona-editor.min.js"></script>
|
||||
<script src="https://unpkg.com/@metona-team/metona-editor@0.4.0/dist/metona-editor.min.js"></script>
|
||||
|
||||
<!-- Gitea 源 -->
|
||||
<script src="https://git.metona.cn/MetonaTeam/MetonaEditor/raw/branch/master/dist/metona-editor.js"></script>
|
||||
@@ -122,6 +124,7 @@ MeEditor.create(container, {
|
||||
// 内容
|
||||
value: '', // 初始 Markdown 文本
|
||||
placeholder: '', // 占位符
|
||||
id: '', // 实例 id(默认自动生成,用于分隔条/草稿等存储键隔离)
|
||||
|
||||
// 视图
|
||||
mode: 'split', // 'edit' | 'split' | 'preview'
|
||||
@@ -256,6 +259,7 @@ editor.exec(action: string): this
|
||||
// h1 h2 h3 quote ul ol hr
|
||||
// link image table
|
||||
// indent outdent undo redo
|
||||
// formatTable(光标所在表格按列宽对齐)
|
||||
// edit split preview fullscreen
|
||||
// zen wordwrap
|
||||
```
|
||||
@@ -352,8 +356,8 @@ editor.isWordWrap(): boolean
|
||||
```typescript
|
||||
editor.toast(message: string, opts?: {
|
||||
type?: 'success' | 'error' | 'warning' | 'info';
|
||||
duration?: number;
|
||||
animation?: 'fade' | 'slide' | 'scale';
|
||||
duration?: number; // ms,0 = 不自动消失
|
||||
animation?: 'fade' | 'slide' | 'scale' | 'bounce' | 'flip' | 'rotate' | 'zoom';
|
||||
}): this
|
||||
```
|
||||
|
||||
@@ -397,7 +401,7 @@ MeEditor.setLocale('en-US')
|
||||
MeEditor.getStatus()
|
||||
// => { version, theme, locale, globalPlugins, presetPlugins }
|
||||
|
||||
// 销毁全局资源
|
||||
// 销毁全局资源(主题/语言监听、全局插件、全局钩子全面复位)
|
||||
MeEditor.destroy()
|
||||
|
||||
// 解析器独立使用
|
||||
@@ -465,6 +469,7 @@ import { highlight, registerLanguage, getSupportedLanguages } from '@metona-team
|
||||
| 粗斜体 | `***text***` `___text___` | `<em><strong>` |
|
||||
| 斜体 | `*italic*` `_italic_` | `<em>` |
|
||||
| 删除线 | `~~text~~` | `<del>` |
|
||||
| 下划线 | `<u>text</u>`(裸标签透传) | `<u>` |
|
||||
| 高亮 | `==text==` | `<mark>` |
|
||||
| 上标 | `x^2^` | `<sup>` |
|
||||
| 下标 | `H~2~O` | `<sub>` |
|
||||
@@ -482,6 +487,7 @@ import { highlight, registerLanguage, getSupportedLanguages } from '@metona-team
|
||||
| 图片 | `` | `<img>` |
|
||||
| 引用链接 | `[text][ref]` + `[ref]: url` | `<a>` |
|
||||
| 引用图片 | `![alt][ref]` + `[ref]: url` | `<img>` |
|
||||
| 表格格式化 | `exec('formatTable')` | 光标所在表格按列宽对齐 |
|
||||
| 自动链接 | `<https://...>` | `<a>` |
|
||||
| 数学公式 | `$E=mc^2$` `$$\int$$` | `<span>` / `<div>` |
|
||||
| 脚注 | `text[^1]` | `<sup>` + 底部定义 |
|
||||
@@ -532,7 +538,8 @@ registerBlockHandler({
|
||||
|
||||
- 所有文本经 `escapeHTML` 转义
|
||||
- 链接 URL 过滤 `javascript:` / `vbscript:` / `file:` / 非图片 `data:`
|
||||
- 属性级注入防护:`href` / `src` / `alt` / `title` / `language-*` 引号与换行均被转义
|
||||
- 属性级注入防护:`href` / `src` / `alt` / `title` / 脚注 id / `language-*` 引号与换行均被转义
|
||||
- 白名单裸标签透传:仅 `<u>` / `</u>`(无属性),带属性的标签仍被转义
|
||||
- `data:image` 限制最大 500KB
|
||||
- `sanitize` 钩子供外部净化(如 DOMPurify)
|
||||
- `highlight` 钩子异常自动回退为纯文本
|
||||
@@ -666,6 +673,9 @@ editor.getThemeContext().adopt();
|
||||
|
||||
// 跟随外部元素
|
||||
editor.getThemeContext().syncWithElement(document.body);
|
||||
|
||||
// 手动断开所有外部跟随订阅(实例 destroy 时也会自动断开)
|
||||
editor.getThemeContext().dispose();
|
||||
```
|
||||
|
||||
---
|
||||
@@ -749,6 +759,9 @@ npm test
|
||||
# 测试覆盖率
|
||||
npm run test -- --coverage
|
||||
|
||||
# 浏览器冒烟测试(Playwright + Chromium,需先构建)
|
||||
npm run build && npm run test:e2e
|
||||
|
||||
# 性能基准(先构建再运行)
|
||||
npm run build && npm run bench
|
||||
|
||||
@@ -760,11 +773,11 @@ npm run format
|
||||
|
||||
```
|
||||
dist/
|
||||
├── metona-editor.js UMD(浏览器直接引入)
|
||||
├── metona-editor.min.js UMD 压缩版(CDN)
|
||||
├── metona-editor.mjs ES Module
|
||||
├── metona-editor.cjs CommonJS
|
||||
└── metona-editor.d.ts TypeScript 类型声明
|
||||
├── metona-editor.js UMD(浏览器直接引入)
|
||||
├── metona-editor.min.js UMD 压缩版(CDN)
|
||||
├── metona-editor.mjs ES Module
|
||||
├── metona-editor.cjs CommonJS
|
||||
└── metona-editor.d.ts TypeScript 类型声明
|
||||
```
|
||||
|
||||
### 源码结构
|
||||
@@ -796,7 +809,8 @@ src/
|
||||
|------|------|
|
||||
| 语言 | TypeScript 5 (strict) |
|
||||
| 构建 | Rollup 3 |
|
||||
| 测试 | Jest 29 + jsdom |
|
||||
| 测试 | Jest 29 + jsdom(826 用例) |
|
||||
| 浏览器冒烟 | Playwright + Chromium(22 项断言) |
|
||||
| 类型生成 | rollup-plugin-dts |
|
||||
| 零运行时依赖 | ✅ |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user