@ebl-vue/editor-full 1.0.12 → 1.1.1

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 (52) hide show
  1. package/dist/index.d.ts +6 -0
  2. package/dist/index.mjs +860 -445
  3. package/dist/index.mjs.map +1 -1
  4. package/package.json +2 -1
  5. package/src/components/Editor/Editor.vue +47 -12
  6. package/src/i18n/zh-cn.ts +6 -1
  7. package/src/icons/index.ts +15 -0
  8. package/src/installer.ts +4 -3
  9. package/src/plugins/alert/index.ts +19 -27
  10. package/src/plugins/block-alignment/index.ts +4 -3
  11. package/src/plugins/code/index.ts +3 -2
  12. package/src/plugins/color-picker/index.ts +3 -11
  13. package/src/plugins/delimiter/index.ts +5 -6
  14. package/src/plugins/header/H1.ts +1 -1
  15. package/src/plugins/header/H2.ts +1 -1
  16. package/src/plugins/header/H3.ts +1 -1
  17. package/src/plugins/header/H4.ts +1 -2
  18. package/src/plugins/header/H5.ts +1 -3
  19. package/src/plugins/header/H6.ts +1 -3
  20. package/src/plugins/imageResizeCrop/ImageTune.ts +900 -0
  21. package/src/plugins/imageResizeCrop/index.css +234 -0
  22. package/src/plugins/imageResizeCrop/index.ts +5 -0
  23. package/src/plugins/imageResizeCrop/types.d.ts +23 -0
  24. package/src/plugins/imageTool/index.css +145 -0
  25. package/src/plugins/imageTool/index.ts +538 -0
  26. package/src/plugins/imageTool/types/codexteam__ajax.d.ts +89 -0
  27. package/src/plugins/imageTool/types/types.ts +236 -0
  28. package/src/plugins/imageTool/ui.ts +313 -0
  29. package/src/plugins/imageTool/uploader.ts +268 -0
  30. package/src/plugins/imageTool/utils/dom.ts +24 -0
  31. package/src/plugins/imageTool/utils/index.ts +73 -0
  32. package/src/plugins/imageTool/utils/isPromise.ts +10 -0
  33. package/src/plugins/indent/index.ts +5 -7
  34. package/src/plugins/inline-code/index.ts +2 -5
  35. package/src/plugins/list/ListRenderer/ChecklistRenderer.ts +1 -4
  36. package/src/plugins/list/index.ts +20 -37
  37. package/src/plugins/list/types/OlCounterType.ts +1 -1
  38. package/src/plugins/marker/index.ts +28 -16
  39. package/src/plugins/paragraph/index.ts +3 -2
  40. package/src/plugins/quote/index.ts +1 -4
  41. package/src/plugins/table/plugin.ts +1 -1
  42. package/src/plugins/table/table.ts +40 -38
  43. package/src/plugins/table/toolbox.ts +5 -4
  44. package/src/plugins/table/utils/dom.ts +15 -14
  45. package/src/plugins/table/utils/popover.ts +28 -15
  46. package/src/plugins/underline/index.ts +2 -4
  47. package/src/plugins/undo/index.ts +48 -33
  48. package/src/plugins/undo/observer.ts +3 -3
  49. package/src/utils/AxiosService.ts +87 -0
  50. package/types/index.d.ts +6 -0
  51. package/vite.config.ts +3 -1
  52. package/src/plugins/list/styles/icons/index.ts +0 -10
@@ -0,0 +1,236 @@
1
+ import type { HTMLPasteEventDetail } from '@editorjs/editorjs';
2
+
3
+ /**
4
+ * Represents options for uploading, including a function to handle previewing.
5
+ */
6
+ export interface UploadOptions {
7
+ /**
8
+ * Callback function to be called when the preview is ready.
9
+ * @param src - The source of the preview as a string.
10
+ * @returns void
11
+ */
12
+ onPreview: (src: string) => void;
13
+ noSelectedFile:()=>void;
14
+ }
15
+
16
+ /**
17
+ * User configuration of Image block tunes. Allows to add custom tunes through the config
18
+ */
19
+ export interface ActionConfig {
20
+ /**
21
+ * The name of the tune.
22
+ */
23
+ name: string;
24
+
25
+ /**
26
+ * The icon for the tune. Should be an SVG string.
27
+ */
28
+ icon: string;
29
+
30
+ /**
31
+ * The title of the tune. This will be displayed in the UI.
32
+ */
33
+ title: string;
34
+
35
+ /**
36
+ * An optional flag indicating whether the tune is a toggle (true) or not (false).
37
+ */
38
+ toggle?: boolean;
39
+
40
+ /**
41
+ * An optional action function to be executed when the tune is activated.
42
+ */
43
+ action?: Function;
44
+ };
45
+
46
+ /**
47
+ * UploadResponseFormat interface representing the response format expected from the backend on file uploading.
48
+ */
49
+ export interface UploadResponseFormat<AdditionalFileData = {}> {
50
+ status?: number;
51
+ /**
52
+ * success - 1 for successful uploading, 0 for failure
53
+ */
54
+ success: number;
55
+
56
+ /**
57
+ * Object with file data.
58
+ * 'url' is required,
59
+ * also can contain any additional data that will be saved and passed back
60
+ */
61
+ file: {
62
+ /**
63
+ * The URL of the uploaded image.
64
+ */
65
+ url: string;
66
+ } & AdditionalFileData;
67
+ }
68
+ export interface IUploadResponseFormat<> {
69
+
70
+ success: boolean;
71
+ data?: any,
72
+ message?: string;
73
+ }
74
+ /**
75
+ * ImageToolData type representing the input and output data format for the image tool, including optional custome actions.
76
+ */
77
+ export type ImageToolData<Actions = {}, AdditionalFileData = {}> = {
78
+ /**
79
+ * Caption for the image.
80
+ */
81
+ caption: string;
82
+
83
+ /**
84
+ * Flag indicating whether the image has a border.
85
+ */
86
+ withBorder: boolean;
87
+
88
+ /**
89
+ * Flag indicating whether the image has a background.
90
+ */
91
+ withBackground: boolean;
92
+
93
+ /**
94
+ * Flag indicating whether the image is stretched.
95
+ */
96
+ stretched: boolean;
97
+
98
+ /**
99
+ * Object containing the URL of the image file.
100
+ * Also can contain any additional data.
101
+ */
102
+ file: {
103
+ /**
104
+ * The URL of the image.
105
+ */
106
+ url: string;
107
+ } & AdditionalFileData;
108
+ } & (Actions extends Record<string, boolean> ? Actions : {});
109
+
110
+ /**
111
+ * @description Allows to enable or disable features.
112
+ */
113
+ export type FeaturesConfig = {
114
+ /**
115
+ * Flag to enable/disable tune - background.
116
+ */
117
+ background?: boolean;
118
+ /**
119
+ * Flag to enable/disable tune - border.
120
+ */
121
+ border?: boolean;
122
+ /**
123
+ * Flag to enable/disable caption.
124
+ * Can be set to 'optional' to allow users to toggle via block tunes.
125
+ */
126
+ caption?: boolean | 'optional';
127
+ /**
128
+ * Flag to enable/disable tune - stretched
129
+ */
130
+ stretch?: boolean;
131
+ };
132
+
133
+ /**
134
+ *
135
+ * @description Config supported by Tool
136
+ */
137
+ export interface ImageConfig {
138
+ userStore?: any;
139
+ /**
140
+ * Endpoints for upload, whether using file or URL.
141
+ */
142
+ endpoints: {
143
+
144
+ /**
145
+ * Endpoint for file upload.
146
+ */
147
+ byFile?: string;
148
+
149
+ /**
150
+ * Endpoints for URL upload.
151
+ */
152
+ byUrl?: string;
153
+ };
154
+
155
+ /**
156
+ * Field name for the uploaded image.
157
+ */
158
+ field?: string;
159
+
160
+ /**
161
+ * Allowed mime-types for the uploaded image.
162
+ */
163
+ types?: string;
164
+
165
+ /**
166
+ * Placeholder text for the caption field.
167
+ */
168
+ captionPlaceholder?: string;
169
+
170
+ /**
171
+ * Additional data to send with requests.
172
+ */
173
+ additionalRequestData?: object;
174
+
175
+ /**
176
+ * Additional headers to send with requests.
177
+ */
178
+ additionalRequestHeaders?: object;
179
+
180
+ /**
181
+ * Custom content for the select file button.
182
+ */
183
+ buttonContent?: string;
184
+
185
+ /**
186
+ * Optional custom uploader.
187
+ */
188
+ uploader?: {
189
+
190
+ /**
191
+ * Method to upload an image by file.
192
+ */
193
+ uploadByFile?: (file: Blob) => Promise<UploadResponseFormat>;
194
+
195
+ /**
196
+ * Method to upload an image by URL.
197
+ */
198
+ uploadByUrl?: (url: string) => Promise<UploadResponseFormat>;
199
+ };
200
+
201
+ /**
202
+ * Additional actions for the tool.
203
+ */
204
+ actions?: ActionConfig[];
205
+
206
+ /**
207
+ * Tunes to be enabled.
208
+ */
209
+ features?: FeaturesConfig;
210
+ }
211
+
212
+ /**
213
+ * Interface representing the details of a paste event for HTML elements.
214
+ * Extends the `HTMLPasteEventDetail` interface to include additional data properties.
215
+ */
216
+ export interface HTMLPasteEventDetailExtended extends HTMLPasteEventDetail {
217
+ /**
218
+ * The data property containing the source of the image and HTML element details.
219
+ */
220
+ data: {
221
+ /**
222
+ * The source URL of the pasted image.
223
+ */
224
+ src: string;
225
+ } & HTMLElement;
226
+ }
227
+
228
+ /**
229
+ * Parameter type of Image setter function in ImageTool
230
+ */
231
+ export type ImageSetterParam = {
232
+ /**
233
+ * url path of the image
234
+ */
235
+ url: string;
236
+ };
@@ -0,0 +1,313 @@
1
+ import { IconPicture } from '../../icons';
2
+ import { make } from './utils/dom';
3
+ import type { API } from '@editorjs/editorjs';
4
+ import type { ImageConfig } from './types/types';
5
+
6
+ /**
7
+ * Enumeration representing the different states of the UI.
8
+ */
9
+ export enum UiState {
10
+ /**
11
+ * The UI is in an empty state, with no image loaded or being selected.
12
+ */
13
+ Empty = 'empty',
14
+
15
+ /**
16
+ * The UI is in an uploading state, indicating an image is currently being uploaded.
17
+ */
18
+ Uploading = 'uploading',
19
+
20
+ /**
21
+ * The UI is in a filled state, with an image successfully loaded.
22
+ */
23
+ Filled = 'filled'
24
+ };
25
+
26
+ /**
27
+ * Nodes interface representing various elements in the UI.
28
+ */
29
+ interface Nodes {
30
+ /**
31
+ * Wrapper element in the UI.
32
+ */
33
+ wrapper: HTMLElement;
34
+
35
+ /**
36
+ * Container for the image element in the UI.
37
+ */
38
+ imageContainer: HTMLElement;
39
+
40
+ /**
41
+ * Button for selecting files.
42
+ */
43
+ fileButton: HTMLElement;
44
+
45
+ /**
46
+ * Represents the image element in the UI, if one is present; otherwise, it's undefined.
47
+ */
48
+ imageEl?: HTMLElement;
49
+
50
+ /**
51
+ * Preloader element for the image.
52
+ */
53
+ imagePreloader: HTMLElement;
54
+
55
+ /**
56
+ * Caption element for the image.
57
+ */
58
+ caption: HTMLElement;
59
+ }
60
+
61
+ /**
62
+ * ConstructorParams interface representing parameters for the Ui class constructor.
63
+ */
64
+ interface ConstructorParams {
65
+ /**
66
+ * Editor.js API.
67
+ */
68
+ api: API;
69
+ /**
70
+ * Configuration for the image.
71
+ */
72
+ config: ImageConfig;
73
+ /**
74
+ * Callback function for selecting a file.
75
+ */
76
+ onSelectFile: () => void;
77
+ /**
78
+ * Flag indicating if the UI is in read-only mode.
79
+ */
80
+ readOnly: boolean;
81
+ }
82
+
83
+ /**
84
+ * Class for working with UI:
85
+ * - rendering base structure
86
+ * - show/hide preview
87
+ * - apply tune view
88
+ */
89
+ export default class Ui {
90
+ /**
91
+ * Nodes representing various elements in the UI.
92
+ */
93
+ public nodes: Nodes;
94
+
95
+ /**
96
+ * API instance for Editor.js.
97
+ */
98
+ private api: API;
99
+
100
+ /**
101
+ * Configuration for the image tool.
102
+ */
103
+ private config: ImageConfig;
104
+
105
+ /**
106
+ * Callback function for selecting a file.
107
+ */
108
+ private onSelectFile: () => void;
109
+
110
+ /**
111
+ * Flag indicating if the UI is in read-only mode.
112
+ */
113
+ private readOnly: boolean;
114
+
115
+ /**
116
+ * @param ui - image tool Ui module
117
+ * @param ui.api - Editor.js API
118
+ * @param ui.config - user config
119
+ * @param ui.onSelectFile - callback for clicks on Select file button
120
+ * @param ui.readOnly - read-only mode flag
121
+ */
122
+ constructor({ api, config, onSelectFile, readOnly }: ConstructorParams) {
123
+ this.api = api;
124
+ this.config = config;
125
+ this.onSelectFile = onSelectFile;
126
+
127
+ this.readOnly = readOnly;
128
+ this.nodes = {
129
+ wrapper: make('div', [this.CSS.baseClass, this.CSS.wrapper]),
130
+ imageContainer: make('div', [this.CSS.imageContainer]),
131
+ fileButton: this.createFileButton(),
132
+ imageEl: undefined,
133
+ imagePreloader: make('div', this.CSS.imagePreloader),
134
+ caption: make('div', [this.CSS.input, this.CSS.caption], {
135
+ contentEditable: !this.readOnly,
136
+ }),
137
+ };
138
+
139
+ /**
140
+ * Create base structure
141
+ * <wrapper>
142
+ * <image-container>
143
+ * <image-preloader />
144
+ * </image-container>
145
+ * <caption />
146
+ * <select-file-button />
147
+ * </wrapper>
148
+ */
149
+ this.nodes.caption.dataset.placeholder = this.config.captionPlaceholder;
150
+ this.nodes.imageContainer.appendChild(this.nodes.imagePreloader);
151
+ this.nodes.wrapper.appendChild(this.nodes.imageContainer);
152
+ this.nodes.wrapper.appendChild(this.nodes.caption);
153
+ this.nodes.wrapper.appendChild(this.nodes.fileButton);
154
+ }
155
+
156
+ /**
157
+ * Apply visual representation of activated tune
158
+ * @param tuneName - one of available tunes {@link Tunes.tunes}
159
+ * @param status - true for enable, false for disable
160
+ */
161
+ public applyTune(tuneName: string, status: boolean): void {
162
+ this.nodes.wrapper.classList.toggle(`${this.CSS.wrapper}--${tuneName}`, status);
163
+ }
164
+
165
+ /**
166
+ * Renders tool UI
167
+ */
168
+ public render(): HTMLElement {
169
+ this.toggleStatus(UiState.Empty);
170
+
171
+ return this.nodes.wrapper;
172
+ }
173
+
174
+ /**
175
+ * Shows uploading preloader
176
+ * @param src - preview source
177
+ */
178
+ public showPreloader(src: string): void {
179
+ this.nodes.imagePreloader.style.backgroundImage = `url(${src})`;
180
+
181
+ //this.toggleStatus(UiState.Uploading);
182
+ }
183
+
184
+
185
+ /**
186
+ * Hide uploading preloader
187
+ */
188
+ public hidePreloader(): void {
189
+ this.nodes.imagePreloader.style.backgroundImage = '';
190
+ this.toggleStatus(UiState.Empty);
191
+ }
192
+
193
+ /**
194
+ * Shows an image
195
+ * @param url - image source
196
+ */
197
+ public fillImage(url: string): void {
198
+ /**
199
+ * Check for a source extension to compose element correctly: video tag for mp4, img — for others
200
+ */
201
+ const tag = /\.mp4$/.test(url) ? 'VIDEO' : 'IMG';
202
+
203
+ const attributes: { [key: string]: string | boolean } = {
204
+ src: url,
205
+ };
206
+
207
+ /**
208
+ * We use eventName variable because IMG and VIDEO tags have different event to be called on source load
209
+ * - IMG: load
210
+ * - VIDEO: loadeddata
211
+ */
212
+ let eventName = 'load';
213
+
214
+ /**
215
+ * Update attributes and eventName if source is a mp4 video
216
+ */
217
+ if (tag === 'VIDEO') {
218
+ /**
219
+ * Add attributes for playing muted mp4 as a gif
220
+ */
221
+ attributes.autoplay = true;
222
+ attributes.loop = true;
223
+ attributes.muted = true;
224
+ attributes.playsinline = true;
225
+
226
+ /**
227
+ * Change event to be listened
228
+ */
229
+ eventName = 'loadeddata';
230
+ }
231
+
232
+ /**
233
+ * Compose tag with defined attributes
234
+ */
235
+ this.nodes.imageEl = make(tag, this.CSS.imageEl, attributes);
236
+
237
+ /**
238
+ * Add load event listener
239
+ */
240
+ this.nodes.imageEl.addEventListener(eventName, () => {
241
+ this.toggleStatus(UiState.Filled);
242
+
243
+ /**
244
+ * Preloader does not exists on first rendering with presaved data
245
+ */
246
+ if (this.nodes.imagePreloader !== undefined) {
247
+ this.nodes.imagePreloader.style.backgroundImage = '';
248
+ }
249
+ });
250
+
251
+ this.nodes.imageContainer.appendChild(this.nodes.imageEl);
252
+ }
253
+
254
+ /**
255
+ * Shows caption input
256
+ * @param text - caption content text
257
+ */
258
+ public fillCaption(text: string): void {
259
+ if (this.nodes.caption !== undefined) {
260
+ this.nodes.caption.innerHTML = text;
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Changes UI status
266
+ * @param status - see {@link Ui.status} constants
267
+ */
268
+ public toggleStatus(status: UiState): void {
269
+ for (const statusType in UiState) {
270
+ if (Object.prototype.hasOwnProperty.call(UiState, statusType)) {
271
+ const state = UiState[statusType as keyof typeof UiState];
272
+
273
+ this.nodes.wrapper.classList.toggle(`${this.CSS.wrapper}--${state}`, state === status);
274
+ }
275
+ }
276
+ }
277
+
278
+ /**
279
+ * CSS classes
280
+ */
281
+ private get CSS(): Record<string, string> {
282
+ return {
283
+ baseClass: this.api.styles.block,
284
+ loading: this.api.styles.loader,
285
+ input: this.api.styles.input,
286
+ button: this.api.styles.button,
287
+
288
+ /**
289
+ * Tool's classes
290
+ */
291
+ wrapper: 'image-tool',
292
+ imageContainer: 'image-tool__image',
293
+ imagePreloader: 'image-tool__image-preloader',
294
+ imageEl: 'image-tool__image-picture',
295
+ caption: 'image-tool__caption',
296
+ };
297
+ };
298
+
299
+ /**
300
+ * Creates upload-file button
301
+ */
302
+ private createFileButton(): HTMLElement {
303
+ const button = make('div', [this.CSS.button]);
304
+
305
+ button.innerHTML = this.config.buttonContent ?? `${IconPicture} ${this.api.i18n.t('Select an Image')}`;
306
+
307
+ button.addEventListener('click', () => {
308
+ this.onSelectFile();
309
+ });
310
+
311
+ return button;
312
+ }
313
+ }