@oix1987/yjd 1.0.1 → 1.0.2
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.
- package/README.md +9 -1
- package/dist/rich-editor.esm.js +2 -0
- package/dist/rich-editor.esm.js.map +1 -0
- package/dist/rich-editor.min.js +2 -0
- package/dist/rich-editor.min.js.map +1 -0
- package/package.json +12 -7
- package/index.js +0 -221
- package/lib/core/editor.js +0 -1175
- package/lib/core/format.js +0 -542
- package/lib/core/module.js +0 -81
- package/lib/core/registry.js +0 -152
- package/lib/formats/background.js +0 -212
- package/lib/formats/bold.js +0 -67
- package/lib/formats/capitalization.js +0 -563
- package/lib/formats/color.js +0 -165
- package/lib/formats/emoji.js +0 -282
- package/lib/formats/font-family.js +0 -547
- package/lib/formats/heading.js +0 -502
- package/lib/formats/image.js +0 -344
- package/lib/formats/import.js +0 -385
- package/lib/formats/indent.js +0 -297
- package/lib/formats/italic.js +0 -27
- package/lib/formats/line-height.js +0 -558
- package/lib/formats/link.js +0 -251
- package/lib/formats/list.js +0 -635
- package/lib/formats/strike.js +0 -31
- package/lib/formats/subscript.js +0 -36
- package/lib/formats/superscript.js +0 -35
- package/lib/formats/table.js +0 -288
- package/lib/formats/tag.js +0 -304
- package/lib/formats/text-align.js +0 -421
- package/lib/formats/text-size.js +0 -497
- package/lib/formats/underline.js +0 -30
- package/lib/formats/video.js +0 -372
- package/lib/modules/block-toolbar.js +0 -628
- package/lib/modules/code-view.js +0 -434
- package/lib/modules/history.js +0 -410
- package/lib/modules/resize-handles.js +0 -677
- package/lib/modules/table-toolbar.js +0 -618
- package/lib/modules/toolbar.js +0 -424
- package/lib/styles-loader.js +0 -144
- package/lib/styles.css +0 -2123
- package/lib/ui/color-picker.js +0 -296
- package/lib/ui/customselect.js +0 -319
- package/lib/ui/emoji-picker.js +0 -196
- package/lib/ui/icons.js +0 -413
- package/lib/ui/image-popup.js +0 -444
- package/lib/ui/import-popup.js +0 -288
- package/lib/ui/link-popup.js +0 -191
- package/lib/ui/list-picker.js +0 -307
- package/lib/ui/select-button.js +0 -61
- package/lib/ui/table-popup.js +0 -171
- package/lib/ui/tag-popup.js +0 -249
- package/lib/ui/text-align-picker.js +0 -281
- package/lib/ui/video-popup.js +0 -422
- package/lib/utils/history-helper.js +0 -50
- package/lib/utils/popup-helper.js +0 -219
- package/lib/utils/popup-positioning.js +0 -231
package/lib/core/registry.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Registry system - Inspired by Quill's registration system
|
|
3
|
-
* Manages registration and retrieval of modules, formats, themes, and UI components
|
|
4
|
-
*/
|
|
5
|
-
class Registry {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.modules = new Map();
|
|
8
|
-
this.formats = new Map();
|
|
9
|
-
this.themes = new Map();
|
|
10
|
-
this.ui = new Map();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Register a module, format, theme, or UI component
|
|
15
|
-
* @param {string|object} path - Registration path or object with multiple registrations
|
|
16
|
-
* @param {*} def - Definition to register
|
|
17
|
-
* @param {boolean} suppressWarning - Suppress overwrite warnings
|
|
18
|
-
*/
|
|
19
|
-
register(path, def, suppressWarning = false) {
|
|
20
|
-
if (typeof path === 'object') {
|
|
21
|
-
// Bulk registration
|
|
22
|
-
Object.entries(path).forEach(([key, value]) => {
|
|
23
|
-
this.register(key, value, suppressWarning);
|
|
24
|
-
});
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const [type, name] = path.split('/');
|
|
29
|
-
|
|
30
|
-
if (!suppressWarning && this.get(path)) {
|
|
31
|
-
console.warn(`Overwriting ${path}`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
switch (type) {
|
|
35
|
-
case 'modules':
|
|
36
|
-
this.modules.set(name, def);
|
|
37
|
-
break;
|
|
38
|
-
case 'formats':
|
|
39
|
-
this.formats.set(name, def);
|
|
40
|
-
break;
|
|
41
|
-
case 'themes':
|
|
42
|
-
this.themes.set(name, def);
|
|
43
|
-
break;
|
|
44
|
-
case 'ui':
|
|
45
|
-
this.ui.set(name, def);
|
|
46
|
-
break;
|
|
47
|
-
default:
|
|
48
|
-
console.warn(`Unknown registry type: ${type}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Get a registered item
|
|
54
|
-
* @param {string} path - Registration path
|
|
55
|
-
* @returns {*}
|
|
56
|
-
*/
|
|
57
|
-
get(path) {
|
|
58
|
-
const [type, name] = path.split('/');
|
|
59
|
-
|
|
60
|
-
switch (type) {
|
|
61
|
-
case 'modules':
|
|
62
|
-
return this.modules.get(name);
|
|
63
|
-
case 'formats':
|
|
64
|
-
return this.formats.get(name);
|
|
65
|
-
case 'themes':
|
|
66
|
-
return this.themes.get(name);
|
|
67
|
-
case 'ui':
|
|
68
|
-
return this.ui.get(name);
|
|
69
|
-
default:
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Check if an item is registered
|
|
76
|
-
* @param {string} path - Registration path
|
|
77
|
-
* @returns {boolean}
|
|
78
|
-
*/
|
|
79
|
-
has(path) {
|
|
80
|
-
return this.get(path) !== null && this.get(path) !== undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Get all registered items of a type
|
|
85
|
-
* @param {string} type - Type to get (modules, formats, themes, ui)
|
|
86
|
-
* @returns {Map}
|
|
87
|
-
*/
|
|
88
|
-
getAll(type) {
|
|
89
|
-
switch (type) {
|
|
90
|
-
case 'modules':
|
|
91
|
-
return new Map(this.modules);
|
|
92
|
-
case 'formats':
|
|
93
|
-
return new Map(this.formats);
|
|
94
|
-
case 'themes':
|
|
95
|
-
return new Map(this.themes);
|
|
96
|
-
case 'ui':
|
|
97
|
-
return new Map(this.ui);
|
|
98
|
-
default:
|
|
99
|
-
return new Map();
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Unregister an item
|
|
105
|
-
* @param {string} path - Registration path
|
|
106
|
-
*/
|
|
107
|
-
unregister(path) {
|
|
108
|
-
const [type, name] = path.split('/');
|
|
109
|
-
|
|
110
|
-
switch (type) {
|
|
111
|
-
case 'modules':
|
|
112
|
-
this.modules.delete(name);
|
|
113
|
-
break;
|
|
114
|
-
case 'formats':
|
|
115
|
-
this.formats.delete(name);
|
|
116
|
-
break;
|
|
117
|
-
case 'themes':
|
|
118
|
-
this.themes.delete(name);
|
|
119
|
-
break;
|
|
120
|
-
case 'ui':
|
|
121
|
-
this.ui.delete(name);
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Clear all registrations
|
|
128
|
-
*/
|
|
129
|
-
clear() {
|
|
130
|
-
this.modules.clear();
|
|
131
|
-
this.formats.clear();
|
|
132
|
-
this.themes.clear();
|
|
133
|
-
this.ui.clear();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Get all registered items for debugging
|
|
138
|
-
*/
|
|
139
|
-
getAllItems() {
|
|
140
|
-
const items = {};
|
|
141
|
-
items.modules = Array.from(this.modules.keys());
|
|
142
|
-
items.formats = Array.from(this.formats.keys());
|
|
143
|
-
items.themes = Array.from(this.themes.keys());
|
|
144
|
-
items.ui = Array.from(this.ui.keys());
|
|
145
|
-
return items;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Create singleton instance
|
|
150
|
-
const registry = new Registry();
|
|
151
|
-
|
|
152
|
-
export default registry;
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { InlineFormat } from '../core/format.js';
|
|
2
|
-
import ColorPicker from '../ui/color-picker.js';
|
|
3
|
-
import { saveBeforeFormat } from '../utils/history-helper.js';
|
|
4
|
-
import Editor from '../core/editor.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Background Color Format - Handles text background color formatting
|
|
8
|
-
* Now supports multiple editor instances with separate popup instances
|
|
9
|
-
*/
|
|
10
|
-
class Background extends InlineFormat {
|
|
11
|
-
static formatName = 'background';
|
|
12
|
-
static tagName = 'SPAN';
|
|
13
|
-
static attribute = 'background-color';
|
|
14
|
-
|
|
15
|
-
constructor() {
|
|
16
|
-
super();
|
|
17
|
-
|
|
18
|
-
// Get current editor instance
|
|
19
|
-
const currentEditor = Editor.getCurrentInstance();
|
|
20
|
-
if (!currentEditor) {
|
|
21
|
-
console.warn('No editor instance found for Background format');
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
this.editorId = currentEditor.instanceId;
|
|
26
|
-
|
|
27
|
-
// Check if this editor already has a background color picker instance
|
|
28
|
-
let colorPicker = currentEditor.getPopupInstance('background');
|
|
29
|
-
|
|
30
|
-
if (!colorPicker) {
|
|
31
|
-
// Create new color picker instance for this editor
|
|
32
|
-
colorPicker = new ColorPicker({
|
|
33
|
-
onColorSelect: (color) => {
|
|
34
|
-
Background.applyBackgroundToCurrentSelection(color, this.editorId);
|
|
35
|
-
},
|
|
36
|
-
editor: currentEditor,
|
|
37
|
-
editorId: this.editorId
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Store popup instance in editor
|
|
41
|
-
currentEditor.setPopupInstance('background', colorPicker);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
this.colorPicker = colorPicker;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Create a new Background format instance for a specific editor
|
|
49
|
-
* @param {string} editorId - Editor instance ID
|
|
50
|
-
* @returns {Background} Background format instance
|
|
51
|
-
*/
|
|
52
|
-
static createForEditor(editorId) {
|
|
53
|
-
const editor = Editor.getInstanceById(editorId);
|
|
54
|
-
if (!editor) {
|
|
55
|
-
console.warn('No editor instance found for ID:', editorId);
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Temporarily set as current instance
|
|
60
|
-
const originalCurrent = Editor.currentInstance;
|
|
61
|
-
Editor.currentInstance = editor;
|
|
62
|
-
|
|
63
|
-
// Create format instance
|
|
64
|
-
const format = new Background();
|
|
65
|
-
|
|
66
|
-
// Restore original current instance
|
|
67
|
-
Editor.currentInstance = originalCurrent;
|
|
68
|
-
|
|
69
|
-
return format;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Static method to apply background color to current selection
|
|
74
|
-
* @param {string} color - Background color value
|
|
75
|
-
* @param {string} editorId - Editor instance ID
|
|
76
|
-
*/
|
|
77
|
-
static applyBackgroundToCurrentSelection(color, editorId = null) {
|
|
78
|
-
// Get the correct editor instance
|
|
79
|
-
let editor = null;
|
|
80
|
-
if (editorId) {
|
|
81
|
-
editor = Editor.getInstanceById(editorId);
|
|
82
|
-
} else {
|
|
83
|
-
editor = Editor.getCurrentInstance();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (!editor) {
|
|
87
|
-
console.warn('No editor instance found for background color application');
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const selection = window.getSelection();
|
|
92
|
-
if (!selection || !selection.rangeCount || selection.isCollapsed) return;
|
|
93
|
-
|
|
94
|
-
// Save state before applying format
|
|
95
|
-
saveBeforeFormat();
|
|
96
|
-
|
|
97
|
-
// Find background button in the current editor's toolbar
|
|
98
|
-
const toolbar = editor.getModule('toolbar');
|
|
99
|
-
let backgroundButton = null;
|
|
100
|
-
|
|
101
|
-
if (toolbar) {
|
|
102
|
-
backgroundButton = toolbar.getButton('background');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Fallback: find button by class in the current editor's toolbar
|
|
106
|
-
if (!backgroundButton) {
|
|
107
|
-
const toolbarContainer = toolbar?.getContainer();
|
|
108
|
-
if (toolbarContainer) {
|
|
109
|
-
backgroundButton = toolbarContainer.querySelector('.rich-editor-toolbar-btn.background-btn');
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Final fallback: find any background button in the current editor's wrapper
|
|
114
|
-
if (!backgroundButton) {
|
|
115
|
-
backgroundButton = editor.wrapper.querySelector('.rich-editor-toolbar-btn.background-btn');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
document.execCommand('styleWithCSS', false, true);
|
|
120
|
-
document.execCommand('backColor', false, color);
|
|
121
|
-
if (backgroundButton) {
|
|
122
|
-
backgroundButton.classList.add('active');
|
|
123
|
-
}
|
|
124
|
-
} catch (error) {
|
|
125
|
-
console.error('Error applying background color format:', error);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Trigger content change after applying format
|
|
129
|
-
setTimeout(() => {
|
|
130
|
-
if (editor && typeof editor.onContentChange === 'function') {
|
|
131
|
-
editor.onContentChange();
|
|
132
|
-
}
|
|
133
|
-
}, 0);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Toggle background color formatting - shows/hides color picker
|
|
138
|
-
*/
|
|
139
|
-
toggle() {
|
|
140
|
-
if (this.colorPicker.isVisible) {
|
|
141
|
-
this.colorPicker.hide();
|
|
142
|
-
} else {
|
|
143
|
-
this.showColorPicker();
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Show color picker positioned relative to background button on toolbar
|
|
149
|
-
*/
|
|
150
|
-
showColorPicker() {
|
|
151
|
-
// Find background button in the current editor's toolbar
|
|
152
|
-
const editor = Editor.getInstanceById(this.editorId);
|
|
153
|
-
if (!editor) return;
|
|
154
|
-
|
|
155
|
-
const toolbar = editor.getModule('toolbar');
|
|
156
|
-
let backgroundButton = null;
|
|
157
|
-
|
|
158
|
-
if (toolbar) {
|
|
159
|
-
backgroundButton = toolbar.getButton('background');
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Fallback: find button by class in the current editor's toolbar
|
|
163
|
-
if (!backgroundButton) {
|
|
164
|
-
const toolbarContainer = toolbar?.getContainer();
|
|
165
|
-
if (toolbarContainer) {
|
|
166
|
-
backgroundButton = toolbarContainer.querySelector('.rich-editor-toolbar-btn.background-btn');
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Final fallback: find any background button in the current editor's wrapper
|
|
171
|
-
if (!backgroundButton) {
|
|
172
|
-
backgroundButton = editor.wrapper.querySelector('.rich-editor-toolbar-btn.background-btn');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (!backgroundButton) {
|
|
176
|
-
console.warn('Background button not found for editor:', this.editorId);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
this.colorPicker.show(backgroundButton);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Check if background color formatting is active in current selection
|
|
185
|
-
*/
|
|
186
|
-
isActive() {
|
|
187
|
-
const selection = window.getSelection();
|
|
188
|
-
if (!selection || !selection.rangeCount) return false;
|
|
189
|
-
|
|
190
|
-
const range = selection.getRangeAt(0);
|
|
191
|
-
let node = range.startContainer;
|
|
192
|
-
|
|
193
|
-
// Nếu là text node thì lấy parent element
|
|
194
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
195
|
-
node = node.parentNode;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
while (node && node !== document.body) {
|
|
199
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
200
|
-
const bg = window.getComputedStyle(node).backgroundColor;
|
|
201
|
-
if ((bg && bg != 'rgba(0, 0, 0, 0)' && bg !== 'transparent')&&(bg && bg!= 'rgb(255, 255, 255)' && bg !== 'transparent')) {
|
|
202
|
-
return true;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
node = node.parentNode;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export default Background;
|
package/lib/formats/bold.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { InlineFormat } from '../core/format.js';
|
|
2
|
-
import { saveBeforeFormat } from '../utils/history-helper.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Bold Format - Handles bold text formatting
|
|
6
|
-
*/
|
|
7
|
-
class Bold extends InlineFormat {
|
|
8
|
-
static formatName = 'bold';
|
|
9
|
-
static tagName = 'B';
|
|
10
|
-
static alternativeTagNames = ['STRONG'];
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Apply bold formatting using execCommand
|
|
14
|
-
*/
|
|
15
|
-
apply() {
|
|
16
|
-
// Save state before applying format
|
|
17
|
-
saveBeforeFormat();
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
document.execCommand('bold', false, null);
|
|
21
|
-
} catch (error) {
|
|
22
|
-
console.error('Error applying bold format:', error);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Remove bold formatting using execCommand
|
|
28
|
-
*/
|
|
29
|
-
remove() {
|
|
30
|
-
try {
|
|
31
|
-
document.execCommand('bold', false, null);
|
|
32
|
-
} catch (error) {
|
|
33
|
-
console.error('Error removing bold format:', error);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Toggle bold formatting
|
|
39
|
-
*/
|
|
40
|
-
toggle() {
|
|
41
|
-
// Save state before applying format
|
|
42
|
-
saveBeforeFormat();
|
|
43
|
-
|
|
44
|
-
try {
|
|
45
|
-
document.execCommand('bold', false, null);
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error('Error toggling bold format:', error);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Check if bold formatting is active using execCommand
|
|
53
|
-
*/
|
|
54
|
-
isActive() {
|
|
55
|
-
try {
|
|
56
|
-
return document.queryCommandState('bold');
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.error('Error checking bold state:', error);
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
export default Bold;
|