release: v0.1.3 — bug fixes, performance, hardening

Bug Fixes:
- fix(core): exec() now supports _customActions registered via addToolbarButton
- fix(core): _emit('focus'/'blur') no longer passes editor argument twice
- fix(core): getHTML() now triggers beforeRender/afterRender hooks
- fix(core): _wrapSelection defaults to 'text' instead of i18n placeholder
- fix(core): addToolbarButton onClick+action no longer double-fires
- fix(core): null-safety on focus/blur/enable/disable after destroy
- fix(parser): empty headings (# ) no longer produce empty <h1> tags
- fix(parser): slugify returns 'heading' fallback for empty/special inputs
- fix(i18n): setCurrentLocale no longer mutates input parameter
- fix(core): autofocus skipped when readOnly is enabled

Performance:
- perf(core): cache last rendered value, skip parsing when content unchanged
- perf(core): add refresh() API to force re-render after theme/locale changes

Hardening:
- feat(core): tabSize dynamically applied to textarea via style.tabSize
- feat(core): getStatus() now includes readOnly field

Tests:
- 7 new test cases: customActions, refresh, focus args, destroy safety,
  getStatus readOnly, autofocus+readOnly, slugify edge cases
- Total: 425 tests passing (+7 from v0.1.2)

Types:
- EditorStatus includes readOnly field
- MarkdownEditor.refresh() added to type definitions
This commit is contained in:
2026-07-23 21:00:09 +08:00
parent 12875921eb
commit 8d2e172289
18 changed files with 146 additions and 40 deletions
+5 -4
View File
@@ -1,7 +1,7 @@
/**
* MetonaEditor Parser - 轻量 Markdown 解析器
* @module parser
* @version 0.1.2
* @version 0.1.3
* @description 自研零依赖 Markdown 解析器,覆盖 CommonMark 子集 + GFM 扩展
*
* 支持语法:
@@ -100,8 +100,8 @@ export const parseMarkdown = (md, env = {}) => {
continue;
}
// ATX 标题
const h = line.match(/^(#{1,6})\s+(.*?)(?:\s+#{1,6})?\s*$/);
// ATX 标题(非空标题文本)
const h = line.match(/^(#{1,6})\s+(.+?)(?:\s+#{1,6})?\s*$/);
if (h) {
tokens.push({ type: 'heading', level: h[1].length, text: h[2] });
i++;
@@ -364,12 +364,13 @@ const renderInline = (text, env) => {
* 生成标题锚点 id(支持中文)
*/
const slugify = (text) => {
return String(text)
const slug = String(text)
.toLowerCase()
.replace(/[^\w\u4e00-\u9fa5\s-]/g, '')
.replace(/\s+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '');
return slug || 'heading';
};
export { safeUrl, slugify };