release: v0.1.1 — bug fixes, CSS scoping, parser improvements
Bug Fixes: - fix(core): insert() replace param was non-functional due to identical ternary branches - fix(types): correct project URL typo (MetonaToast → MetonaEditor) Improvements: - feat(core): scope CSS theme variables to .me-wrapper per-instance, preventing global style pollution - feat(themes): add optional target parameter to setThemeVariables() for element-scoped theming - perf(parser): improve bold/strikethrough regex to support inline delimiter chars (e.g. **a*b**, ~~a~b~~) - fix(parser): prevent *** cross-tag nesting by requiring first content char ≠ delimiter - docs(animations): clarify module purpose as future-use animation metadata registry Tests: - test(core): add 2 cases for insert() replace:true / replace:false behavior - All 409 tests passing (+2 new) Chores: - bump version 0.1.0 → 0.1.1 across all source files, package.json, README, and demo
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
> 轻量、零依赖、精致美观的 Markdown Editor 库。单文件,开箱即用,中文优先。
|
||||
|
||||
[](https://www.npmjs.com/package/@metona-team/metona-editor)
|
||||
[](https://www.npmjs.com/package/@metona-team/metona-editor)
|
||||
[](./LICENSE)
|
||||
[](./tests)
|
||||
[](./tests)
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@metona-team/metona-editor",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@metona-team/metona-editor",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@metona-team/metona-editor",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"description": "轻量、零依赖、精致美观的 Markdown Editor 库。单文件,开箱即用。",
|
||||
"type": "module",
|
||||
"main": "dist/metona-editor.js",
|
||||
|
||||
+1
-1
@@ -305,7 +305,7 @@
|
||||
'',
|
||||
'| 名称 | 值 |',
|
||||
'| --- | --- |',
|
||||
'| 版本 | 0.1.0 |',
|
||||
'| 版本 | 0.1.1 |',
|
||||
'| 依赖 | 零 |',
|
||||
'| 测试 | 390+ |',
|
||||
'',
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* MetonaEditor Animations - 动画管理
|
||||
* @module animations
|
||||
* @version 0.1.0
|
||||
* @description 动画注册与管理
|
||||
* @version 0.1.1
|
||||
* @description 动画注册与管理(当前为 CSS 动画元数据管理,供未来扩展如 Toast/通知组件的进出场动画使用;
|
||||
* 内置 7 种预设动画曲线配置;编辑器核心当前未直接调用此模块)
|
||||
*/
|
||||
|
||||
import { ANIMATIONS } from './constants.js';
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Constants - 常量定义
|
||||
* @module constants
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 默认配置、主题、动画、工具栏等常量
|
||||
*/
|
||||
|
||||
|
||||
+9
-4
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Core - 编辑器核心
|
||||
* @module core
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description MarkdownEditor 类实现:DOM 构建、事件、渲染、历史栈、选区操作、模式切换
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,7 @@ import { injectStyles } from './styles.js';
|
||||
import { t as i18nT, getCurrentLocale, getLocaleDirection } from './i18n.js';
|
||||
import { parseMarkdown } from './parser.js';
|
||||
import { presetPlugins } from './plugins.js';
|
||||
import { getTheme, applyTheme, saveTheme } from './themes.js';
|
||||
import { getTheme, applyTheme, saveTheme, getThemeConfig, setThemeVariables } from './themes.js';
|
||||
|
||||
const MODES = ['edit', 'split', 'preview'];
|
||||
|
||||
@@ -104,6 +104,10 @@ class MarkdownEditor {
|
||||
saveTheme(this.config.theme);
|
||||
}
|
||||
|
||||
// 将 CSS 变量限定到当前实例的 wrapper 元素,避免污染全局样式
|
||||
const resolvedThemeConfig = getThemeConfig(this.config.theme);
|
||||
setThemeVariables(resolvedThemeConfig, this.el);
|
||||
|
||||
this._buildToolbar();
|
||||
this._bindEvents();
|
||||
|
||||
@@ -773,8 +777,9 @@ class MarkdownEditor {
|
||||
const ta = this.textarea;
|
||||
const start = ta.selectionStart;
|
||||
const end = ta.selectionEnd;
|
||||
const replace = opts.replace || false;
|
||||
ta.value = ta.value.slice(0, replace ? start : start) + text + ta.value.slice(replace ? end : end);
|
||||
const replace = opts.replace === true;
|
||||
// replace=true: 替换选区内容;replace=false: 在光标处插入,保留选区
|
||||
ta.value = ta.value.slice(0, start) + text + ta.value.slice(replace ? end : start);
|
||||
ta.focus();
|
||||
const pos = start + text.length;
|
||||
ta.selectionStart = ta.selectionEnd = pos;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor i18n - 国际化管理
|
||||
* @module i18n
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 多语言支持、语言切换和翻译管理
|
||||
*/
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Icons — 工具栏图标SVG定义
|
||||
* @module icons
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 工具栏格式化按钮 SVG 图标
|
||||
*/
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor - 轻量级 Markdown Editor 库
|
||||
* @module metona-editor
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @author thzxx
|
||||
* @description 现代化、零依赖、易扩展、易维护、易使用的 Markdown 编辑器库。单文件,开箱即用。
|
||||
* @license MIT
|
||||
@@ -29,7 +29,7 @@ import { animationUtils } from './animations.js';
|
||||
import { DEFAULTS, ICONS, THEMES, EDIT_MODES, DEFAULT_TOOLBAR, TOOLBAR_ACTIONS } from './constants.js';
|
||||
|
||||
// 版本信息
|
||||
const VERSION = '0.1.0';
|
||||
const VERSION = '0.1.1';
|
||||
|
||||
/**
|
||||
* 全局默认插件队列
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Locales — 国际化翻译数据
|
||||
* @module locales
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 内置 zh-CN / en-US 完整翻译
|
||||
*/
|
||||
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Parser - 轻量 Markdown 解析器
|
||||
* @module parser
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 自研零依赖 Markdown 解析器,覆盖 CommonMark 子集 + GFM 扩展
|
||||
*
|
||||
* 支持语法:
|
||||
@@ -286,16 +286,16 @@ const renderInline = (text, env) => {
|
||||
return `<a href="${u}" target="_blank" rel="noopener noreferrer">${url}</a>`;
|
||||
});
|
||||
|
||||
// 6. 粗体 **text** / __text__
|
||||
s = s.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
||||
s = s.replace(/__([^_]+)__/g, '<strong>$1</strong>');
|
||||
// 6. 粗体 **text** / __text__(内容首字符不能是分隔符,避免 *** 歧义)
|
||||
s = s.replace(/\*\*([^*].*?)\*\*/g, '<strong>$1</strong>');
|
||||
s = s.replace(/__([^_].*?)__/g, '<strong>$1</strong>');
|
||||
|
||||
// 7. 斜体 *text* / _text_
|
||||
// 7. 斜体 *text* / _text_(贪婪匹配,避免匹配 ** 或 __ 前缀)
|
||||
s = s.replace(/(^|[^*])\*([^*\n]+)\*/g, '$1<em>$2</em>');
|
||||
s = s.replace(/(^|[^_])_([^_\n]+)_/g, '$1<em>$2</em>');
|
||||
|
||||
// 8. 删除线 ~~text~~
|
||||
s = s.replace(/~~([^~]+)~~/g, '<del>$1</del>');
|
||||
// 8. 删除线 ~~text~~(非贪婪匹配,支持内含单个 ~ 字符)
|
||||
s = s.replace(/~~(.+?)~~/g, '<del>$1</del>');
|
||||
|
||||
// 9. 还原行内代码
|
||||
s = s.replace(/\u0000(\d+)\u0000/g, (m, idx) => `<code>${escapeHTML(codes[+idx])}</code>`);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Plugins - 插件系统
|
||||
* @module plugins
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 插件管理器 + 预设插件(autoSave / exportTool / searchReplace)
|
||||
*
|
||||
* 插件约定:
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Styles - 编辑器样式
|
||||
* @module styles
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 编辑器 UI 样式注入与管理
|
||||
*/
|
||||
|
||||
|
||||
+5
-3
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Themes - 主题管理
|
||||
* @module themes
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 主题系统、自定义主题和主题切换
|
||||
*/
|
||||
|
||||
@@ -70,11 +70,13 @@ export const applyTheme = (theme) => {
|
||||
|
||||
/**
|
||||
* 设置主题CSS变量
|
||||
* @param {Object} config - 主题配置对象
|
||||
* @param {HTMLElement} [target] - 目标元素,不传则设置到 documentElement(全局默认)
|
||||
*/
|
||||
export const setThemeVariables = (config) => {
|
||||
export const setThemeVariables = (config, target) => {
|
||||
if (typeof document === 'undefined' || !config || typeof config !== 'object') return;
|
||||
|
||||
const root = document.documentElement;
|
||||
const root = target || document.documentElement;
|
||||
// 基础变量(保留用于全局与组件回退)
|
||||
root.style.setProperty('--md-bg', config.bg);
|
||||
root.style.setProperty('--md-text', config.text);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* MetonaEditor Utils - 工具函数
|
||||
* @module utils
|
||||
* @version 0.1.0
|
||||
* @version 0.1.1
|
||||
* @description 通用工具函数集合
|
||||
*/
|
||||
|
||||
|
||||
@@ -132,6 +132,22 @@ describe('MarkdownEditor - 内容 API', () => {
|
||||
expect(ed.getValue()).toBe('aXbc');
|
||||
});
|
||||
|
||||
test('insert replace:true 替换选区', () => {
|
||||
ed.setValue('hello world');
|
||||
ed.textarea.selectionStart = 0;
|
||||
ed.textarea.selectionEnd = 5;
|
||||
ed.insert('hi', { replace: true });
|
||||
expect(ed.getValue()).toBe('hi world');
|
||||
});
|
||||
|
||||
test('insert replace:false 在光标处插入(保留选区后的内容)', () => {
|
||||
ed.setValue('abcdef');
|
||||
ed.textarea.selectionStart = 3;
|
||||
ed.textarea.selectionEnd = 3;
|
||||
ed.insert('X');
|
||||
expect(ed.getValue()).toBe('abcXdef');
|
||||
});
|
||||
|
||||
test('wrap 包裹选区', () => {
|
||||
ed.setValue('hello');
|
||||
ed.textarea.selectionStart = 0;
|
||||
|
||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Type definitions for MetonaEditor
|
||||
// Project: https://git.metona.cn/MetonaTeam/MetonaToast
|
||||
// Project: https://git.metona.cn/MetonaTeam/MetonaEditor
|
||||
// Author: thzxx
|
||||
|
||||
declare const VERSION: string;
|
||||
|
||||
Reference in New Issue
Block a user