@oix1987/yjd 1.0.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +223 -142
  3. package/core.js +82 -0
  4. package/dist/core.esm.js +2 -0
  5. package/dist/core.esm.js.map +1 -0
  6. package/dist/rich-editor.esm.js +1 -1
  7. package/dist/rich-editor.esm.js.map +1 -1
  8. package/dist/rich-editor.min.js +1 -1
  9. package/dist/rich-editor.min.js.map +1 -1
  10. package/index.d.ts +230 -103
  11. package/index.js +297 -0
  12. package/lib/core/editor.js +1885 -0
  13. package/lib/core/format.js +540 -0
  14. package/lib/core/module.js +81 -0
  15. package/lib/core/registry.js +158 -0
  16. package/lib/formats/background.js +213 -0
  17. package/lib/formats/bold.js +49 -0
  18. package/lib/formats/capitalization.js +579 -0
  19. package/lib/formats/color.js +183 -0
  20. package/lib/formats/emoji.js +282 -0
  21. package/lib/formats/font-family.js +548 -0
  22. package/lib/formats/heading.js +502 -0
  23. package/lib/formats/image.js +341 -0
  24. package/lib/formats/import.js +385 -0
  25. package/lib/formats/indent.js +297 -0
  26. package/lib/formats/italic.js +27 -0
  27. package/lib/formats/line-height.js +562 -0
  28. package/lib/formats/link.js +251 -0
  29. package/lib/formats/list.js +635 -0
  30. package/lib/formats/strike.js +31 -0
  31. package/lib/formats/subscript.js +40 -0
  32. package/lib/formats/superscript.js +39 -0
  33. package/lib/formats/table.js +293 -0
  34. package/lib/formats/tag.js +304 -0
  35. package/lib/formats/text-align.js +422 -0
  36. package/lib/formats/text-size.js +498 -0
  37. package/lib/formats/underline.js +30 -0
  38. package/lib/formats/video.js +381 -0
  39. package/lib/modules/block-toolbar.js +639 -0
  40. package/lib/modules/code-view.js +447 -0
  41. package/lib/modules/find-replace.js +273 -0
  42. package/lib/modules/history.js +425 -0
  43. package/lib/modules/mention.js +200 -0
  44. package/lib/modules/resize-handles.js +701 -0
  45. package/lib/modules/slash-menu.js +183 -0
  46. package/lib/modules/table-toolbar.js +635 -0
  47. package/lib/modules/toolbar.js +607 -0
  48. package/lib/serialize.js +241 -0
  49. package/lib/static.js +28 -0
  50. package/lib/styles-loader.js +142 -0
  51. package/{dist → lib}/styles.css +1392 -35
  52. package/lib/styles.css.js +2 -0
  53. package/lib/styles.min.css +1 -0
  54. package/lib/ui/color-picker.js +296 -0
  55. package/lib/ui/customselect.js +351 -0
  56. package/lib/ui/emoji-picker.js +196 -0
  57. package/lib/ui/icons.js +145 -0
  58. package/lib/ui/image-popup.js +435 -0
  59. package/lib/ui/import-popup.js +288 -0
  60. package/lib/ui/link-popup.js +139 -0
  61. package/lib/ui/list-picker.js +307 -0
  62. package/lib/ui/select-button.js +68 -0
  63. package/lib/ui/table-popup.js +171 -0
  64. package/lib/ui/tag-popup.js +249 -0
  65. package/lib/ui/text-align-picker.js +278 -0
  66. package/lib/ui/video-popup.js +413 -0
  67. package/lib/utils/exec-command.js +72 -0
  68. package/lib/utils/history-helper.js +50 -0
  69. package/lib/utils/popup-helper.js +219 -0
  70. package/lib/utils/popup-positioning.js +234 -0
  71. package/lib/utils/sanitize.js +164 -0
  72. package/package.json +51 -32
  73. package/umd-entry.js +19 -0
package/index.d.ts CHANGED
@@ -1,103 +1,230 @@
1
- declare module 'yjdtest' {
2
- // Editor options interface
3
- interface EditorOptions {
4
- placeholder?: string;
5
- theme?: string;
6
- height?: number;
7
- width?: number;
8
- maxWidth?: number;
9
- maxHeight?: number;
10
- content?: string | null;
11
- onChange?: (content: string) => void;
12
- features?: {
13
- emoji?: boolean;
14
- image?: boolean;
15
- table?: boolean;
16
- wordCount?: boolean;
17
- breadcrumb?: boolean;
18
- };
19
- toolbar1?: Array<{
20
- group: string;
21
- items: string[];
22
- }>;
23
- toolbar2?: Array<{
24
- group: string;
25
- items: string[];
26
- }>;
27
- }
28
-
29
- export class Editor {
30
- constructor(selector: string | Element, options?: EditorOptions);
31
- on(event: string, handler: (data: any) => void): void;
32
- off(event: string, handler: (data: any) => void): void;
33
- emit(event: string, data: any): void;
34
- getContent(): string;
35
- setContent(content: string): void;
36
- focus(): void;
37
- }
38
-
39
- export class Module {}
40
- export class Format {}
41
- export class InlineFormat extends Format {}
42
- export class BlockFormat extends Format {}
43
- export const registry: any;
44
-
45
- export class RichEditor extends Editor {
46
- static register(path: string, definition: any, suppressWarning?: boolean): void;
47
- static get(path: string): any;
48
- static create(selector: string | Element, options?: EditorOptions): RichEditor;
49
- }
50
-
51
- export function createEditor(selector: string | Element, options?: EditorOptions): RichEditor;
52
-
53
- // Formats
54
- export const Bold: any;
55
- export const Italic: any;
56
- export const Underline: any;
57
- export const Strike: any;
58
- export const Subscript: any;
59
- export const Superscript: any;
60
- export const Color: any;
61
- export const Background: any;
62
- export const Link: any;
63
- export const Table: any;
64
- export const Heading: any;
65
- export const FontFamily: any;
66
- export const LineHeight: any;
67
- export const Capitalization: any;
68
- export const TextAlign: any;
69
- export const List: any;
70
- export const Indent: any;
71
- export const IndentIncrease: any;
72
- export const IndentDecrease: any;
73
- export const Emoji: any;
74
- export const Image: any;
75
- export const Video: any;
76
- export const Tag: any;
77
- export const TextSize: any;
78
- export const Import: any;
79
-
80
- // Modules
81
- export const Toolbar: any;
82
- export const History: any;
83
- export const BlockToolbar: any;
84
- export const TableToolbar: any;
85
- export const CodeView: any;
86
- export const ResizeHandles: any;
87
-
88
- // UI components
89
- export const ColorPicker: any;
90
- export const IconUtils: any;
91
- export const LinkPopup: any;
92
- export const TablePopup: any;
93
- export const TextAlignPicker: any;
94
- export const ListPicker: any;
95
- export const EmojiPicker: any;
96
- export const ImagePopup: any;
97
- export const VideoPopup: any;
98
- export const TagPopup: any;
99
-
100
- export const createCustomButton: any;
101
-
102
- export default RichEditor;
103
- }
1
+ // Type definitions for @oix1987/yjd
2
+ // These declarations are the package entry types (referenced via "types" in package.json),
3
+ // so they are declared at top level rather than wrapped in `declare module`.
4
+
5
+ /** A person/task suggestion returned by a mention source. */
6
+ export interface MentionItem {
7
+ id: string | number;
8
+ name?: string;
9
+ label?: string;
10
+ avatar_url?: string;
11
+ [key: string]: any;
12
+ }
13
+
14
+ /** Config for a single mention trigger character. */
15
+ export interface MentionTrigger {
16
+ /** Trigger character, e.g. '#'. */
17
+ char: string;
18
+ /** Async (or sync) lookup of suggestions for the typed query. */
19
+ source: (query: string) => MentionItem[] | Promise<MentionItem[]>;
20
+ /** Custom HTML for a suggestion row. Defaults to avatar + name. */
21
+ renderItem?: (item: MentionItem) => string;
22
+ }
23
+
24
+ /** @mention configuration. The token inserted carries `data-id`. */
25
+ export interface MentionOptions {
26
+ /** Primary trigger character (default '@'). */
27
+ trigger?: string;
28
+ source?: (query: string) => MentionItem[] | Promise<MentionItem[]>;
29
+ renderItem?: (item: MentionItem) => string;
30
+ /** Additional triggers, e.g. '#' for task references. */
31
+ triggers?: MentionTrigger[];
32
+ }
33
+
34
+ /** Image upload hook configuration. */
35
+ export interface ImageOptions {
36
+ /**
37
+ * Upload the chosen file and resolve to its URL. While pending, a placeholder
38
+ * is shown; on resolve the src is swapped, on reject the image is removed.
39
+ * Omit to fall back to inline base64 (data URLs).
40
+ */
41
+ upload?: (file: File) => string | Promise<string>;
42
+ /** `accept` attribute for the file picker (default 'image/*'). */
43
+ accept?: string;
44
+ /** Maximum file size in bytes; larger files emit 'image:error'. */
45
+ maxSize?: number;
46
+ }
47
+
48
+ /** A JSON document node produced by getJSON()/domToJson. */
49
+ export interface JsonNode {
50
+ tag?: string;
51
+ text?: string;
52
+ attrs?: Record<string, string>;
53
+ content?: JsonNode[];
54
+ }
55
+
56
+ /** Root JSON document. */
57
+ export interface JsonDoc {
58
+ type: 'doc';
59
+ content: JsonNode[];
60
+ }
61
+
62
+ // Editor options interface
63
+ export interface EditorOptions {
64
+ placeholder?: string;
65
+ theme?: string;
66
+ height?: number;
67
+ width?: number;
68
+ maxWidth?: number;
69
+ maxHeight?: number;
70
+ content?: string | null;
71
+ onChange?: (content: string) => void;
72
+ /** When true, paste always inserts plain text (default: false). */
73
+ pasteAsPlainText?: boolean;
74
+ /** Accessible label for the editable region (defaults to placeholder). */
75
+ ariaLabel?: string;
76
+ /** Maximum number of characters allowed. */
77
+ maxLength?: number;
78
+ /** Initial text direction. */
79
+ direction?: 'ltr' | 'rtl';
80
+ /** Enable markdown shortcuts (default: true). Set false to disable. */
81
+ markdown?: boolean;
82
+ /** Autosave drafts to localStorage. true, or { key, debounce(ms) }. */
83
+ autosave?: boolean | { key?: string; debounce?: number };
84
+ /** Image upload hook (replaces inline base64 when `upload` is provided). */
85
+ image?: ImageOptions | boolean;
86
+ /** @mention / #task autocomplete. Inert until a `source` is given. */
87
+ mention?: MentionOptions;
88
+ features?: {
89
+ emoji?: boolean;
90
+ image?: boolean;
91
+ table?: boolean;
92
+ wordCount?: boolean;
93
+ breadcrumb?: boolean;
94
+ };
95
+ toolbar1?: Array<{
96
+ group: string;
97
+ items: string[];
98
+ }>;
99
+ toolbar2?: Array<{
100
+ group: string;
101
+ items: string[];
102
+ }>;
103
+ }
104
+
105
+ export class Editor {
106
+ constructor(selector: string | Element, options?: EditorOptions);
107
+ on(event: string, handler: (data: any) => void): void;
108
+ off(event: string, handler: (data: any) => void): void;
109
+ emit(event: string, data: any): void;
110
+ getContent(): string;
111
+ setContent(content: string): void;
112
+ /** Alias of getContent() / setContent(). */
113
+ getHTML(): string;
114
+ setHTML(html: string): void;
115
+ /** Export/import the document as a JSON tree. */
116
+ getJSON(): JsonDoc;
117
+ setJSON(json: JsonDoc | JsonNode[]): void;
118
+ /** Export/import the document as Markdown (mention ids preserved). */
119
+ getMarkdown(): string;
120
+ setMarkdown(markdown: string): void;
121
+ getText(): string;
122
+ isEmpty(): boolean;
123
+ clear(): void;
124
+ insertText(text: string): void;
125
+ insertHTML(html: string): void;
126
+ clearFormatting(): void;
127
+ insertHorizontalRule(): void;
128
+ insertImageFile(file: File): void;
129
+ setReadOnly(readOnly: boolean): void;
130
+ isReadOnly(): boolean;
131
+ setDirection(dir: 'ltr' | 'rtl'): void;
132
+ getDirection(): 'ltr' | 'rtl';
133
+ toggleDirection(): void;
134
+ clearAutosave(): void;
135
+ focus(): void;
136
+ destroy(): void;
137
+ }
138
+
139
+ export class Module {}
140
+ export class Format {}
141
+ export class InlineFormat extends Format {}
142
+ export class BlockFormat extends Format {}
143
+ export const registry: any;
144
+
145
+ export class RichEditor extends Editor {
146
+ static register(path: string, definition: any, suppressWarning?: boolean): void;
147
+ static get(path: string): any;
148
+ static create(selector: string | Element, options?: EditorOptions): RichEditor;
149
+ /**
150
+ * Progressive-enhance a <textarea> into an editor, keeping textarea.value
151
+ * in sync (and dispatching native input/change events) on every edit.
152
+ */
153
+ static fromTextarea(
154
+ textarea: HTMLTextAreaElement | string,
155
+ options?: EditorOptions & { format?: 'html' | 'markdown' }
156
+ ): RichEditor;
157
+ /** The original textarea, when created via fromTextarea(). */
158
+ textarea?: HTMLTextAreaElement;
159
+ }
160
+
161
+ /** Brand-aligned alias of {@link RichEditor}. */
162
+ export { RichEditor as yjd };
163
+
164
+ export function createEditor(selector: string | Element, options?: EditorOptions): RichEditor;
165
+
166
+ /**
167
+ * Render stored HTML into a read-only view that matches the editor's styling.
168
+ * Sanitizes the HTML and tags the host element with `.yjd-content`.
169
+ */
170
+ export function renderStatic(html: string, target?: Element): Element;
171
+
172
+ // Serialization helpers (also available on the editor as get/set methods)
173
+ export function htmlToMarkdown(html: string): string;
174
+ export function markdownToHtml(markdown: string): string;
175
+ export function domToJson(html: string): JsonDoc;
176
+ export function jsonToHtml(json: JsonDoc | JsonNode[]): string;
177
+
178
+ // Formats
179
+ export const Bold: any;
180
+ export const Italic: any;
181
+ export const Underline: any;
182
+ export const Strike: any;
183
+ export const Subscript: any;
184
+ export const Superscript: any;
185
+ export const Color: any;
186
+ export const Background: any;
187
+ export const Link: any;
188
+ export const Table: any;
189
+ export const Heading: any;
190
+ export const FontFamily: any;
191
+ export const LineHeight: any;
192
+ export const Capitalization: any;
193
+ export const TextAlign: any;
194
+ export const List: any;
195
+ export const Indent: any;
196
+ export const IndentIncrease: any;
197
+ export const IndentDecrease: any;
198
+ export const Emoji: any;
199
+ export const Image: any;
200
+ export const Video: any;
201
+ export const Tag: any;
202
+ export const TextSize: any;
203
+ export const Import: any;
204
+
205
+ // Modules
206
+ export const Toolbar: any;
207
+ export const History: any;
208
+ export const BlockToolbar: any;
209
+ export const TableToolbar: any;
210
+ export const CodeView: any;
211
+ export const FindReplace: any;
212
+ export const SlashMenu: any;
213
+ export const Mention: any;
214
+ export const ResizeHandles: any;
215
+
216
+ // UI components
217
+ export const ColorPicker: any;
218
+ export const IconUtils: any;
219
+ export const LinkPopup: any;
220
+ export const TablePopup: any;
221
+ export const TextAlignPicker: any;
222
+ export const ListPicker: any;
223
+ export const EmojiPicker: any;
224
+ export const ImagePopup: any;
225
+ export const VideoPopup: any;
226
+ export const TagPopup: any;
227
+
228
+ export const createCustomButton: any;
229
+
230
+ export default RichEditor;
package/index.js ADDED
@@ -0,0 +1,297 @@
1
+ import Editor from './lib/core/editor.js';
2
+ import registry from './lib/core/registry.js';
3
+ import Module from './lib/core/module.js';
4
+ import { Format, InlineFormat, BlockFormat } from './lib/core/format.js';
5
+ import StylesLoader from './lib/styles-loader.js';
6
+ import { renderStatic } from './lib/static.js';
7
+ import { htmlToMarkdown, markdownToHtml, domToJson, jsonToHtml } from './lib/serialize.js';
8
+
9
+ // Import formats
10
+ import Bold from './lib/formats/bold.js';
11
+ import Italic from './lib/formats/italic.js';
12
+ import Underline from './lib/formats/underline.js';
13
+ import Strike from './lib/formats/strike.js';
14
+ import Subscript from './lib/formats/subscript.js';
15
+ import Superscript from './lib/formats/superscript.js';
16
+ import Color from './lib/formats/color.js';
17
+ import Background from './lib/formats/background.js';
18
+ import Link from './lib/formats/link.js';
19
+ import Table from './lib/formats/table.js';
20
+ import Heading from './lib/formats/heading.js';
21
+ import FontFamily from './lib/formats/font-family.js';
22
+ import LineHeight from './lib/formats/line-height.js';
23
+ import Capitalization from './lib/formats/capitalization.js';
24
+ import TextAlign from './lib/formats/text-align.js';
25
+ import List from './lib/formats/list.js';
26
+ import Indent, { IndentIncrease, IndentDecrease } from './lib/formats/indent.js';
27
+ import Emoji from './lib/formats/emoji.js';
28
+ import Image from './lib/formats/image.js';
29
+ import Video from './lib/formats/video.js';
30
+ import Tag from './lib/formats/tag.js';
31
+ import TextSize from './lib/formats/text-size.js';
32
+
33
+ import Import from './lib/formats/import.js';
34
+
35
+ // Import modules
36
+ import Toolbar from './lib/modules/toolbar.js';
37
+ import History from './lib/modules/history.js';
38
+ import BlockToolbar from './lib/modules/block-toolbar.js';
39
+ import TableToolbar from './lib/modules/table-toolbar.js';
40
+ import CodeView from './lib/modules/code-view.js';
41
+ import FindReplace from './lib/modules/find-replace.js';
42
+ import SlashMenu from './lib/modules/slash-menu.js';
43
+ import Mention from './lib/modules/mention.js';
44
+
45
+ import ResizeHandles from './lib/modules/resize-handles.js';
46
+
47
+ // Import UI components
48
+ import ColorPicker from './lib/ui/color-picker.js';
49
+ import IconUtils from './lib/ui/icons.js';
50
+ import LinkPopup from './lib/ui/link-popup.js';
51
+ import TablePopup from './lib/ui/table-popup.js';
52
+ import TextAlignPicker from './lib/ui/text-align-picker.js';
53
+ import ListPicker from './lib/ui/list-picker.js';
54
+ import EmojiPicker from './lib/ui/emoji-picker.js';
55
+ import ImagePopup from './lib/ui/image-popup.js';
56
+ import VideoPopup from './lib/ui/video-popup.js';
57
+ import TagPopup from './lib/ui/tag-popup.js';
58
+
59
+ import createCustomButton from './lib/ui/select-button.js';
60
+
61
+
62
+
63
+ // Register default formats
64
+ registry.register('formats/bold', Bold, true);
65
+ registry.register('formats/italic', Italic, true);
66
+ registry.register('formats/underline', Underline, true);
67
+ registry.register('formats/strike', Strike, true);
68
+ registry.register('formats/subscript', Subscript, true);
69
+ registry.register('formats/superscript', Superscript, true);
70
+ registry.register('formats/color', Color, true);
71
+ registry.register('formats/background', Background, true);
72
+ registry.register('formats/link', Link, true);
73
+ registry.register('formats/table', Table, true);
74
+ registry.register('formats/heading', Heading, true);
75
+ registry.register('formats/font-family', FontFamily, true);
76
+ registry.register('formats/line-height', LineHeight, true);
77
+ registry.register('formats/capitalization', Capitalization, true);
78
+ registry.register('formats/text-align', TextAlign, true);
79
+ registry.register('formats/list', List, true);
80
+ registry.register('formats/indent', Indent, true);
81
+ registry.register('formats/indent-increase', IndentIncrease, true);
82
+ registry.register('formats/indent-decrease', IndentDecrease, true);
83
+ registry.register('formats/emoji', Emoji, true);
84
+ registry.register('formats/image', Image, true);
85
+ registry.register('formats/video', Video, true);
86
+ registry.register('formats/tag', Tag, true);
87
+ registry.register('formats/text-size', TextSize, true);
88
+
89
+ registry.register('formats/import', Import, true);
90
+
91
+ // Register default modules
92
+ registry.register('modules/toolbar', Toolbar, true);
93
+ registry.register('modules/history', History, true);
94
+ registry.register('modules/block-toolbar', BlockToolbar, true);
95
+ registry.register('modules/table-toolbar', TableToolbar, true);
96
+ registry.register('modules/code-view', CodeView, true);
97
+ registry.register('modules/find-replace', FindReplace, true);
98
+ registry.register('modules/slash-menu', SlashMenu, true);
99
+ registry.register('modules/mention', Mention, true);
100
+
101
+ registry.register('modules/resize-handles', ResizeHandles, true);
102
+
103
+ // Register UI components
104
+ registry.register('ui/color-picker', ColorPicker, true);
105
+ registry.register('ui/text-align-picker', TextAlignPicker, true);
106
+ registry.register('ui/list-picker', ListPicker, true);
107
+ registry.register('ui/emoji-picker', EmojiPicker, true);
108
+ registry.register('ui/image-popup', ImagePopup, true);
109
+ registry.register('ui/video-popup', VideoPopup, true);
110
+ registry.register('ui/tag-popup', TagPopup, true);
111
+
112
+ registry.register('ui/custom-button', createCustomButton, true);
113
+
114
+
115
+
116
+ // Load CSS styles
117
+ StylesLoader.loadStyles().catch(error => {
118
+ console.warn('Could not load Rich Editor styles:', error);
119
+ });
120
+
121
+ // Main Editor class with registration system
122
+ class RichEditor extends Editor {
123
+ /**
124
+ * Register a module, format, or theme
125
+ * @param {string|object} path - Registration path
126
+ * @param {*} definition - Class definition
127
+ * @param {boolean} suppressWarning - Suppress overwrite warnings
128
+ */
129
+ static register(path, definition, suppressWarning = false) {
130
+ registry.register(path, definition, suppressWarning);
131
+ }
132
+
133
+ /**
134
+ * Get registered item
135
+ * @param {string} path - Registration path
136
+ */
137
+ static get(path) {
138
+ return registry.get(path);
139
+ }
140
+
141
+ /**
142
+ * Create new editor instance
143
+ * @param {string|Element} selector - DOM selector or element
144
+ * @param {object} options - Editor options
145
+ */
146
+ static create(selector, options = {}) {
147
+ return new RichEditor(selector, options);
148
+ }
149
+
150
+ /**
151
+ * Progressive-enhance a <textarea>: hide it, mount an editor in its place,
152
+ * and keep the textarea's value in sync so existing form submits keep working.
153
+ *
154
+ * const ed = RichEditor.fromTextarea(document.querySelector('#body'), {
155
+ * // any editor option; `format` chooses how the textarea is read/written:
156
+ * format: 'html' | 'markdown', // default 'html'
157
+ * });
158
+ *
159
+ * The textarea's current value seeds the editor (parsed as HTML or Markdown
160
+ * per `format`). On every change the textarea is updated and a native 'input'
161
+ * event is dispatched, so framework bindings / validation keep firing.
162
+ *
163
+ * @param {HTMLTextAreaElement|string} textarea Element or selector.
164
+ * @param {object} [options] Editor options + optional `format`.
165
+ * @returns {RichEditor}
166
+ */
167
+ static fromTextarea(textarea, options = {}) {
168
+ const ta = typeof textarea === 'string' ? document.querySelector(textarea) : textarea;
169
+ if (!ta) throw new Error('RichEditor.fromTextarea: textarea not found');
170
+
171
+ const format = options.format === 'markdown' ? 'markdown' : 'html';
172
+ const readEditor = (ed) => (format === 'markdown' ? ed.getMarkdown() : ed.getContent());
173
+
174
+ // Mount point right after the textarea; hide the original.
175
+ const mount = document.createElement('div');
176
+ ta.after(mount);
177
+ ta.style.display = 'none';
178
+ ta.setAttribute('aria-hidden', 'true');
179
+
180
+ const initial = ta.value || '';
181
+ const editor = new RichEditor(mount, {
182
+ width: '100%',
183
+ ...options,
184
+ // Seed content from the textarea (skip if caller passed explicit content).
185
+ content: options.content != null ? options.content
186
+ : (format === 'markdown' ? markdownToHtml(initial) : initial),
187
+ });
188
+
189
+ const sync = () => {
190
+ const next = readEditor(editor);
191
+ if (ta.value === next) return;
192
+ ta.value = next;
193
+ ta.dispatchEvent(new Event('input', { bubbles: true }));
194
+ ta.dispatchEvent(new Event('change', { bubbles: true }));
195
+ };
196
+ editor.on('change', sync);
197
+ sync(); // normalise the textarea to the editor's serialization up front.
198
+
199
+ editor.textarea = ta;
200
+ return editor;
201
+ }
202
+ }
203
+
204
+ // Export classes for extension. `yjd` is the brand-aligned name; `RichEditor`
205
+ // is kept as an alias for backward compatibility.
206
+ export {
207
+ RichEditor as default,
208
+ RichEditor,
209
+ RichEditor as yjd,
210
+ Editor,
211
+ Module,
212
+ Format,
213
+ InlineFormat,
214
+ BlockFormat,
215
+ registry
216
+ };
217
+
218
+ // Export formats
219
+ export {
220
+ Bold,
221
+ Italic,
222
+ Underline,
223
+ Strike,
224
+ Subscript,
225
+ Superscript,
226
+ Color,
227
+ Background,
228
+ Link,
229
+ Table,
230
+ Heading,
231
+ FontFamily,
232
+ LineHeight,
233
+ Capitalization,
234
+ TextAlign,
235
+ List,
236
+ Indent,
237
+ IndentIncrease,
238
+ IndentDecrease,
239
+ Emoji,
240
+ Image,
241
+ Video,
242
+ Tag,
243
+ TextSize,
244
+
245
+ Import
246
+ };
247
+
248
+ // Export modules
249
+ export {
250
+ Toolbar,
251
+ History,
252
+ BlockToolbar,
253
+ TableToolbar,
254
+ CodeView,
255
+ FindReplace,
256
+ SlashMenu,
257
+ Mention,
258
+
259
+ ResizeHandles
260
+ };
261
+
262
+ // Export UI components
263
+ export {
264
+ ColorPicker,
265
+ IconUtils,
266
+ LinkPopup,
267
+ TablePopup,
268
+ TextAlignPicker,
269
+ ListPicker,
270
+ EmojiPicker,
271
+ ImagePopup,
272
+ VideoPopup,
273
+ TagPopup,
274
+
275
+ createCustomButton
276
+ };
277
+
278
+ // Static rendering + serialization helpers
279
+ export {
280
+ renderStatic,
281
+ htmlToMarkdown,
282
+ markdownToHtml,
283
+ domToJson,
284
+ jsonToHtml
285
+ };
286
+
287
+
288
+
289
+
290
+ /**
291
+ * Utility function to create editor instance
292
+ * @param {string|Element} selector - DOM selector or element
293
+ * @param {object} options - Editor options
294
+ */
295
+ export function createEditor(selector, options = {}) {
296
+ return new RichEditor(selector, options);
297
+ }