feat(parser): comprehensive Markdown parser enhancement - Add nested list support (multi-level unordered/ordered, mixed nesting) - Add Setext headings (=== / ---) - Add indented code blocks (4-space indent) - Add HTML comment passthrough (<!-- -->) - Add entity reference protection (& ©) - Add ordered list start attribute - Add link title single-quote support - Add LaTeX math formulas ($inline$ / $$block$$) - Add footnote support ([^1] ref + [^1]: definition) - Add definition lists (term\n: definition) - Extend emoji map from 85 to 150+ common emojis - Fix backtick code block matching (CommonMark spec) - Fix italic regex character truncation (lookbehind assertions) - Fix superscript/subscript/strikethrough ambiguity - Fix blockquote prefix handling (>text without space) - Enhance safeUrl filtering (additional protocol checks) - Enhance slugify (Unicode NFKC normalization) perf(parser): single-pass inline scanning, render cache, pre-compiled regex - Replace 14-step chained regex with unified single-pass scanInline() - Add cachedRenderInline() with FIFO LRU eviction (300-entry cap) - Pre-compile 15+ static regex constants for block boundary detection - Skip redundant style='text-align:left' on default-aligned table cells style(parser): add CSS for footnotes, definition lists, math formulas, sup/sub test(parser): 44 new test cases covering all v0.1.4 syntax additions (469 total) chore: bump version 0.1.3 → 0.1.4 across all source files, docs, site pages
379 lines
11 KiB
TypeScript
379 lines
11 KiB
TypeScript
// Type definitions for MetonaEditor v0.1.4
|
||
// Project: https://git.metona.cn/MetonaTeam/MetonaEditor
|
||
// Author: thzxx
|
||
|
||
declare const VERSION: string;
|
||
|
||
/** 视图模式 */
|
||
export type EditMode = 'edit' | 'split' | 'preview';
|
||
|
||
/** 主题名 */
|
||
export type ThemeName = 'light' | 'dark' | 'auto' | 'warm' | string;
|
||
|
||
/** 渲染环境,传给自定义 render 函数 */
|
||
export interface RenderEnv {
|
||
highlight?: (code: string, lang: string) => string;
|
||
locale?: string;
|
||
[key: string]: unknown;
|
||
}
|
||
|
||
/** 工具栏项:动作名或 '|'(分隔符) */
|
||
export type ToolbarItem = string | '|';
|
||
|
||
/** 编辑器配置 */
|
||
export interface MarkdownEditorOptions {
|
||
/** 初始内容 */
|
||
value?: string;
|
||
/** 占位符 */
|
||
placeholder?: string;
|
||
/** 视图模式,默认 'split' */
|
||
mode?: EditMode;
|
||
/** 高度:数字为 px,字符串原样使用,默认 400 */
|
||
height?: number | string;
|
||
/** 工具栏按钮序列,传 false 隐藏工具栏 */
|
||
toolbar?: ToolbarItem[] | false;
|
||
/** 是否显示字数统计状态栏,默认 true */
|
||
wordCount?: boolean;
|
||
/** 自动聚焦,默认 false */
|
||
autofocus?: boolean;
|
||
/** 拼写检查,默认 false */
|
||
spellcheck?: boolean;
|
||
/** 历史栈上限,默认 100 */
|
||
historyLimit?: number;
|
||
/** 分屏模式下同步滚动,默认 true */
|
||
syncScroll?: boolean;
|
||
/** Tab 插入的空格数,0 表示插入 \t,默认 2 */
|
||
tabSize?: number;
|
||
/** 只读模式,默认 false */
|
||
readOnly?: boolean;
|
||
/** 历史栈防抖延迟(ms),默认 400 */
|
||
historyDebounce?: number;
|
||
/** 主题,默认 'auto' */
|
||
theme?: ThemeName;
|
||
/** 国际化语言,默认 'zh-CN' */
|
||
locale?: string;
|
||
/** 自定义 Markdown 渲染函数,覆盖内置解析器 */
|
||
render?: (markdown: string, env: RenderEnv) => string;
|
||
/** 自定义代码高亮函数 */
|
||
highlight?: (code: string, lang: string) => string;
|
||
/** 自定义 HTML 净化函数(接收渲染后 HTML,返回安全 HTML) */
|
||
sanitize?: (html: string) => string;
|
||
/** 自定义容器 className */
|
||
className?: string;
|
||
/** 容器内联样式对象 */
|
||
style?: { [key: string]: string };
|
||
/** 实例级插件列表 */
|
||
plugins?: Array<string | PluginObject>;
|
||
/** 唯一 id */
|
||
id?: string;
|
||
|
||
// 生命周期回调
|
||
onCreate?: (editor: MarkdownEditor) => void;
|
||
onDestroy?: (editor: MarkdownEditor) => void;
|
||
onInput?: (value: string, editor: MarkdownEditor) => void;
|
||
onChange?: (value: string, editor: MarkdownEditor) => void;
|
||
onFocus?: (editor: MarkdownEditor) => void;
|
||
onBlur?: (editor: MarkdownEditor) => void;
|
||
onSave?: (value: string, editor: MarkdownEditor) => void;
|
||
onModeChange?: (mode: EditMode, editor: MarkdownEditor) => void;
|
||
onFullscreen?: (fullscreen: boolean, editor: MarkdownEditor) => void;
|
||
}
|
||
|
||
/** 插件对象 */
|
||
export interface PluginObject {
|
||
name: string;
|
||
description?: string;
|
||
[key: string]: any;
|
||
install?: (editor: MarkdownEditor) => void;
|
||
destroy?: (editor: MarkdownEditor) => void;
|
||
}
|
||
|
||
/** 工具栏按钮配置(addToolbarButton 用) */
|
||
export interface ToolbarButtonConfig {
|
||
action: string;
|
||
title?: string;
|
||
text?: string;
|
||
icon?: string;
|
||
onClick?: (editor: MarkdownEditor) => void;
|
||
handler?: (...args: any[]) => void;
|
||
}
|
||
|
||
/** 统计信息 */
|
||
export interface EditorStats {
|
||
characters: number;
|
||
words: number;
|
||
chineseChars: number;
|
||
englishWords: number;
|
||
lines: number;
|
||
readingTime: number;
|
||
}
|
||
|
||
/** 编辑器状态 */
|
||
export interface EditorStatus {
|
||
id: string;
|
||
mode: EditMode;
|
||
theme: ThemeName;
|
||
locale: string;
|
||
fullscreen: boolean;
|
||
readOnly: boolean;
|
||
disabled: boolean;
|
||
destroyed: boolean;
|
||
plugins: string[];
|
||
}
|
||
|
||
/** 事件名 */
|
||
export type EditorEventName =
|
||
| 'input' | 'change' | 'focus' | 'blur' | 'save'
|
||
| 'modeChange' | 'fullscreen' | 'autosave' | 'destroy'
|
||
| 'beforeRender' | 'afterRender';
|
||
|
||
/** 全局钩子名 */
|
||
export type HookName =
|
||
| 'beforeCreate' | 'afterCreate'
|
||
| 'beforeRender' | 'afterRender'
|
||
| 'beforeDestroy' | 'afterDestroy';
|
||
|
||
/** MarkdownEditor 编辑器类 */
|
||
export class MarkdownEditor {
|
||
constructor(container: string | HTMLElement, options?: MarkdownEditorOptions);
|
||
|
||
/** 实例 id */
|
||
readonly id: string;
|
||
/** 容器元素 */
|
||
readonly container: HTMLElement;
|
||
/** 配置(只读视图) */
|
||
readonly config: MarkdownEditorOptions;
|
||
/** 根元素 */
|
||
readonly el: HTMLElement;
|
||
readonly toolbarEl: HTMLElement;
|
||
readonly bodyEl: HTMLElement;
|
||
readonly editorPane: HTMLElement;
|
||
readonly previewPane: HTMLElement;
|
||
readonly dividerEl: HTMLElement;
|
||
readonly textarea: HTMLTextAreaElement;
|
||
readonly previewEl: HTMLElement;
|
||
readonly statusEl: HTMLElement | null;
|
||
|
||
// 静态钩子
|
||
static on(name: HookName, fn: (editor: MarkdownEditor) => void): () => void;
|
||
static off(name: HookName, fn: (editor: MarkdownEditor) => void): void;
|
||
static trigger(name: HookName, editor: MarkdownEditor): void;
|
||
|
||
// 内容
|
||
getValue(): string;
|
||
setValue(markdown: string, opts?: { silent?: boolean }): this;
|
||
getHTML(): string;
|
||
/** 强制刷新预览(内容未变时手动触发重渲染) */
|
||
refresh(): this;
|
||
insert(text: string, opts?: { replace?: boolean }): this;
|
||
wrap(before: string, after?: string): this;
|
||
|
||
// 选区/焦点
|
||
focus(): this;
|
||
blur(): this;
|
||
enable(): this;
|
||
disable(): this;
|
||
isDisabled(): boolean;
|
||
setReadOnly(readOnly: boolean): this;
|
||
isReadOnly(): boolean;
|
||
|
||
// 事件
|
||
on(name: EditorEventName, fn: (...args: any[]) => void): () => void;
|
||
off(name: EditorEventName, fn: (...args: any[]) => void): this;
|
||
|
||
// 命令
|
||
exec(action: string, ...args: any[]): this;
|
||
|
||
// 历史栈
|
||
undo(): this;
|
||
redo(): this;
|
||
canUndo(): boolean;
|
||
canRedo(): boolean;
|
||
|
||
// 模式与全屏
|
||
setMode(mode: EditMode): this;
|
||
getMode(): EditMode;
|
||
toggleFullscreen(): this;
|
||
isFullscreen(): boolean;
|
||
exitFullscreen(): this;
|
||
|
||
// 统计与状态
|
||
getStats(): EditorStats;
|
||
getStatus(): EditorStatus;
|
||
|
||
// 插件
|
||
use(plugin: string | PluginObject, options?: object): this;
|
||
getPlugins(): PluginObject[];
|
||
addToolbarButton(config: ToolbarButtonConfig): this;
|
||
|
||
// 生命周期
|
||
destroy(): void;
|
||
isDestroyed(): boolean;
|
||
}
|
||
|
||
/** MarkdownEditor 别名 */
|
||
export const Editor: typeof MarkdownEditor;
|
||
|
||
/** 工厂函数:创建编辑器实例 */
|
||
export function create(container: string | HTMLElement, options?: MarkdownEditorOptions): MarkdownEditor;
|
||
|
||
/** 注册全局默认插件(作用于所有后续创建的实例) */
|
||
export function use(plugin: string | PluginObject, options?: object): typeof api;
|
||
|
||
/** 注册全局事件钩子 */
|
||
export function on(name: HookName, fn: (editor: MarkdownEditor) => void): () => void;
|
||
/** 注销全局事件钩子 */
|
||
export function off(name: HookName, fn: (editor: MarkdownEditor) => void): typeof api;
|
||
|
||
/** 切换全局主题 */
|
||
export function setTheme(theme: ThemeName, options?: object): typeof api;
|
||
/** 切换全局语言 */
|
||
export function setLocale(locale: string): typeof api;
|
||
/** 销毁所有全局资源 */
|
||
export function destroy(): void;
|
||
/** 获取库运行状态 */
|
||
export function getStatus(): {
|
||
version: string;
|
||
theme: string;
|
||
locale: string;
|
||
globalPlugins: string[];
|
||
presetPlugins: string[];
|
||
};
|
||
|
||
// ============ 解析器 ============
|
||
/** Markdown 解析函数 */
|
||
export function parseMarkdown(markdown: string, env?: RenderEnv): string;
|
||
/** URL 安全过滤(增强版) */
|
||
export function safeUrl(url: string): string;
|
||
/** 生成标题锚点 id(Unicode NFKC 规范化) */
|
||
export function slugify(text: string): string;
|
||
/** 清除渲染缓存(主题切换等场景) */
|
||
export function clearRenderCache(): void;
|
||
|
||
// ============ 插件 ============
|
||
/** 预设插件表 */
|
||
export const presetPlugins: {
|
||
autoSave: PluginObject;
|
||
exportTool: PluginObject;
|
||
searchReplace: PluginObject;
|
||
[key: string]: PluginObject;
|
||
};
|
||
|
||
/** 插件工具 */
|
||
export const pluginUtils: {
|
||
createManager(): PluginManager;
|
||
register(name: string, plugin: PluginObject): PluginManager;
|
||
unregister(name: string): PluginManager;
|
||
get(name: string): PluginObject | null;
|
||
has(name: string): boolean;
|
||
getAll(): PluginObject[];
|
||
getNames(): string[];
|
||
enable(name: string): PluginManager;
|
||
disable(name: string): PluginManager;
|
||
isEnabled(name: string): boolean;
|
||
getPreset(name: string): PluginObject | null;
|
||
getAllPresets(): { [key: string]: PluginObject };
|
||
createPlugin(config: object): PluginObject;
|
||
validatePlugin(plugin: PluginObject): { valid: boolean; errors: string[] };
|
||
};
|
||
|
||
/** 插件管理器 */
|
||
export class PluginManager {
|
||
register(name: string, plugin: PluginObject): this;
|
||
unregister(name: string): this;
|
||
get(name: string): PluginObject | null;
|
||
has(name: string): boolean;
|
||
getAll(): PluginObject[];
|
||
getNames(): string[];
|
||
enable(name: string): this;
|
||
disable(name: string): this;
|
||
isEnabled(name: string): boolean;
|
||
destroy(): void;
|
||
}
|
||
|
||
// ============ 常量 ============
|
||
export const DEFAULTS: Readonly<MarkdownEditorOptions>;
|
||
export const ICONS: { [key: string]: string };
|
||
export const THEMES: { [key: string]: any };
|
||
export const EDIT_MODES: EditMode[];
|
||
export const DEFAULT_TOOLBAR: ToolbarItem[];
|
||
export const TOOLBAR_ACTIONS: string[];
|
||
|
||
// ============ 工具集 ============
|
||
export const themeUtils: {
|
||
initTheme(): void;
|
||
switchTheme(theme: ThemeName): void;
|
||
toggleTheme(): void;
|
||
getCurrentTheme(): string;
|
||
getResolvedTheme(): string;
|
||
applyTheme(theme: ThemeName): void;
|
||
registerTheme(name: string, config: object): void;
|
||
unregisterTheme(name: string): void;
|
||
getAllThemes(): object;
|
||
getThemeNames(): string[];
|
||
hasTheme(name: string): boolean;
|
||
watchSystemTheme(): void;
|
||
unwatchSystemTheme(): void;
|
||
addThemeListener(fn: (theme: string, resolved: string) => void): () => void;
|
||
removeThemeListener(fn: (theme: string, resolved: string) => void): void;
|
||
clearThemeListeners(): void;
|
||
[key: string]: any;
|
||
};
|
||
|
||
export const i18nUtils: {
|
||
initI18n(): void;
|
||
t(key: string, params?: object): string;
|
||
getCurrentLocale(): string;
|
||
setCurrentLocale(locale: string): void;
|
||
loadLocale(locale: string, messages: object): void;
|
||
addLocaleListener(fn: (locale: string) => void): () => void;
|
||
removeLocaleListener(fn: (locale: string) => void): void;
|
||
clearLocaleListeners(): void;
|
||
[key: string]: any;
|
||
};
|
||
|
||
export const animationUtils: {
|
||
cancelAll(): void;
|
||
[key: string]: any;
|
||
};
|
||
|
||
// ============ 默认导出 ============
|
||
export interface MeEditorAPI {
|
||
VERSION: string;
|
||
version: string;
|
||
MarkdownEditor: typeof MarkdownEditor;
|
||
Editor: typeof MarkdownEditor;
|
||
create: typeof create;
|
||
use: typeof use;
|
||
on: typeof on;
|
||
off: typeof off;
|
||
setTheme: typeof setTheme;
|
||
setLocale: typeof setLocale;
|
||
destroy: typeof destroy;
|
||
getStatus: typeof getStatus;
|
||
parseMarkdown: typeof parseMarkdown;
|
||
safeUrl: typeof safeUrl;
|
||
slugify: typeof slugify;
|
||
themes: typeof themeUtils;
|
||
i18n: typeof i18nUtils;
|
||
animations: typeof animationUtils;
|
||
plugins: typeof pluginUtils;
|
||
presetPlugins: typeof presetPlugins;
|
||
DEFAULTS: typeof DEFAULTS;
|
||
ICONS: typeof ICONS;
|
||
THEMES: typeof THEMES;
|
||
EDIT_MODES: typeof EDIT_MODES;
|
||
DEFAULT_TOOLBAR: typeof DEFAULT_TOOLBAR;
|
||
TOOLBAR_ACTIONS: typeof TOOLBAR_ACTIONS;
|
||
}
|
||
|
||
/** 默认导出 API 对象 */
|
||
declare const api: MeEditorAPI;
|
||
export default api;
|
||
|
||
export {
|
||
api,
|
||
api as meEditor,
|
||
api as MeEditor,
|
||
};
|