fix: stability improvements — initialize _outlineTimer, extract INLINE_RE constant
- core.js: initialize this._outlineTimer = null in constructor (fixes clearTimeout(undefined)) - parser.js: extract INLINE_RE to module-level constant (avoid recompilation on every scanInline call)
This commit is contained in:
@@ -109,6 +109,7 @@ class MarkdownEditor {
|
|||||||
this._shortcuts = []; // v0.1.6: 快捷键注册表
|
this._shortcuts = []; // v0.1.6: 快捷键注册表
|
||||||
this._contextMenuItems = []; // v0.1.6: 右键菜单项
|
this._contextMenuItems = []; // v0.1.6: 右键菜单项
|
||||||
this._customActions = {}; // 自定义工具栏动作
|
this._customActions = {}; // 自定义工具栏动作
|
||||||
|
this._outlineTimer = null; // 大纲防抖计时器
|
||||||
|
|
||||||
// 渲染函数:自定义覆盖内置解析器
|
// 渲染函数:自定义覆盖内置解析器
|
||||||
this._renderFn = (typeof this.config.render === 'function') ? this.config.render : parseMarkdown;
|
this._renderFn = (typeof this.config.render === 'function') ? this.config.render : parseMarkdown;
|
||||||
|
|||||||
+21
-33
@@ -775,43 +775,31 @@ const extractInlineCodes = (text, codes) => {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单遍内联扫描正则(模块级常量,避免每次调用重新编译)
|
||||||
|
*/
|
||||||
|
const INLINE_RE = new RegExp([
|
||||||
|
'(!\\[[^\\]]*\\]\\([^)]+\\))',
|
||||||
|
'|(?<!!)(\\[[^\\]]+\\]\\([^)]+\\))',
|
||||||
|
'|(!\\[[^\\]]*\\]\\[[^\\]]*\\])',
|
||||||
|
'|(?<!!)(\\[[^\\]]+\\]\\[[^\\]]*\\])',
|
||||||
|
'|(<https?:\\/\\/[^\\s&]+>)',
|
||||||
|
'|(\\*\\*[^*\\n][^*\\n]*?\\*\\*)',
|
||||||
|
'|(__[^_\\n][^_\\n]*?__)',
|
||||||
|
'|(~~[^\\n]+?~~)',
|
||||||
|
'|(==[^\\n]+?==)',
|
||||||
|
'|((?<=^|[^*])\\*(?!\\*)([^*\\n]+?)\\*(?!\\*))',
|
||||||
|
'|((?<=^|[^_])_(?!_)([^_\\n]+?)_(?!_))',
|
||||||
|
'|(\\^[^\\s^][^\\s^]*?\\^)',
|
||||||
|
'|(~[^\\s~][^\\s~]*?~)',
|
||||||
|
'|(?<!\\$)(\\$(?!\\$)[^\\n]+?\\$(?!\\$))',
|
||||||
|
'|(\\[\\^[^\\]]+\\])',
|
||||||
|
].join(''), 'g');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单遍内联扫描(将所有内联语法合并到一个正则处理)
|
* 单遍内联扫描(将所有内联语法合并到一个正则处理)
|
||||||
*/
|
*/
|
||||||
const scanInline = (s, codes, env) => {
|
const scanInline = (s, codes, env) => {
|
||||||
// 组合正则:按优先级从左到右
|
|
||||||
const INLINE_RE = new RegExp([
|
|
||||||
// 图片 
|
|
||||||
'(!\\[[^\\]]*\\]\\([^)]+\\))',
|
|
||||||
// 链接 [...](...) - 需要忽略图片前缀
|
|
||||||
'|(?<!!)(\\[[^\\]]+\\]\\([^)]+\\))',
|
|
||||||
// 图片引用 ![...][...]
|
|
||||||
'|(!\\[[^\\]]*\\]\\[[^\\]]*\\])',
|
|
||||||
// 链接引用 [...][...] 或快捷引用 [...][]
|
|
||||||
'|(?<!!)(\\[[^\\]]+\\]\\[[^\\]]*\\])',
|
|
||||||
// 自动链接已经转义的 <url>
|
|
||||||
'|(<https?:\\/\\/[^\\s&]+>)',
|
|
||||||
// 粗体 **...**(内容不跨换行)
|
|
||||||
'|(\\*\\*[^*\\n][^*\\n]*?\\*\\*)',
|
|
||||||
// 粗体 __...__
|
|
||||||
'|(__[^_\\n][^_\\n]*?__)',
|
|
||||||
// 删除线 ~~...~~(放在斜体之前防歧义)
|
|
||||||
'|(~~[^\\n]+?~~)',
|
|
||||||
// 高亮 ==...==
|
|
||||||
'|(==[^\\n]+?==)',
|
|
||||||
// 斜体 *...*(非贪婪,需避开 **)
|
|
||||||
'|((?<=^|[^*])\\*(?!\\*)([^*\\n]+?)\\*(?!\\*))',
|
|
||||||
// 斜体 _..._(非贪婪,需避开 __)
|
|
||||||
'|((?<=^|[^_])_(?!_)([^_\\n]+?)_(?!_))',
|
|
||||||
// 上标 ^...^(非空白,不跨行)
|
|
||||||
'|(\\^[^\\s^][^\\s^]*?\\^)',
|
|
||||||
// 下标 ~...~(非空白,不跨行,排除 ~~ 删除线)
|
|
||||||
'|(~[^\\s~][^\\s~]*?~)',
|
|
||||||
// 行内公式 $...$(非 $$)
|
|
||||||
'|(?<!\\$)(\\$(?!\\$)[^\\n]+?\\$(?!\\$))',
|
|
||||||
// 脚注引用 [^...]
|
|
||||||
'|(\\[\\^[^\\]]+\\])',
|
|
||||||
].join(''), 'g');
|
|
||||||
|
|
||||||
// 先保护代码占位符 \u0000N\u0000,避免被正则破坏
|
// 先保护代码占位符 \u0000N\u0000,避免被正则破坏
|
||||||
const placeholderMap = new Map();
|
const placeholderMap = new Map();
|
||||||
|
|||||||
Reference in New Issue
Block a user