/** * MetonaEditor — Type-safe, lightweight Markdown Editor * @module metona-editor * @version 0.4.3 */ import { MarkdownEditor } from './core'; import { parseMarkdown, parseTokens, renderTokens, safeUrl, slugify, clearRenderCache, registerBlockHandler } from './parser'; import { themeUtils, exportCSSVars, getCSSVariable, followExternalTheme, adoptFromParent, createInstanceTheme } from './themes'; import { i18nUtils, createInstanceI18n, loadRemote } from './i18n'; import { pluginUtils, presetPlugins, topologicalSort, validateConfig } from './plugins'; import { animationUtils } from './animations'; import { highlight, normalizeLanguage, registerLanguage, getSupportedLanguages } from './highlight'; import { DEFAULTS, ICONS, THEMES, EDIT_MODES, DEFAULT_TOOLBAR, TOOLBAR_ACTIONS } from './constants'; import type { EditMode, ThemeName, ToolbarItem, EditorOptions } from './constants'; const VERSION = '0.4.3'; const globalPlugins: any[] = []; // 全局插件在 afterCreate 安装:此时 DOM 已构建完成,依赖 textarea/el 的插件 // (searchReplace / shortcutHelp / imagePaste)才能正常生效。 const injectGlobalPlugins = (editor: MarkdownEditor): void => { if (!editor || editor.isDestroyed()) return; globalPlugins.forEach((p) => { try { editor.use(p); } catch (e) { console.error('MeEditor global plugin install error:', e); } }); }; MarkdownEditor.on('afterCreate', injectGlobalPlugins); function create(container: string | HTMLElement, options: EditorOptions = {}): MarkdownEditor { return new MarkdownEditor(container, options); } function use(plugin: string | any, options: any = {}): typeof api { let p = plugin; if (typeof plugin === 'string') { p = presetPlugins[plugin]; if (!p) { console.warn(`MeEditor: preset plugin "${plugin}" not found`); return api; } } if (!p || typeof p !== 'object') { console.warn('MeEditor: invalid plugin'); return api; } const merged = (options && typeof options === 'object' && Object.keys(options).length > 0) ? { ...p, ...options } : p; globalPlugins.push(merged); return api; } function on(name: string, fn: (editor: MarkdownEditor) => void): () => void { return MarkdownEditor.on(name, fn); } function off(name: string, fn: (editor: MarkdownEditor) => void): typeof api { MarkdownEditor.off(name, fn); return api; } function setTheme(theme: ThemeName, _options?: any): typeof api { if (themeUtils && typeof themeUtils.switchTheme === 'function') themeUtils.switchTheme(theme); return api; } function setLocale(locale: string): typeof api { if (i18nUtils && typeof i18nUtils.setCurrentLocale === 'function') i18nUtils.setCurrentLocale(locale); return api; } function destroy(): void { if (themeUtils) { try { themeUtils.clearThemeListeners(); } catch (_) {} try { themeUtils.unwatchSystemTheme(); } catch (_) {} } if (i18nUtils) { try { i18nUtils.clearLocaleListeners(); } catch (_) {} } if (animationUtils) { try { animationUtils.cancelAll(); } catch (_) {} } globalPlugins.length = 0; // 清理全局静态钩子(beforeCreate/afterCreate/beforeChange 等),整体复位; // 随后重建内部 afterCreate 插件注入钩子,保证 destroy 后 MeEditor.use() 仍可用。 try { MarkdownEditor._hooks.clear(); } catch (_) {} MarkdownEditor.on('afterCreate', injectGlobalPlugins); } function getStatus() { return { version: VERSION, theme: (themeUtils && typeof themeUtils.getCurrentTheme === 'function') ? themeUtils.getCurrentTheme() : 'auto', locale: (i18nUtils && typeof i18nUtils.getCurrentLocale === 'function') ? i18nUtils.getCurrentLocale() : 'zh-CN', globalPlugins: globalPlugins.map((p) => p.name || 'custom'), presetPlugins: Object.keys(presetPlugins || {}), }; } try { if (typeof themeUtils === 'object' && typeof themeUtils.initTheme === 'function') themeUtils.initTheme(); if (typeof i18nUtils === 'object' && typeof i18nUtils.initI18n === 'function') i18nUtils.initI18n(); } catch (_) {} const api = { VERSION, version: VERSION, MarkdownEditor, Editor: MarkdownEditor, create, use, on, off, setTheme, setLocale, destroy, getStatus, parseMarkdown, parseTokens, renderTokens, safeUrl, slugify, clearRenderCache, registerBlockHandler, highlight, normalizeLanguage, registerLanguage, getSupportedLanguages, themes: themeUtils, i18n: i18nUtils, animations: animationUtils, plugins: pluginUtils, presetPlugins, topologicalSort, validateConfig, createInstanceI18n, loadRemote, exportCSSVars, getCSSVariable, followExternalTheme, adoptFromParent, createInstanceTheme, DEFAULTS, ICONS, THEMES, EDIT_MODES, DEFAULT_TOOLBAR, TOOLBAR_ACTIONS, }; if (typeof window !== 'undefined') { (window as any).MeEditor = api; } export default api; export { api, api as meEditor, api as MeEditor, MarkdownEditor, MarkdownEditor as Editor, create, use, on, off, setTheme, setLocale, destroy, getStatus, parseMarkdown, parseTokens, renderTokens, safeUrl, slugify, clearRenderCache, registerBlockHandler, highlight, normalizeLanguage, registerLanguage, getSupportedLanguages, themeUtils, i18nUtils, pluginUtils, presetPlugins, animationUtils, topologicalSort, validateConfig, createInstanceI18n, loadRemote, exportCSSVars, getCSSVariable, followExternalTheme, adoptFromParent, createInstanceTheme, DEFAULTS, ICONS, THEMES, EDIT_MODES, DEFAULT_TOOLBAR, TOOLBAR_ACTIONS, VERSION, };