@firestitch/html-editor 12.5.1 → 12.5.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.
Files changed (51) hide show
  1. package/app/modules/html-editor/classes/plugin.d.ts +7 -7
  2. package/app/modules/html-editor/components/html-editor/html-editor.component.d.ts +58 -58
  3. package/app/modules/html-editor/consts/paragraph-buttons.const.d.ts +1 -1
  4. package/app/modules/html-editor/consts/rich-buttons.const.d.ts +1 -1
  5. package/app/modules/html-editor/consts/text-buttons.const.d.ts +1 -1
  6. package/app/modules/html-editor/enums/default-plugin.enum.d.ts +16 -16
  7. package/app/modules/html-editor/fs-html-editor.module.d.ts +43 -43
  8. package/app/modules/html-editor/injects/config.inject.d.ts +3 -3
  9. package/app/modules/html-editor/interfaces/html-editor-config.d.ts +40 -40
  10. package/app/modules/html-editor/interfaces/plugin-button.d.ts +12 -12
  11. package/app/modules/html-editor/interfaces/plugin-config.d.ts +5 -5
  12. package/app/modules/html-editor/plugins/checklist.plugin.d.ts +7 -7
  13. package/app/modules/html-editor/plugins/code.plugin.d.ts +9 -9
  14. package/app/modules/html-editor/plugins/configs/mention-plugin.config.d.ts +13 -13
  15. package/app/modules/html-editor/plugins/configs/screen-record-plugin.config.d.ts +7 -7
  16. package/app/modules/html-editor/plugins/mention.plugin.d.ts +15 -15
  17. package/app/modules/html-editor/plugins/realtime.plugin.d.ts +7 -7
  18. package/app/modules/html-editor/plugins/screen-record.plugin.d.ts +11 -11
  19. package/app/modules/html-editor/services/froala-loader.service.d.ts +21 -21
  20. package/app/modules/html-renderer/components/html-renderer/html-renderer.component.d.ts +12 -12
  21. package/app/modules/html-renderer/fs-html-renderer.module.d.ts +8 -8
  22. package/bundles/firestitch-html-editor.umd.js +1382 -1374
  23. package/bundles/firestitch-html-editor.umd.js.map +1 -1
  24. package/esm2015/app/modules/html-editor/classes/plugin.js +4 -4
  25. package/esm2015/app/modules/html-editor/components/html-editor/html-editor.component.js +516 -507
  26. package/esm2015/app/modules/html-editor/consts/paragraph-buttons.const.js +9 -9
  27. package/esm2015/app/modules/html-editor/consts/rich-buttons.const.js +6 -6
  28. package/esm2015/app/modules/html-editor/consts/text-buttons.const.js +18 -18
  29. package/esm2015/app/modules/html-editor/enums/default-plugin.enum.js +1 -1
  30. package/esm2015/app/modules/html-editor/fs-html-editor.module.js +68 -68
  31. package/esm2015/app/modules/html-editor/injects/config.inject.js +3 -3
  32. package/esm2015/app/modules/html-editor/interfaces/html-editor-config.js +1 -1
  33. package/esm2015/app/modules/html-editor/interfaces/plugin-button.js +1 -1
  34. package/esm2015/app/modules/html-editor/interfaces/plugin-config.js +1 -1
  35. package/esm2015/app/modules/html-editor/plugins/checklist.plugin.js +34 -34
  36. package/esm2015/app/modules/html-editor/plugins/code.plugin.js +62 -62
  37. package/esm2015/app/modules/html-editor/plugins/configs/mention-plugin.config.js +1 -1
  38. package/esm2015/app/modules/html-editor/plugins/configs/screen-record-plugin.config.js +1 -1
  39. package/esm2015/app/modules/html-editor/plugins/mention.plugin.js +86 -86
  40. package/esm2015/app/modules/html-editor/plugins/realtime.plugin.js +12 -12
  41. package/esm2015/app/modules/html-editor/plugins/screen-record.plugin.js +88 -88
  42. package/esm2015/app/modules/html-editor/services/froala-loader.service.js +88 -88
  43. package/esm2015/app/modules/html-renderer/components/html-renderer/html-renderer.component.js +28 -28
  44. package/esm2015/app/modules/html-renderer/fs-html-renderer.module.js +25 -25
  45. package/esm2015/firestitch-html-editor.js +4 -4
  46. package/esm2015/public_api.js +13 -13
  47. package/fesm2015/firestitch-html-editor.js +983 -974
  48. package/fesm2015/firestitch-html-editor.js.map +1 -1
  49. package/firestitch-html-editor.d.ts +5 -5
  50. package/package.json +1 -1
  51. package/public_api.d.ts +18 -18
@@ -16,1012 +16,1021 @@ import * as i1 from '@angular/platform-browser';
16
16
  import Tribute from 'tributejs';
17
17
  import { __awaiter } from 'tslib';
18
18
 
19
- const RichButtons = [
20
- 'insertTable',
21
- 'insertImage',
22
- 'insertLink',
23
- 'insertVideo',
19
+ const RichButtons = [
20
+ 'insertTable',
21
+ 'insertImage',
22
+ 'insertLink',
23
+ 'insertVideo',
24
24
  ];
25
25
 
26
- const TextButtons = [
27
- 'paragraphFormat',
28
- 'code',
29
- 'bold',
30
- 'italic',
31
- 'underline',
32
- 'strikeThrough',
33
- 'subscript',
34
- 'superscript',
35
- 'fontFamily',
36
- 'fontSize',
37
- 'textColor',
38
- 'backgroundColor',
39
- 'inlineClass',
40
- 'inlineStyle',
41
- 'clearFormatting',
42
- 'quote',
26
+ const TextButtons = [
27
+ 'paragraphFormat',
28
+ 'code',
29
+ 'bold',
30
+ 'italic',
31
+ 'underline',
32
+ 'strikeThrough',
33
+ 'subscript',
34
+ 'superscript',
35
+ 'fontFamily',
36
+ 'fontSize',
37
+ 'textColor',
38
+ 'backgroundColor',
39
+ 'inlineClass',
40
+ 'inlineStyle',
41
+ 'clearFormatting',
42
+ 'quote',
43
43
  ];
44
44
 
45
- const ParagraphButtons = [
46
- 'align',
47
- 'formatOL',
48
- 'formatUL',
49
- 'checklist',
50
- 'indent',
51
- 'outdent',
52
- 'lineHeight'
45
+ const ParagraphButtons = [
46
+ 'align',
47
+ 'formatOL',
48
+ 'formatUL',
49
+ 'checklist',
50
+ 'indent',
51
+ 'outdent',
52
+ 'lineHeight'
53
53
  ];
54
54
 
55
- const FS_HTML_EDITOR_DEFAULT_CONFIG = new InjectionToken('fs-html-editor.default-config');
55
+ const FS_HTML_EDITOR_DEFAULT_CONFIG = new InjectionToken('fs-html-editor.default-config');
56
56
  const FS_HTML_EDITOR_CONFIG = new InjectionToken('fs-html-editor.config');
57
57
 
58
- class FsFroalaLoaderService {
59
- constructor(_defaultConfig, _document) {
60
- this._defaultConfig = _defaultConfig;
61
- this._document = _document;
62
- this._froalaLoaded = new BehaviorSubject(false);
63
- this._froalaPluginsLoaded = new BehaviorSubject(false);
64
- this._sourceLoader = fsSourceLoader;
65
- this._loaded$ = combineLatest([this._froalaLoaded, this._froalaPluginsLoaded])
66
- .pipe(map(([FroalaReady, pluginsRead]) => {
67
- return pluginsRead && FroalaReady;
68
- }), shareReplay(1));
69
- this._sourceLoader.setDocument(this._document);
70
- this._load();
71
- }
72
- get loaded$() {
73
- return this._loaded$;
74
- }
75
- get FroalaEditor() {
76
- return this._FroalaEditor;
77
- }
78
- _load() {
79
- this._sourceLoader.registerResources({
80
- froala: [
81
- '/assets/js/froala/froala_editor.min.js',
82
- '/assets/css/froala_editor.pkgd.min.css',
83
- ],
84
- froala_align: '/assets/js/froala/plugins/align.min.js',
85
- froala_colors: '/assets/js/froala/plugins/colors.min.js',
86
- froala_image: '/assets/js/froala/plugins/image.min.js',
87
- froala_link: '/assets/js/froala/plugins/link.min.js',
88
- froala_lists: '/assets/js/froala/plugins/lists.min.js',
89
- froala_paragraph_format: '/assets/js/froala/plugins/paragraph_format.min.js',
90
- froala_table: '/assets/js/froala/plugins/table.min.js',
91
- froala_url: '/assets/js/froala/plugins/url.min.js',
92
- froala_video: '/assets/js/froala/plugins/video.min.js',
93
- froala_quote: '/assets/js/froala/plugins/quote.min.js',
94
- froala_draggable: '/assets/js/froala/plugins/draggable.min.js',
95
- froala_font_size: '/assets/js/froala/plugins/font_size.min.js',
96
- froala_quick_insert: '/assets/js/froala/plugins/quick_insert.min.js',
97
- froala_line_height: '/assets/js/froala/plugins/line_height.min.js'
98
- });
99
- this._sourceLoader.loadResource('froala')
100
- .pipe(tap(() => {
101
- this._FroalaEditor = window.FroalaEditor;
102
- this._froalaDone();
103
- }), concatMap(() => {
104
- return this._loadPlugins();
105
- }), tap(() => {
106
- this._froalaPluginsDone();
107
- }))
108
- .subscribe();
109
- }
110
- _loadPlugins() {
111
- const resources = this._defaultConfig
112
- .froalaPlugins
113
- .map((pluginName) => `froala_${pluginName}`);
114
- return this._sourceLoader.loadResources(resources);
115
- }
116
- _froalaDone() {
117
- this._froalaLoaded.next(true);
118
- }
119
- _froalaPluginsDone() {
120
- this._froalaPluginsLoaded.next(true);
121
- }
122
- }
123
- FsFroalaLoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsFroalaLoaderService, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
124
- FsFroalaLoaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsFroalaLoaderService, providedIn: 'root' });
125
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsFroalaLoaderService, decorators: [{
126
- type: Injectable,
127
- args: [{
128
- providedIn: 'root',
129
- }]
130
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
131
- type: Optional
132
- }, {
133
- type: Inject,
134
- args: [FS_HTML_EDITOR_CONFIG]
135
- }] }, { type: Document, decorators: [{
136
- type: Inject,
137
- args: [DOCUMENT]
58
+ class FsFroalaLoaderService {
59
+ constructor(_defaultConfig, _document) {
60
+ this._defaultConfig = _defaultConfig;
61
+ this._document = _document;
62
+ this._froalaLoaded = new BehaviorSubject(false);
63
+ this._froalaPluginsLoaded = new BehaviorSubject(false);
64
+ this._sourceLoader = fsSourceLoader;
65
+ this._loaded$ = combineLatest([this._froalaLoaded, this._froalaPluginsLoaded])
66
+ .pipe(map(([FroalaReady, pluginsRead]) => {
67
+ return pluginsRead && FroalaReady;
68
+ }), shareReplay(1));
69
+ this._sourceLoader.setDocument(this._document);
70
+ this._load();
71
+ }
72
+ get loaded$() {
73
+ return this._loaded$;
74
+ }
75
+ get FroalaEditor() {
76
+ return this._FroalaEditor;
77
+ }
78
+ _load() {
79
+ this._sourceLoader.registerResources({
80
+ froala: [
81
+ '/assets/js/froala/froala_editor.min.js',
82
+ '/assets/css/froala_editor.pkgd.min.css',
83
+ ],
84
+ froala_align: '/assets/js/froala/plugins/align.min.js',
85
+ froala_colors: '/assets/js/froala/plugins/colors.min.js',
86
+ froala_image: '/assets/js/froala/plugins/image.min.js',
87
+ froala_link: '/assets/js/froala/plugins/link.min.js',
88
+ froala_lists: '/assets/js/froala/plugins/lists.min.js',
89
+ froala_paragraph_format: '/assets/js/froala/plugins/paragraph_format.min.js',
90
+ froala_table: '/assets/js/froala/plugins/table.min.js',
91
+ froala_url: '/assets/js/froala/plugins/url.min.js',
92
+ froala_video: '/assets/js/froala/plugins/video.min.js',
93
+ froala_quote: '/assets/js/froala/plugins/quote.min.js',
94
+ froala_draggable: '/assets/js/froala/plugins/draggable.min.js',
95
+ froala_font_size: '/assets/js/froala/plugins/font_size.min.js',
96
+ froala_quick_insert: '/assets/js/froala/plugins/quick_insert.min.js',
97
+ froala_line_height: '/assets/js/froala/plugins/line_height.min.js'
98
+ });
99
+ this._sourceLoader.loadResource('froala')
100
+ .pipe(tap(() => {
101
+ this._FroalaEditor = window.FroalaEditor;
102
+ this._froalaDone();
103
+ }), concatMap(() => {
104
+ return this._loadPlugins();
105
+ }), tap(() => {
106
+ this._froalaPluginsDone();
107
+ }))
108
+ .subscribe();
109
+ }
110
+ _loadPlugins() {
111
+ const resources = this._defaultConfig
112
+ .froalaPlugins
113
+ .map((pluginName) => `froala_${pluginName}`);
114
+ return this._sourceLoader.loadResources(resources);
115
+ }
116
+ _froalaDone() {
117
+ this._froalaLoaded.next(true);
118
+ }
119
+ _froalaPluginsDone() {
120
+ this._froalaPluginsLoaded.next(true);
121
+ }
122
+ }
123
+ FsFroalaLoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsFroalaLoaderService, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
124
+ FsFroalaLoaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsFroalaLoaderService, providedIn: 'root' });
125
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsFroalaLoaderService, decorators: [{
126
+ type: Injectable,
127
+ args: [{
128
+ providedIn: 'root',
129
+ }]
130
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
131
+ type: Optional
132
+ }, {
133
+ type: Inject,
134
+ args: [FS_HTML_EDITOR_CONFIG]
135
+ }] }, { type: Document, decorators: [{
136
+ type: Inject,
137
+ args: [DOCUMENT]
138
138
  }] }]; } });
139
139
 
140
- class FsHtmlRendererComponent {
141
- constructor(sanitized, _cdRef) {
142
- this.sanitized = sanitized;
143
- this._cdRef = _cdRef;
144
- }
145
- set setHtml(html) {
146
- this.trustedHtml = this.sanitized.bypassSecurityTrustHtml(html || '');
147
- this._cdRef.markForCheck();
148
- }
149
- }
150
- FsHtmlRendererComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererComponent, deps: [{ token: i1.DomSanitizer }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
151
- FsHtmlRendererComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FsHtmlRendererComponent, selector: "fs-html-renderer", inputs: { setHtml: ["html", "setHtml"] }, ngImport: i0, template: "<div class=\"fr-view fs-html-editor-default\" [innerHtml]=\"trustedHtml\"></div>\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
152
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererComponent, decorators: [{
153
- type: Component,
154
- args: [{
155
- selector: 'fs-html-renderer',
156
- templateUrl: 'html-renderer.component.html',
157
- styleUrls: ['html-renderer.component.scss'],
158
- changeDetection: ChangeDetectionStrategy.OnPush,
159
- }]
160
- }], ctorParameters: function () { return [{ type: i1.DomSanitizer }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { setHtml: [{
161
- type: Input,
162
- args: ['html']
140
+ class FsHtmlRendererComponent {
141
+ constructor(sanitized, _cdRef) {
142
+ this.sanitized = sanitized;
143
+ this._cdRef = _cdRef;
144
+ }
145
+ set setHtml(html) {
146
+ this.trustedHtml = this.sanitized.bypassSecurityTrustHtml(html || '');
147
+ this._cdRef.markForCheck();
148
+ }
149
+ }
150
+ FsHtmlRendererComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererComponent, deps: [{ token: i1.DomSanitizer }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
151
+ FsHtmlRendererComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FsHtmlRendererComponent, selector: "fs-html-renderer", inputs: { setHtml: ["html", "setHtml"] }, ngImport: i0, template: "<div class=\"fr-view fs-html-editor-default\" [innerHtml]=\"trustedHtml\"></div>\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
152
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererComponent, decorators: [{
153
+ type: Component,
154
+ args: [{
155
+ selector: 'fs-html-renderer',
156
+ templateUrl: 'html-renderer.component.html',
157
+ styleUrls: ['html-renderer.component.scss'],
158
+ changeDetection: ChangeDetectionStrategy.OnPush,
159
+ }]
160
+ }], ctorParameters: function () { return [{ type: i1.DomSanitizer }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { setHtml: [{
161
+ type: Input,
162
+ args: ['html']
163
163
  }] } });
164
164
 
165
- class FsHtmlEditorComponent {
166
- constructor(_defaultConfig, _cdRef, _fr) {
167
- this._defaultConfig = _defaultConfig;
168
- this._cdRef = _cdRef;
169
- this._fr = _fr;
170
- this.classFocused = false;
171
- this.classDisabled = false;
172
- this.config = {};
173
- this.initialized = false;
174
- this._initialize$ = new ReplaySubject();
175
- this._froalaReady$ = new BehaviorSubject(null);
176
- this._destroy$ = new Subject();
177
- this.onChange = (data) => { };
178
- this.onTouched = () => { };
179
- }
180
- get el() {
181
- return this.elRef.nativeElement;
182
- }
183
- get html() {
184
- return this._html;
185
- }
186
- get editor() {
187
- return this._editor;
188
- }
189
- get froalaLoaded$() {
190
- return this._fr.loaded$;
191
- }
192
- ngOnInit() {
193
- this.config = this.config || {};
194
- this.config.autofocus = this.config.autofocus !== false && !this.config.disabled;
195
- this.initialized = !this.config.initOnClick;
196
- this._listenLazyInit();
197
- }
198
- ngAfterViewInit() {
199
- if (!this.config.initOnClick || !this.hasContent()) {
200
- this.initialized = true;
201
- this._initialize$.next();
202
- }
203
- }
204
- hasContent() {
205
- const el = document.createElement('div');
206
- if (el.querySelector('img')) {
207
- return true;
208
- }
209
- el.innerHTML = this._html;
210
- return !!el.innerText.length;
211
- }
212
- initialize(options = {}) {
213
- const config = this._createConfig();
214
- this._initPlugins(config);
215
- this._initButtons(config);
216
- this._editor = new this._fr.FroalaEditor(this.el, this._createOptions(), () => {
217
- this._froalaReady$.next({ config, options });
218
- });
219
- }
220
- _processImageUpload(blob) {
221
- const processor = new FileProcessor();
222
- const file = new FsFile(blob);
223
- return processor.process([file], this.config.image)
224
- .pipe(switchMap(([f]) => {
225
- return this.config.image.upload(f.file);
226
- }));
227
- }
228
- uninitializedClick(event) {
229
- if (!event.defaultPrevented) {
230
- const target = event.target;
231
- if (target && target.nodeName === 'A' && target.getAttribute('href')) {
232
- const targetTarget = target.getAttribute('target');
233
- target.setAttribute('target', '_blank');
234
- setTimeout(() => {
235
- if (targetTarget) {
236
- target.setAttribute('target', targetTarget);
237
- }
238
- else {
239
- target.removeAttribute('target');
240
- }
241
- });
242
- }
243
- else {
244
- if (this.config.initClick) {
245
- this.config.initClick(event);
246
- }
247
- this._initialize$.next();
248
- this.initialized = true;
249
- }
250
- }
251
- }
252
- updateSize() {
253
- // Hack: To trigger the toolbar button size modes
254
- window.dispatchEvent(new Event('resize'));
255
- }
256
- validate(control) {
257
- const err = {};
258
- if (this.config.maxLength && this._html) {
259
- const maxLength = this.config.maxLength;
260
- const length = this._html.length;
261
- if (length > maxLength) {
262
- err.maxLengthError = `Must be ${maxLength} characters or fewer. You entered ${length} characters.`;
263
- }
264
- }
265
- return Object.keys(err).length ? err : null;
266
- }
267
- focus(options) {
268
- options = options ? options : {};
269
- if (options.cursorPosition === 'end') {
270
- this.editor.selection.setAtEnd(this.editor.$el.get(0));
271
- }
272
- else {
273
- this.editor.selection.setAtStart(this.editor.$el.get(0));
274
- }
275
- this.editor.selection.restore();
276
- const elSelection = this.editor.selection.element();
277
- if (elSelection) {
278
- elSelection.scrollIntoView({ block: 'center' });
279
- }
280
- }
281
- clear() {
282
- this.writeValue('');
283
- }
284
- disable() {
285
- this.classDisabled = true;
286
- }
287
- setHtml(html) {
288
- this.writeValue(html);
289
- }
290
- writeValue(html) {
291
- this._html = html || '';
292
- if (Array.isArray(this._html)) {
293
- this._html = this._html.pop();
294
- }
295
- this._html = this._html
296
- .replace(/<(li)>\s?<(div)>/g, '<li>')
297
- .replace(/<\/(div)><\/(li)>/g, '</li>');
298
- if (this.editor && this.editor.html) {
299
- try {
300
- this.editor.html.set(this._html);
301
- }
302
- catch (e) {
303
- }
304
- }
305
- this._cdRef.markForCheck();
306
- }
307
- registerOnChange(fn) {
308
- this.onChange = fn;
309
- }
310
- registerOnTouched(fn) {
311
- this.onTouched = fn;
312
- }
313
- ngOnDestroy() {
314
- this._initialize$.complete();
315
- this._destroy$.next();
316
- this._destroy$.complete();
317
- this.destroy();
318
- }
319
- destroy() {
320
- if (this.editor) {
321
- this.editor.destroy();
322
- }
323
- this.initialized = false;
324
- this._cdRef.markForCheck();
325
- this.el.innerHTML = '';
326
- }
327
- _createConfig() {
328
- return merge({ froalaConfig: {} }, this._defaultConfig, this.config);
329
- }
330
- _change(html) {
331
- this._html = html;
332
- this.onChange(html);
333
- }
334
- _initButtons(config) {
335
- (config.buttons || [])
336
- .forEach((button) => {
337
- /*
338
- Svg Keys:
339
- ["add", "advancedImageEditor", "alignCenter", "alignJustify", "alignLeft", "alignRight",
340
- "anchors", "back", "backgroundColor", "blockquote", "bold", "cellBackground",
341
- "cellBorderColor", "cellOptions", "cellStyle", "clearFormatting", "close", "codeView",
342
- "cogs", "columns", "editLink", "exitFullscreen", "fontAwesome", "fontFamily",
343
- "fontSize", "fullscreen", "help", "horizontalLine", "imageAltText", "imageCaption",
344
- "imageClass", "imageDisplay", "imageManager", "imageSize", "indent", "inlineClass",
345
- "inlineStyle", "insertEmbed", "insertFile", "insertImage", "insertLink", "insertMore",
346
- "insertTable", "insertVideo", "upload", "italic", "search", "lineHeight", "linkStyles",
347
- "mention", "more", "openLink", "orderedList", "outdent", "pageBreaker",
348
- "paragraphFormat", "paragraphMore", "paragraphStyle", "pdfExport", "print",
349
- "redo", "removeTable", "remove", "replaceImage", "row", "selectAll", "smile",
350
- "spellcheck", "star", "strikeThrough", "subscript", "superscript", "symbols", "tags",
351
- "tableHeader", "tableStyle", "textColor", "textMore", "underline", "undo", "unlink",
352
- "unorderedList", "verticalAlignBottom", "verticalAlignMiddle", "verticalAlignTop"]
353
- */
354
- var _a, _b, _c;
355
- if (button.svgKey) {
356
- this._fr.FroalaEditor.DefineIcon(button.name, { SVG_KEY: button.svgKey });
357
- }
358
- this._fr.FroalaEditor.RegisterCommand(button.name, {
359
- title: button.title,
360
- focus: (_a = button.focus) !== null && _a !== void 0 ? _a : true,
361
- undo: (_b = button.undo) !== null && _b !== void 0 ? _b : true,
362
- refreshAfterCallback: (_c = button.refreshAfterCallback) !== null && _c !== void 0 ? _c : true,
363
- callback: function () {
364
- button.click(this);
365
- }
366
- });
367
- });
368
- }
369
- _initPlugins(config) {
370
- (config.plugins || []).forEach((plugin) => {
371
- this._fr.FroalaEditor.PLUGINS[plugin.config.name] = function (editor) {
372
- plugin.editor = editor;
373
- plugin.initialize();
374
- return plugin;
375
- };
376
- (plugin.config.buttons || []).forEach((button) => {
377
- this._fr.FroalaEditor.DefineIcon(button.name, {
378
- NAME: button.name,
379
- PATH: button.svgPath,
380
- });
381
- this._fr.FroalaEditor.RegisterCommand(button.name, {
382
- icon: button.name,
383
- title: button.tooltip,
384
- undo: button.undo,
385
- focus: button.focus,
386
- showOnMobile: button.showOnMobile,
387
- refreshAfterCallback: button.refreshAfterCallback,
388
- callback: function () {
389
- if (button.click) {
390
- button.click(this);
391
- }
392
- },
393
- refresh: function (button) {
394
- if (button.refresh) {
395
- button.refresh(this, button);
396
- }
397
- }
398
- });
399
- });
400
- });
401
- }
402
- _createOptions() {
403
- var _a, _b;
404
- const config = this._createConfig();
405
- return merge(
406
- // For some reason editor store somewhere pointer on default config object and dublicate options each time on init
407
- // Extra merge level fixed this problem and allow to init config properly without legacy data
408
- {}, {
409
- shortcutsEnabled: ['show', 'bold', 'italic', 'underline', 'indent', 'outdent', 'undo', 'redo', 'insertImage', 'createLink'],
410
- key: config.activationKey,
411
- placeholderText: config.placeholder,
412
- linkAlwaysBlank: true,
413
- tabSpaces: 2,
414
- typingTimer: 250,
415
- tooltips: false,
416
- wordPasteModal: false,
417
- imageDefaultWidth: 0,
418
- imageDefaultAlign: 'left',
419
- quickInsertEnabled: false,
420
- paragraphDefaultSelection: 'Format',
421
- videoUpload: false,
422
- imagePaste: !!((_a = config.image) === null || _a === void 0 ? void 0 : _a.upload),
423
- imageUpload: !!((_b = config.image) === null || _b === void 0 ? void 0 : _b.upload),
424
- paragraphFormat: {
425
- N: 'Normal',
426
- H1: 'Heading 1',
427
- H2: 'Heading 2',
428
- H3: 'Heading 3',
429
- H4: 'Heading 4',
430
- BLOCKQUOTE: 'Quote',
431
- },
432
- lineHeights: {
433
- Default: '',
434
- '0.5': '0.5',
435
- 'Single': '1',
436
- '1.15': '1.15',
437
- '1.5': '1.5',
438
- 'Double': '2'
439
- },
440
- paragraphFormatSelection: true,
441
- toolbarButtonsXS: {
442
- moreText: {
443
- buttons: TextButtons,
444
- buttonsVisible: 1,
445
- },
446
- moreParagraph: {
447
- buttons: ParagraphButtons,
448
- buttonsVisible: 2,
449
- },
450
- moreRich: {
451
- buttons: RichButtons,
452
- buttonsVisible: 0,
453
- },
454
- },
455
- toolbarButtons: {
456
- moreText: {
457
- buttons: TextButtons,
458
- buttonsVisible: 3,
459
- },
460
- moreParagraph: {
461
- buttons: ParagraphButtons,
462
- buttonsVisible: 5,
463
- },
464
- moreRich: {
465
- buttons: RichButtons,
466
- buttonsVisible: 3,
467
- },
468
- },
469
- }, config.froalaConfig);
470
- }
471
- _listenLazyInit() {
472
- this.froalaLoaded$
473
- .pipe(filter((ready) => ready), switchMap(() => this._initialize$), tap(() => {
474
- const selection = window.getSelection();
475
- const options = {};
476
- if (selection.baseNode) {
477
- options.selection = {
478
- node: selection.baseNode.nodeValue,
479
- offset: selection.baseOffset,
480
- };
481
- }
482
- this.initialize(options);
483
- }), switchMap(() => this._froalaReady$), filter((data) => !!data), tap(({ config, options }) => {
484
- this._setupFroala(config, options);
485
- }))
486
- .subscribe();
487
- }
488
- _contentChanged() {
489
- const editorHTML = this._editor.html.get();
490
- if (this.html !== editorHTML) {
491
- this._change(editorHTML);
492
- }
493
- }
494
- _setupFroala(config, options) {
495
- this._cdRef.markForCheck();
496
- this.setHtml(this._html);
497
- if (config.disabled) {
498
- this.disable();
499
- }
500
- if (config.froalaConfig.events) {
501
- if (config.froalaConfig.events.initialized) {
502
- config.froalaConfig.events.initialized();
503
- }
504
- }
505
- this._editor.events.on('focus', () => {
506
- this.classFocused = true;
507
- this._cdRef.markForCheck();
508
- });
509
- this._editor.events.on('blur', () => {
510
- this.classFocused = false;
511
- this._cdRef.markForCheck();
512
- });
513
- fromEventPattern((handler) => {
514
- this._editor.events.on('contentChanged', handler);
515
- }, () => { })
516
- .pipe(startWith(this._html), map(() => this.editor.html.get()), distinctUntilChanged(), skip(1))
517
- .subscribe(() => {
518
- this._contentChanged();
519
- });
520
- // this._editor.events.on('contentChanged', () => {
521
- // console.log('test');
522
- // if (!this._firstChange) {
523
- // this._contentChanged();
524
- // }
525
- // });
526
- this._editor.events.on('paste.afterCleanup', (html) => {
527
- var div = document.createElement('div');
528
- div.innerHTML = html;
529
- div.querySelectorAll('*')
530
- .forEach((el) => {
531
- for (var i = 0; i < el.attributes.length; i++) {
532
- const name = el.attributes[0].name;
533
- if (name !== 'href') {
534
- el.removeAttribute(name);
535
- }
536
- }
537
- });
538
- return div.innerHTML;
539
- });
540
- this._editor.events.on('keydown', () => {
541
- this.onTouched();
542
- });
543
- if (this.config.image && this.config.image.upload) {
544
- this._editor.events.on('image.beforePasteUpload', (image) => {
545
- fetch(image.getAttribute('src'))
546
- .then((res) => {
547
- res.blob()
548
- .then((blob) => {
549
- this._processImageUpload(blob)
550
- .pipe(takeUntil(this._destroy$))
551
- .subscribe((url) => {
552
- image.setAttribute('src', url);
553
- image.removeAttribute('data-fr-image-pasted');
554
- this._contentChanged();
555
- });
556
- });
557
- });
558
- return false;
559
- });
560
- this._editor.events.on('image.beforeUpload', (blobs) => {
561
- this._processImageUpload(blobs[0])
562
- .pipe(takeUntil(this._destroy$))
563
- .subscribe((url) => {
564
- this.editor.image.insert(url, null, null, this.editor.image.get());
565
- });
566
- return false;
567
- });
568
- }
569
- if (this.el.querySelector('.fr-second-toolbar')) {
570
- this.el.querySelector('.fr-second-toolbar').remove();
571
- }
572
- const selection = options.selection;
573
- if (selection) {
574
- const node = Array.from(this.el.querySelectorAll('.fr-element *')).find((node) => {
575
- return selection.node === node.textContent;
576
- });
577
- if (node) {
578
- const range = document.createRange();
579
- const sel = window.getSelection();
580
- range.setStart(this._getTextNode(node), selection.offset);
581
- range.collapse(true);
582
- sel.removeAllRanges();
583
- sel.addRange(range);
584
- }
585
- else if (this.config.autofocus) {
586
- this.focus();
587
- }
588
- }
589
- else if (this.config.autofocus) {
590
- this.focus();
591
- }
592
- }
593
- _getTextNode(node) {
594
- if (node) {
595
- if (node.nodeType === Node.TEXT_NODE) {
596
- return node;
597
- }
598
- if (node.childNodes) {
599
- return this._getTextNode(node.childNodes[0]);
600
- }
601
- }
602
- }
603
- }
604
- FsHtmlEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorComponent, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: i0.ChangeDetectorRef }, { token: FsFroalaLoaderService }], target: i0.ɵɵFactoryTarget.Component });
605
- FsHtmlEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FsHtmlEditorComponent, selector: "fs-html-editor", inputs: { config: "config" }, host: { properties: { "class.focused": "this.classFocused", "class.disabled": "this.classDisabled" } }, providers: [
606
- {
607
- provide: NG_VALUE_ACCESSOR,
608
- useExisting: forwardRef(() => FsHtmlEditorComponent),
609
- multi: true
610
- },
611
- {
612
- provide: NG_VALIDATORS,
613
- useExisting: forwardRef(() => FsHtmlEditorComponent),
614
- multi: true
615
- },
616
- ], viewQueries: [{ propertyName: "elRef", first: true, predicate: ["elRef"], descendants: true }], ngImport: i0, template: "<fs-label-field>\n <fs-label *ngIf=\"config.label\">{{config.label}}</fs-label>\n <div class=\"fs-html-editor-default\">\n <ng-container *ngIf=\"initialized\">\n <ng-container *fsSkeleton=\"(froalaLoaded$ | async) !== false\">\n </ng-container>\n </ng-container>\n \n <div #elRef></div>\n \n <div class=\"bottom-line\"></div>\n <div class=\"disabled-line\"></div>\n <fs-html-renderer\n *ngIf=\"!initialized\"\n [html]=\"html\"\n (click)=\"uninitializedClick($event)\">\n </fs-html-renderer>\n </div>\n \n <fs-label-message>\n <div class=\"fs-form-message\"></div>\n </fs-label-message>\n</fs-label-field>\n", styles: [":host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper{transition:none!important}:host ::ng-deep .fr-toolbar-open .fr-more-toolbar{display:block}:host ::ng-deep .fr-more-toolbar{display:none}:host ::ng-deep .fr-toolbar.fr-top{position:sticky;z-index:2;border-radius:0;background-color:#fff}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp{margin:0 20px 0 0}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar.fr-top div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-top.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top.fr-top{border:0}:host ::ng-deep .fr-toolbar.fr-top .fr-newline{margin:0}:host ::ng-deep .fr-toolbar.fr-top .fr-more-toolbar{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}:host.disabled ::ng-deep .disabled-line{display:block}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}.disabled-line{display:none;position:absolute;bottom:-1px;z-index:1;background-image:linear-gradient(90deg,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);background-size:4px 100%;background-repeat:repeat-x;height:1px;width:100%}.bottom-line{opacity:0;transform-origin:50%;transform:scaleX(.5);transition:background-color .3s cubic-bezier(.55,0,.55,.2);width:100%;border-bottom:2px solid #949494;position:absolute;bottom:-1px;z-index:1}:host{position:relative;display:block}:host.focused .bottom-line{opacity:1;display:block;transform:scaleX(1);transition:transform .3s cubic-bezier(.25,.8,.25,1),opacity .1s cubic-bezier(.25,.8,.25,1),background-color .3s cubic-bezier(.25,.8,.25,1)}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#F5F5F5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}\n"], components: [{ type: i2.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["bottomMargin", "topMargin", "labelMargin"] }, { type: i2.FsLabelComponent, selector: "fs-label" }, { type: FsHtmlRendererComponent, selector: "fs-html-renderer", inputs: ["html"] }, { type: i2.FsLabelMessageComponent, selector: "fs-label-message" }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
617
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorComponent, decorators: [{
618
- type: Component,
619
- args: [{
620
- selector: 'fs-html-editor',
621
- templateUrl: 'html-editor.component.html',
622
- styleUrls: ['html-editor.component.scss'],
623
- providers: [
624
- {
625
- provide: NG_VALUE_ACCESSOR,
626
- useExisting: forwardRef(() => FsHtmlEditorComponent),
627
- multi: true
628
- },
629
- {
630
- provide: NG_VALIDATORS,
631
- useExisting: forwardRef(() => FsHtmlEditorComponent),
632
- multi: true
633
- },
634
- ],
635
- changeDetection: ChangeDetectionStrategy.OnPush,
636
- }]
637
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
638
- type: Optional
639
- }, {
640
- type: Inject,
641
- args: [FS_HTML_EDITOR_CONFIG]
642
- }] }, { type: i0.ChangeDetectorRef }, { type: FsFroalaLoaderService }]; }, propDecorators: { classFocused: [{
643
- type: HostBinding,
644
- args: ['class.focused']
645
- }], classDisabled: [{
646
- type: HostBinding,
647
- args: ['class.disabled']
648
- }], elRef: [{
649
- type: ViewChild,
650
- args: ['elRef']
651
- }], config: [{
652
- type: Input
165
+ class FsHtmlEditorComponent {
166
+ constructor(_defaultConfig, _cdRef, _fr) {
167
+ this._defaultConfig = _defaultConfig;
168
+ this._cdRef = _cdRef;
169
+ this._fr = _fr;
170
+ this.classFocused = false;
171
+ this.classDisabled = false;
172
+ this.config = {};
173
+ this.initialized = false;
174
+ this._initialize$ = new ReplaySubject();
175
+ this._froalaReady$ = new BehaviorSubject(null);
176
+ this._destroy$ = new Subject();
177
+ this.onChange = (data) => { };
178
+ this.onTouched = () => { };
179
+ }
180
+ get el() {
181
+ return this.elRef.nativeElement;
182
+ }
183
+ get html() {
184
+ return this._html;
185
+ }
186
+ get editor() {
187
+ return this._editor;
188
+ }
189
+ get froalaLoaded$() {
190
+ return this._fr.loaded$;
191
+ }
192
+ ngOnInit() {
193
+ this.config = this.config || {};
194
+ this.config.autofocus = this.config.autofocus !== false && !this.config.disabled;
195
+ this.initialized = !this.config.initOnClick;
196
+ this._listenLazyInit();
197
+ }
198
+ ngAfterViewInit() {
199
+ if (!this.config.initOnClick || !this.hasContent()) {
200
+ this.initialized = true;
201
+ this._initialize$.next();
202
+ }
203
+ }
204
+ hasContent() {
205
+ const el = document.createElement('div');
206
+ if (el.querySelector('img')) {
207
+ return true;
208
+ }
209
+ el.innerHTML = this._html;
210
+ return !!el.innerText.length;
211
+ }
212
+ initialize(options = {}) {
213
+ const config = this._createConfig();
214
+ this._initPlugins(config);
215
+ this._initButtons(config);
216
+ this._editor = new this._fr.FroalaEditor(this.el, this._createOptions(), () => {
217
+ this._froalaReady$.next({ config, options });
218
+ });
219
+ }
220
+ _processImageUpload(blob) {
221
+ const processor = new FileProcessor();
222
+ const file = new FsFile(blob);
223
+ const config = {
224
+ orientate: true,
225
+ quality: this.config.image.quality,
226
+ format: this.config.image.format,
227
+ maxWidth: this.config.image.width,
228
+ maxHeight: this.config.image.height,
229
+ minWidth: this.config.image.minWidth,
230
+ minHeight: this.config.image.minHeight,
231
+ };
232
+ return processor.processFile(file, config)
233
+ .pipe(switchMap((fsFile) => {
234
+ return this.config.image.upload(fsFile.file);
235
+ }));
236
+ }
237
+ uninitializedClick(event) {
238
+ if (!event.defaultPrevented) {
239
+ const target = event.target;
240
+ if (target && target.nodeName === 'A' && target.getAttribute('href')) {
241
+ const targetTarget = target.getAttribute('target');
242
+ target.setAttribute('target', '_blank');
243
+ setTimeout(() => {
244
+ if (targetTarget) {
245
+ target.setAttribute('target', targetTarget);
246
+ }
247
+ else {
248
+ target.removeAttribute('target');
249
+ }
250
+ });
251
+ }
252
+ else {
253
+ if (this.config.initClick) {
254
+ this.config.initClick(event);
255
+ }
256
+ this._initialize$.next();
257
+ this.initialized = true;
258
+ }
259
+ }
260
+ }
261
+ updateSize() {
262
+ // Hack: To trigger the toolbar button size modes
263
+ window.dispatchEvent(new Event('resize'));
264
+ }
265
+ validate(control) {
266
+ const err = {};
267
+ if (this.config.maxLength && this._html) {
268
+ const maxLength = this.config.maxLength;
269
+ const length = this._html.length;
270
+ if (length > maxLength) {
271
+ err.maxLengthError = `Must be ${maxLength} characters or fewer. You entered ${length} characters.`;
272
+ }
273
+ }
274
+ return Object.keys(err).length ? err : null;
275
+ }
276
+ focus(options) {
277
+ options = options ? options : {};
278
+ if (options.cursorPosition === 'end') {
279
+ this.editor.selection.setAtEnd(this.editor.$el.get(0));
280
+ }
281
+ else {
282
+ this.editor.selection.setAtStart(this.editor.$el.get(0));
283
+ }
284
+ this.editor.selection.restore();
285
+ const elSelection = this.editor.selection.element();
286
+ if (elSelection) {
287
+ elSelection.scrollIntoView({ block: 'center' });
288
+ }
289
+ }
290
+ clear() {
291
+ this.writeValue('');
292
+ }
293
+ disable() {
294
+ this.classDisabled = true;
295
+ }
296
+ setHtml(html) {
297
+ this.writeValue(html);
298
+ }
299
+ writeValue(html) {
300
+ this._html = html || '';
301
+ if (Array.isArray(this._html)) {
302
+ this._html = this._html.pop();
303
+ }
304
+ this._html = this._html
305
+ .replace(/<(li)>\s?<(div)>/g, '<li>')
306
+ .replace(/<\/(div)><\/(li)>/g, '</li>');
307
+ if (this.editor && this.editor.html) {
308
+ try {
309
+ this.editor.html.set(this._html);
310
+ }
311
+ catch (e) {
312
+ }
313
+ }
314
+ this._cdRef.markForCheck();
315
+ }
316
+ registerOnChange(fn) {
317
+ this.onChange = fn;
318
+ }
319
+ registerOnTouched(fn) {
320
+ this.onTouched = fn;
321
+ }
322
+ ngOnDestroy() {
323
+ this._initialize$.complete();
324
+ this._destroy$.next();
325
+ this._destroy$.complete();
326
+ this.destroy();
327
+ }
328
+ destroy() {
329
+ if (this.editor) {
330
+ this.editor.destroy();
331
+ }
332
+ this.initialized = false;
333
+ this._cdRef.markForCheck();
334
+ this.el.innerHTML = '';
335
+ }
336
+ _createConfig() {
337
+ return merge({ froalaConfig: {} }, this._defaultConfig, this.config);
338
+ }
339
+ _change(html) {
340
+ this._html = html;
341
+ this.onChange(html);
342
+ }
343
+ _initButtons(config) {
344
+ (config.buttons || [])
345
+ .forEach((button) => {
346
+ /*
347
+ Svg Keys:
348
+ ["add", "advancedImageEditor", "alignCenter", "alignJustify", "alignLeft", "alignRight",
349
+ "anchors", "back", "backgroundColor", "blockquote", "bold", "cellBackground",
350
+ "cellBorderColor", "cellOptions", "cellStyle", "clearFormatting", "close", "codeView",
351
+ "cogs", "columns", "editLink", "exitFullscreen", "fontAwesome", "fontFamily",
352
+ "fontSize", "fullscreen", "help", "horizontalLine", "imageAltText", "imageCaption",
353
+ "imageClass", "imageDisplay", "imageManager", "imageSize", "indent", "inlineClass",
354
+ "inlineStyle", "insertEmbed", "insertFile", "insertImage", "insertLink", "insertMore",
355
+ "insertTable", "insertVideo", "upload", "italic", "search", "lineHeight", "linkStyles",
356
+ "mention", "more", "openLink", "orderedList", "outdent", "pageBreaker",
357
+ "paragraphFormat", "paragraphMore", "paragraphStyle", "pdfExport", "print",
358
+ "redo", "removeTable", "remove", "replaceImage", "row", "selectAll", "smile",
359
+ "spellcheck", "star", "strikeThrough", "subscript", "superscript", "symbols", "tags",
360
+ "tableHeader", "tableStyle", "textColor", "textMore", "underline", "undo", "unlink",
361
+ "unorderedList", "verticalAlignBottom", "verticalAlignMiddle", "verticalAlignTop"]
362
+ */
363
+ var _a, _b, _c;
364
+ if (button.svgKey) {
365
+ this._fr.FroalaEditor.DefineIcon(button.name, { SVG_KEY: button.svgKey });
366
+ }
367
+ this._fr.FroalaEditor.RegisterCommand(button.name, {
368
+ title: button.title,
369
+ focus: (_a = button.focus) !== null && _a !== void 0 ? _a : true,
370
+ undo: (_b = button.undo) !== null && _b !== void 0 ? _b : true,
371
+ refreshAfterCallback: (_c = button.refreshAfterCallback) !== null && _c !== void 0 ? _c : true,
372
+ callback: function () {
373
+ button.click(this);
374
+ }
375
+ });
376
+ });
377
+ }
378
+ _initPlugins(config) {
379
+ (config.plugins || []).forEach((plugin) => {
380
+ this._fr.FroalaEditor.PLUGINS[plugin.config.name] = function (editor) {
381
+ plugin.editor = editor;
382
+ plugin.initialize();
383
+ return plugin;
384
+ };
385
+ (plugin.config.buttons || []).forEach((button) => {
386
+ this._fr.FroalaEditor.DefineIcon(button.name, {
387
+ NAME: button.name,
388
+ PATH: button.svgPath,
389
+ });
390
+ this._fr.FroalaEditor.RegisterCommand(button.name, {
391
+ icon: button.name,
392
+ title: button.tooltip,
393
+ undo: button.undo,
394
+ focus: button.focus,
395
+ showOnMobile: button.showOnMobile,
396
+ refreshAfterCallback: button.refreshAfterCallback,
397
+ callback: function () {
398
+ if (button.click) {
399
+ button.click(this);
400
+ }
401
+ },
402
+ refresh: function (button) {
403
+ if (button.refresh) {
404
+ button.refresh(this, button);
405
+ }
406
+ }
407
+ });
408
+ });
409
+ });
410
+ }
411
+ _createOptions() {
412
+ var _a, _b;
413
+ const config = this._createConfig();
414
+ return merge(
415
+ // For some reason editor store somewhere pointer on default config object and dublicate options each time on init
416
+ // Extra merge level fixed this problem and allow to init config properly without legacy data
417
+ {}, {
418
+ shortcutsEnabled: ['show', 'bold', 'italic', 'underline', 'indent', 'outdent', 'undo', 'redo', 'insertImage', 'createLink'],
419
+ key: config.activationKey,
420
+ placeholderText: config.placeholder,
421
+ linkAlwaysBlank: true,
422
+ tabSpaces: 2,
423
+ typingTimer: 250,
424
+ tooltips: false,
425
+ wordPasteModal: false,
426
+ imageDefaultWidth: 0,
427
+ imageDefaultAlign: 'left',
428
+ quickInsertEnabled: false,
429
+ paragraphDefaultSelection: 'Format',
430
+ videoUpload: false,
431
+ imagePaste: !!((_a = config.image) === null || _a === void 0 ? void 0 : _a.upload),
432
+ imageUpload: !!((_b = config.image) === null || _b === void 0 ? void 0 : _b.upload),
433
+ paragraphFormat: {
434
+ N: 'Normal',
435
+ H1: 'Heading 1',
436
+ H2: 'Heading 2',
437
+ H3: 'Heading 3',
438
+ H4: 'Heading 4',
439
+ BLOCKQUOTE: 'Quote',
440
+ },
441
+ lineHeights: {
442
+ Default: '',
443
+ '0.5': '0.5',
444
+ 'Single': '1',
445
+ '1.15': '1.15',
446
+ '1.5': '1.5',
447
+ 'Double': '2'
448
+ },
449
+ paragraphFormatSelection: true,
450
+ toolbarButtonsXS: {
451
+ moreText: {
452
+ buttons: TextButtons,
453
+ buttonsVisible: 1,
454
+ },
455
+ moreParagraph: {
456
+ buttons: ParagraphButtons,
457
+ buttonsVisible: 2,
458
+ },
459
+ moreRich: {
460
+ buttons: RichButtons,
461
+ buttonsVisible: 0,
462
+ },
463
+ },
464
+ toolbarButtons: {
465
+ moreText: {
466
+ buttons: TextButtons,
467
+ buttonsVisible: 3,
468
+ },
469
+ moreParagraph: {
470
+ buttons: ParagraphButtons,
471
+ buttonsVisible: 5,
472
+ },
473
+ moreRich: {
474
+ buttons: RichButtons,
475
+ buttonsVisible: 3,
476
+ },
477
+ },
478
+ }, config.froalaConfig);
479
+ }
480
+ _listenLazyInit() {
481
+ this.froalaLoaded$
482
+ .pipe(filter((ready) => ready), switchMap(() => this._initialize$), tap(() => {
483
+ const selection = window.getSelection();
484
+ const options = {};
485
+ if (selection.baseNode) {
486
+ options.selection = {
487
+ node: selection.baseNode.nodeValue,
488
+ offset: selection.baseOffset,
489
+ };
490
+ }
491
+ this.initialize(options);
492
+ }), switchMap(() => this._froalaReady$), filter((data) => !!data), tap(({ config, options }) => {
493
+ this._setupFroala(config, options);
494
+ }))
495
+ .subscribe();
496
+ }
497
+ _contentChanged() {
498
+ const editorHTML = this._editor.html.get();
499
+ if (this.html !== editorHTML) {
500
+ this._change(editorHTML);
501
+ }
502
+ }
503
+ _setupFroala(config, options) {
504
+ this._cdRef.markForCheck();
505
+ this.setHtml(this._html);
506
+ if (config.disabled) {
507
+ this.disable();
508
+ }
509
+ if (config.froalaConfig.events) {
510
+ if (config.froalaConfig.events.initialized) {
511
+ config.froalaConfig.events.initialized();
512
+ }
513
+ }
514
+ this._editor.events.on('focus', () => {
515
+ this.classFocused = true;
516
+ this._cdRef.markForCheck();
517
+ });
518
+ this._editor.events.on('blur', () => {
519
+ this.classFocused = false;
520
+ this._cdRef.markForCheck();
521
+ });
522
+ fromEventPattern((handler) => {
523
+ this._editor.events.on('contentChanged', handler);
524
+ }, () => { })
525
+ .pipe(startWith(this._html), map(() => this.editor.html.get()), distinctUntilChanged(), skip(1))
526
+ .subscribe(() => {
527
+ this._contentChanged();
528
+ });
529
+ // this._editor.events.on('contentChanged', () => {
530
+ // console.log('test');
531
+ // if (!this._firstChange) {
532
+ // this._contentChanged();
533
+ // }
534
+ // });
535
+ this._editor.events.on('paste.afterCleanup', (html) => {
536
+ var div = document.createElement('div');
537
+ div.innerHTML = html;
538
+ div.querySelectorAll('*')
539
+ .forEach((el) => {
540
+ for (var i = 0; i < el.attributes.length; i++) {
541
+ const name = el.attributes[0].name;
542
+ if (name !== 'href') {
543
+ el.removeAttribute(name);
544
+ }
545
+ }
546
+ });
547
+ return div.innerHTML;
548
+ });
549
+ this._editor.events.on('keydown', () => {
550
+ this.onTouched();
551
+ });
552
+ if (this.config.image && this.config.image.upload) {
553
+ this._editor.events.on('image.beforePasteUpload', (image) => {
554
+ fetch(image.getAttribute('src'))
555
+ .then((res) => {
556
+ res.blob()
557
+ .then((blob) => {
558
+ this._processImageUpload(blob)
559
+ .pipe(takeUntil(this._destroy$))
560
+ .subscribe((url) => {
561
+ image.setAttribute('src', url);
562
+ image.removeAttribute('data-fr-image-pasted');
563
+ this._contentChanged();
564
+ });
565
+ });
566
+ });
567
+ return false;
568
+ });
569
+ this._editor.events.on('image.beforeUpload', (blobs) => {
570
+ this._processImageUpload(blobs[0])
571
+ .pipe(takeUntil(this._destroy$))
572
+ .subscribe((url) => {
573
+ this.editor.image.insert(url, null, null, this.editor.image.get());
574
+ });
575
+ return false;
576
+ });
577
+ }
578
+ if (this.el.querySelector('.fr-second-toolbar')) {
579
+ this.el.querySelector('.fr-second-toolbar').remove();
580
+ }
581
+ const selection = options.selection;
582
+ if (selection) {
583
+ const node = Array.from(this.el.querySelectorAll('.fr-element *')).find((node) => {
584
+ return selection.node === node.textContent;
585
+ });
586
+ if (node) {
587
+ const range = document.createRange();
588
+ const sel = window.getSelection();
589
+ range.setStart(this._getTextNode(node), selection.offset);
590
+ range.collapse(true);
591
+ sel.removeAllRanges();
592
+ sel.addRange(range);
593
+ }
594
+ else if (this.config.autofocus) {
595
+ this.focus();
596
+ }
597
+ }
598
+ else if (this.config.autofocus) {
599
+ this.focus();
600
+ }
601
+ }
602
+ _getTextNode(node) {
603
+ if (node) {
604
+ if (node.nodeType === Node.TEXT_NODE) {
605
+ return node;
606
+ }
607
+ if (node.childNodes) {
608
+ return this._getTextNode(node.childNodes[0]);
609
+ }
610
+ }
611
+ }
612
+ }
613
+ FsHtmlEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorComponent, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: i0.ChangeDetectorRef }, { token: FsFroalaLoaderService }], target: i0.ɵɵFactoryTarget.Component });
614
+ FsHtmlEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FsHtmlEditorComponent, selector: "fs-html-editor", inputs: { config: "config" }, host: { properties: { "class.focused": "this.classFocused", "class.disabled": "this.classDisabled" } }, providers: [
615
+ {
616
+ provide: NG_VALUE_ACCESSOR,
617
+ useExisting: forwardRef(() => FsHtmlEditorComponent),
618
+ multi: true
619
+ },
620
+ {
621
+ provide: NG_VALIDATORS,
622
+ useExisting: forwardRef(() => FsHtmlEditorComponent),
623
+ multi: true
624
+ },
625
+ ], viewQueries: [{ propertyName: "elRef", first: true, predicate: ["elRef"], descendants: true }], ngImport: i0, template: "<fs-label-field>\n <fs-label *ngIf=\"config.label\">{{config.label}}</fs-label>\n <div class=\"fs-html-editor-default\">\n <ng-container *ngIf=\"initialized\">\n <ng-container *fsSkeleton=\"(froalaLoaded$ | async) !== false\">\n </ng-container>\n </ng-container>\n \n <div #elRef></div>\n \n <div class=\"bottom-line\"></div>\n <div class=\"disabled-line\"></div>\n <fs-html-renderer\n *ngIf=\"!initialized\"\n [html]=\"html\"\n (click)=\"uninitializedClick($event)\">\n </fs-html-renderer>\n </div>\n \n <fs-label-message>\n <div class=\"fs-form-message\"></div>\n </fs-label-message>\n</fs-label-field>\n", styles: [":host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper{transition:none!important}:host ::ng-deep .fr-toolbar-open .fr-more-toolbar{display:block}:host ::ng-deep .fr-more-toolbar{display:none}:host ::ng-deep .fr-toolbar.fr-top{position:sticky;z-index:2;border-radius:0;background-color:#fff}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp{margin:0 20px 0 0}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar.fr-top div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-top.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top.fr-top{border:0}:host ::ng-deep .fr-toolbar.fr-top .fr-newline{margin:0}:host ::ng-deep .fr-toolbar.fr-top .fr-more-toolbar{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}:host.disabled ::ng-deep .disabled-line{display:block}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}.disabled-line{display:none;position:absolute;bottom:-1px;z-index:1;background-image:linear-gradient(90deg,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);background-size:4px 100%;background-repeat:repeat-x;height:1px;width:100%}.bottom-line{opacity:0;transform-origin:50%;transform:scaleX(.5);transition:background-color .3s cubic-bezier(.55,0,.55,.2);width:100%;border-bottom:2px solid #949494;position:absolute;bottom:-1px;z-index:1}:host{position:relative;display:block}:host.focused .bottom-line{opacity:1;display:block;transform:scaleX(1);transition:transform .3s cubic-bezier(.25,.8,.25,1),opacity .1s cubic-bezier(.25,.8,.25,1),background-color .3s cubic-bezier(.25,.8,.25,1)}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#F5F5F5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}\n"], components: [{ type: i2.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["bottomMargin", "topMargin", "labelMargin"] }, { type: i2.FsLabelComponent, selector: "fs-label" }, { type: FsHtmlRendererComponent, selector: "fs-html-renderer", inputs: ["html"] }, { type: i2.FsLabelMessageComponent, selector: "fs-label-message" }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }], pipes: { "async": i4.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
626
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorComponent, decorators: [{
627
+ type: Component,
628
+ args: [{
629
+ selector: 'fs-html-editor',
630
+ templateUrl: 'html-editor.component.html',
631
+ styleUrls: ['html-editor.component.scss'],
632
+ providers: [
633
+ {
634
+ provide: NG_VALUE_ACCESSOR,
635
+ useExisting: forwardRef(() => FsHtmlEditorComponent),
636
+ multi: true
637
+ },
638
+ {
639
+ provide: NG_VALIDATORS,
640
+ useExisting: forwardRef(() => FsHtmlEditorComponent),
641
+ multi: true
642
+ },
643
+ ],
644
+ changeDetection: ChangeDetectionStrategy.OnPush,
645
+ }]
646
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
647
+ type: Optional
648
+ }, {
649
+ type: Inject,
650
+ args: [FS_HTML_EDITOR_CONFIG]
651
+ }] }, { type: i0.ChangeDetectorRef }, { type: FsFroalaLoaderService }]; }, propDecorators: { classFocused: [{
652
+ type: HostBinding,
653
+ args: ['class.focused']
654
+ }], classDisabled: [{
655
+ type: HostBinding,
656
+ args: ['class.disabled']
657
+ }], elRef: [{
658
+ type: ViewChild,
659
+ args: ['elRef']
660
+ }], config: [{
661
+ type: Input
653
662
  }] } });
654
663
 
655
- class FsHtmlRendererModule {
656
- }
657
- FsHtmlRendererModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
658
- FsHtmlRendererModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererModule, declarations: [FsHtmlRendererComponent], imports: [CommonModule], exports: [FsHtmlRendererComponent] });
659
- FsHtmlRendererModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererModule, imports: [[
660
- CommonModule,
661
- ]] });
662
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererModule, decorators: [{
663
- type: NgModule,
664
- args: [{
665
- imports: [
666
- CommonModule,
667
- ],
668
- exports: [
669
- FsHtmlRendererComponent,
670
- ],
671
- declarations: [
672
- FsHtmlRendererComponent,
673
- ],
674
- }]
664
+ class FsHtmlRendererModule {
665
+ }
666
+ FsHtmlRendererModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
667
+ FsHtmlRendererModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererModule, declarations: [FsHtmlRendererComponent], imports: [CommonModule], exports: [FsHtmlRendererComponent] });
668
+ FsHtmlRendererModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererModule, imports: [[
669
+ CommonModule,
670
+ ]] });
671
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlRendererModule, decorators: [{
672
+ type: NgModule,
673
+ args: [{
674
+ imports: [
675
+ CommonModule,
676
+ ],
677
+ exports: [
678
+ FsHtmlRendererComponent,
679
+ ],
680
+ declarations: [
681
+ FsHtmlRendererComponent,
682
+ ],
683
+ }]
675
684
  }] });
676
685
 
677
- class FsHtmlEditorModule {
678
- static forRoot(config = {}) {
679
- return {
680
- ngModule: FsHtmlEditorModule,
681
- providers: [
682
- { provide: FS_HTML_EDITOR_DEFAULT_CONFIG, useValue: config },
683
- {
684
- provide: FS_HTML_EDITOR_CONFIG,
685
- useFactory: FsHtmlEditorConfigFactory,
686
- deps: [FS_HTML_EDITOR_DEFAULT_CONFIG]
687
- }
688
- ]
689
- };
690
- }
691
- }
692
- FsHtmlEditorModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
693
- FsHtmlEditorModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorModule, declarations: [FsHtmlEditorComponent], imports: [CommonModule,
694
- FsSkeletonModule,
695
- FsLabelModule,
696
- FsHtmlRendererModule], exports: [FsHtmlEditorComponent] });
697
- FsHtmlEditorModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorModule, imports: [[
698
- CommonModule,
699
- FsSkeletonModule,
700
- FsLabelModule,
701
- FsHtmlRendererModule,
702
- ]] });
703
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorModule, decorators: [{
704
- type: NgModule,
705
- args: [{
706
- imports: [
707
- CommonModule,
708
- FsSkeletonModule,
709
- FsLabelModule,
710
- FsHtmlRendererModule,
711
- ],
712
- exports: [
713
- FsHtmlEditorComponent,
714
- ],
715
- declarations: [
716
- FsHtmlEditorComponent,
717
- ],
718
- }]
719
- }] });
720
- function FsHtmlEditorConfigFactory(config) {
721
- return Object.assign({ froalaPlugins: [
722
- "align" /* Align */,
723
- "colors" /* Colors */,
724
- "image" /* Image */,
725
- "link" /* Link */,
726
- "lists" /* Lists */,
727
- "paragraph_format" /* ParagraphFormat */,
728
- "quote" /* Quote */,
729
- "table" /* Table */,
730
- "url" /* Url */,
731
- "video" /* Video */,
732
- "draggable" /* Draggable */,
733
- "font_size" /* FontSize */,
734
- "line_height" /* LineHeight */,
735
- ] }, config);
686
+ class FsHtmlEditorModule {
687
+ static forRoot(config = {}) {
688
+ return {
689
+ ngModule: FsHtmlEditorModule,
690
+ providers: [
691
+ { provide: FS_HTML_EDITOR_DEFAULT_CONFIG, useValue: config },
692
+ {
693
+ provide: FS_HTML_EDITOR_CONFIG,
694
+ useFactory: FsHtmlEditorConfigFactory,
695
+ deps: [FS_HTML_EDITOR_DEFAULT_CONFIG]
696
+ }
697
+ ]
698
+ };
699
+ }
700
+ }
701
+ FsHtmlEditorModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
702
+ FsHtmlEditorModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorModule, declarations: [FsHtmlEditorComponent], imports: [CommonModule,
703
+ FsSkeletonModule,
704
+ FsLabelModule,
705
+ FsHtmlRendererModule], exports: [FsHtmlEditorComponent] });
706
+ FsHtmlEditorModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorModule, imports: [[
707
+ CommonModule,
708
+ FsSkeletonModule,
709
+ FsLabelModule,
710
+ FsHtmlRendererModule,
711
+ ]] });
712
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorModule, decorators: [{
713
+ type: NgModule,
714
+ args: [{
715
+ imports: [
716
+ CommonModule,
717
+ FsSkeletonModule,
718
+ FsLabelModule,
719
+ FsHtmlRendererModule,
720
+ ],
721
+ exports: [
722
+ FsHtmlEditorComponent,
723
+ ],
724
+ declarations: [
725
+ FsHtmlEditorComponent,
726
+ ],
727
+ }]
728
+ }] });
729
+ function FsHtmlEditorConfigFactory(config) {
730
+ return Object.assign({ froalaPlugins: [
731
+ "align" /* Align */,
732
+ "colors" /* Colors */,
733
+ "image" /* Image */,
734
+ "link" /* Link */,
735
+ "lists" /* Lists */,
736
+ "paragraph_format" /* ParagraphFormat */,
737
+ "quote" /* Quote */,
738
+ "table" /* Table */,
739
+ "url" /* Url */,
740
+ "video" /* Video */,
741
+ "draggable" /* Draggable */,
742
+ "font_size" /* FontSize */,
743
+ "line_height" /* LineHeight */,
744
+ ] }, config);
736
745
  }
737
746
 
738
- class Plugin {
739
- initialize() { }
740
- destroy() { }
747
+ class Plugin {
748
+ initialize() { }
749
+ destroy() { }
741
750
  }
742
751
 
743
- class MentionPlugin extends Plugin {
744
- constructor(config) {
745
- super();
746
- this.config = config;
747
- this._guid = guid();
748
- this.selected = (event) => {
749
- if (this.config.selected) {
750
- if (MentionPlugin._currentGuid === this._guid) {
751
- this.config.selected(event.detail.item.original);
752
- }
753
- }
754
- };
755
- this.config = Object.assign(Object.assign({}, config), { buttons: [
756
- {
757
- name: config.name,
758
- tooltip: config.tooltip,
759
- svgPath: config.iconPath,
760
- click: (editor) => {
761
- this._closeAll();
762
- this._tribute.showMenuForCollection(editor.el);
763
- }
764
- }
765
- ] });
766
- this._tribute = new Tribute({
767
- values: debounce(this._loadValues.bind(this), 200),
768
- searchOpts: {
769
- pre: '',
770
- post: '',
771
- skip: true
772
- },
773
- containerClass: `fs-html-editor-mention-container ${this.config.containerClass || ''}`,
774
- itemClass: `fs-html-editor-mention-menu-item ${this.config.menuItemClass || ''}`,
775
- trigger: this.config.trigger,
776
- allowSpaces: true,
777
- menuItemTemplate: (item) => {
778
- return this.config.menuItemTemplate(item.original);
779
- },
780
- selectTemplate: (item) => {
781
- const template = this.config.selectedTemplate(item.original);
782
- let p = document.createElement('p');
783
- p.innerHTML = template;
784
- let node = p.firstElementChild;
785
- if (!node) {
786
- node = document.createElement('span');
787
- node.innerHTML = template;
788
- }
789
- node.setAttribute('contenteditable', 'false');
790
- node.classList.add('fr-deletable');
791
- return node.outerHTML;
792
- },
793
- });
794
- MentionPlugin._tributes.push(this._tribute);
795
- }
796
- initialize() {
797
- this._tribute.attach(this.editor.el);
798
- this.editor.events.on('keydown', (e) => {
799
- if (e.key === 'Enter' && this._tribute.isActive) {
800
- return false;
801
- }
802
- }, true);
803
- this.editor.el.addEventListener("tribute-replaced", this.selected);
804
- }
805
- destroy() {
806
- this.editor.el.removeEventListener("tribute-replaced", this.selected);
807
- }
808
- _closeAll() {
809
- MentionPlugin._tributes.forEach((tribute) => {
810
- if (tribute.menu) {
811
- tribute.hideMenu();
812
- }
813
- });
814
- }
815
- _loadValues(keyword, cb) {
816
- MentionPlugin._currentGuid = this._guid;
817
- return this.config.fetch(keyword)
818
- .subscribe((data) => {
819
- cb(data);
820
- });
821
- }
822
- }
823
- MentionPlugin._currentGuid = null;
752
+ class MentionPlugin extends Plugin {
753
+ constructor(config) {
754
+ super();
755
+ this.config = config;
756
+ this._guid = guid();
757
+ this.selected = (event) => {
758
+ if (this.config.selected) {
759
+ if (MentionPlugin._currentGuid === this._guid) {
760
+ this.config.selected(event.detail.item.original);
761
+ }
762
+ }
763
+ };
764
+ this.config = Object.assign(Object.assign({}, config), { buttons: [
765
+ {
766
+ name: config.name,
767
+ tooltip: config.tooltip,
768
+ svgPath: config.iconPath,
769
+ click: (editor) => {
770
+ this._closeAll();
771
+ this._tribute.showMenuForCollection(editor.el);
772
+ }
773
+ }
774
+ ] });
775
+ this._tribute = new Tribute({
776
+ values: debounce(this._loadValues.bind(this), 200),
777
+ searchOpts: {
778
+ pre: '',
779
+ post: '',
780
+ skip: true
781
+ },
782
+ containerClass: `fs-html-editor-mention-container ${this.config.containerClass || ''}`,
783
+ itemClass: `fs-html-editor-mention-menu-item ${this.config.menuItemClass || ''}`,
784
+ trigger: this.config.trigger,
785
+ allowSpaces: true,
786
+ menuItemTemplate: (item) => {
787
+ return this.config.menuItemTemplate(item.original);
788
+ },
789
+ selectTemplate: (item) => {
790
+ const template = this.config.selectedTemplate(item.original);
791
+ let p = document.createElement('p');
792
+ p.innerHTML = template;
793
+ let node = p.firstElementChild;
794
+ if (!node) {
795
+ node = document.createElement('span');
796
+ node.innerHTML = template;
797
+ }
798
+ node.setAttribute('contenteditable', 'false');
799
+ node.classList.add('fr-deletable');
800
+ return node.outerHTML;
801
+ },
802
+ });
803
+ MentionPlugin._tributes.push(this._tribute);
804
+ }
805
+ initialize() {
806
+ this._tribute.attach(this.editor.el);
807
+ this.editor.events.on('keydown', (e) => {
808
+ if (e.key === 'Enter' && this._tribute.isActive) {
809
+ return false;
810
+ }
811
+ }, true);
812
+ this.editor.el.addEventListener("tribute-replaced", this.selected);
813
+ }
814
+ destroy() {
815
+ this.editor.el.removeEventListener("tribute-replaced", this.selected);
816
+ }
817
+ _closeAll() {
818
+ MentionPlugin._tributes.forEach((tribute) => {
819
+ if (tribute.menu) {
820
+ tribute.hideMenu();
821
+ }
822
+ });
823
+ }
824
+ _loadValues(keyword, cb) {
825
+ MentionPlugin._currentGuid = this._guid;
826
+ return this.config.fetch(keyword)
827
+ .subscribe((data) => {
828
+ cb(data);
829
+ });
830
+ }
831
+ }
832
+ MentionPlugin._currentGuid = null;
824
833
  MentionPlugin._tributes = [];
825
834
 
826
- class ChecklistPlugin extends Plugin {
827
- constructor(config = { name: 'checklist' }) {
828
- super();
829
- this.config = config;
830
- this.config = Object.assign(Object.assign({}, config), { name: 'checklist', buttons: [
831
- {
832
- name: 'checklist',
833
- svgPath: 'M8.4,10.3l-1.2,1.2l4,4L20,6.7l-1.2-1.2l-7.6,7.6L8.4,10.3z M18.2,18.2H5.8V5.8h8.9V4H5.8C4.8,4,4,4.8,4,5.8v12.4c0,1,0.8,1.8,1.8,1.8h12.4c1,0,1.8-0.8,1.8-1.8v-7.1h-1.8V18.2z',
834
- click: (editor) => {
835
- editor.html.insert('<ul class="checklist"><li></li></ul>');
836
- }
837
- }
838
- ] });
839
- }
840
- initialize() {
841
- this.editor.events.on('click', (e) => {
842
- const li = e.target;
843
- if (li.nodeName === 'LI' && e.offsetX < 0) {
844
- const items = [li, ...li.querySelectorAll('li')];
845
- if (li.classList.contains('checked')) {
846
- items.forEach((item) => {
847
- item.classList.remove('checked');
848
- });
849
- }
850
- else {
851
- items.forEach((item) => {
852
- item.classList.add('checked');
853
- });
854
- }
855
- }
856
- }, false);
857
- }
835
+ class ChecklistPlugin extends Plugin {
836
+ constructor(config = { name: 'checklist' }) {
837
+ super();
838
+ this.config = config;
839
+ this.config = Object.assign(Object.assign({}, config), { name: 'checklist', buttons: [
840
+ {
841
+ name: 'checklist',
842
+ svgPath: 'M8.4,10.3l-1.2,1.2l4,4L20,6.7l-1.2-1.2l-7.6,7.6L8.4,10.3z M18.2,18.2H5.8V5.8h8.9V4H5.8C4.8,4,4,4.8,4,5.8v12.4c0,1,0.8,1.8,1.8,1.8h12.4c1,0,1.8-0.8,1.8-1.8v-7.1h-1.8V18.2z',
843
+ click: (editor) => {
844
+ editor.html.insert('<ul class="checklist"><li></li></ul>');
845
+ }
846
+ }
847
+ ] });
848
+ }
849
+ initialize() {
850
+ this.editor.events.on('click', (e) => {
851
+ const li = e.target;
852
+ if (li.nodeName === 'LI' && e.offsetX < 0) {
853
+ const items = [li, ...li.querySelectorAll('li')];
854
+ if (li.classList.contains('checked')) {
855
+ items.forEach((item) => {
856
+ item.classList.remove('checked');
857
+ });
858
+ }
859
+ else {
860
+ items.forEach((item) => {
861
+ item.classList.add('checked');
862
+ });
863
+ }
864
+ }
865
+ }, false);
866
+ }
858
867
  }
859
868
 
860
- class CodePlugin extends Plugin {
861
- constructor(config = { name: 'code' }) {
862
- super();
863
- this.config = config;
864
- this.config = Object.assign(Object.assign({}, config), { name: 'code', buttons: [
865
- {
866
- name: 'code',
867
- svgPath: 'M8.9,7.3L4.2,12l4.7,4.7l1.1-1.1L6.4,12L10,8.4L8.9,7.3z M15.1,7.3L14,8.4l3.6,3.6L14,15.6l1.1,1.1l4.7-4.7L15.1,7.3z',
868
- click: (editor) => {
869
- const node = editor.selection.get();
870
- const codeEl = this._getCodeEl(node.baseNode);
871
- if (codeEl) {
872
- codeEl.classList.remove('code');
873
- }
874
- else {
875
- editor.html.insert('<p class="code">' + editor.selection.get().toString().replace(/\n{1,}/g, '<br>') + '</p>');
876
- }
877
- }
878
- }
879
- ] });
880
- }
881
- initialize() {
882
- this.editor.events.on('keydown', (e) => {
883
- if (e.keyCode === 13) {
884
- const selection = this.editor.selection.get();
885
- if (selection && this._getCodeEl(selection.baseNode)) {
886
- e.preventDefault();
887
- e.stopPropagation();
888
- e.stopImmediatePropagation();
889
- let br = '<br>';
890
- const base = selection.baseNode;
891
- if (base.nodeName === '#text' && selection.baseOffset === base.length) {
892
- if (!(base.nextSibling && base.nextSibling.nodeName === 'BR')) {
893
- br += '<br>';
894
- }
895
- }
896
- else {
897
- const el = Array.from(base.childNodes).splice(selection.baseOffset - 1, 1).pop();
898
- if (el && el.nodeName !== 'BR') {
899
- br += '<br>';
900
- }
901
- }
902
- this.editor.html.insert(br);
903
- return false;
904
- }
905
- }
906
- }, true);
907
- }
908
- destroy() { }
909
- _getCodeEl(el) {
910
- if (el) {
911
- if (el.classList && el.classList.contains('code')) {
912
- return el;
913
- }
914
- if (el.parentElement) {
915
- return this._getCodeEl(el.parentElement);
916
- }
917
- }
918
- return null;
919
- }
869
+ class CodePlugin extends Plugin {
870
+ constructor(config = { name: 'code' }) {
871
+ super();
872
+ this.config = config;
873
+ this.config = Object.assign(Object.assign({}, config), { name: 'code', buttons: [
874
+ {
875
+ name: 'code',
876
+ svgPath: 'M8.9,7.3L4.2,12l4.7,4.7l1.1-1.1L6.4,12L10,8.4L8.9,7.3z M15.1,7.3L14,8.4l3.6,3.6L14,15.6l1.1,1.1l4.7-4.7L15.1,7.3z',
877
+ click: (editor) => {
878
+ const node = editor.selection.get();
879
+ const codeEl = this._getCodeEl(node.baseNode);
880
+ if (codeEl) {
881
+ codeEl.classList.remove('code');
882
+ }
883
+ else {
884
+ editor.html.insert('<p class="code">' + editor.selection.get().toString().replace(/\n{1,}/g, '<br>') + '</p>');
885
+ }
886
+ }
887
+ }
888
+ ] });
889
+ }
890
+ initialize() {
891
+ this.editor.events.on('keydown', (e) => {
892
+ if (e.keyCode === 13) {
893
+ const selection = this.editor.selection.get();
894
+ if (selection && this._getCodeEl(selection.baseNode)) {
895
+ e.preventDefault();
896
+ e.stopPropagation();
897
+ e.stopImmediatePropagation();
898
+ let br = '<br>';
899
+ const base = selection.baseNode;
900
+ if (base.nodeName === '#text' && selection.baseOffset === base.length) {
901
+ if (!(base.nextSibling && base.nextSibling.nodeName === 'BR')) {
902
+ br += '<br>';
903
+ }
904
+ }
905
+ else {
906
+ const el = Array.from(base.childNodes).splice(selection.baseOffset - 1, 1).pop();
907
+ if (el && el.nodeName !== 'BR') {
908
+ br += '<br>';
909
+ }
910
+ }
911
+ this.editor.html.insert(br);
912
+ return false;
913
+ }
914
+ }
915
+ }, true);
916
+ }
917
+ destroy() { }
918
+ _getCodeEl(el) {
919
+ if (el) {
920
+ if (el.classList && el.classList.contains('code')) {
921
+ return el;
922
+ }
923
+ if (el.parentElement) {
924
+ return this._getCodeEl(el.parentElement);
925
+ }
926
+ }
927
+ return null;
928
+ }
920
929
  }
921
930
 
922
- class ScreenRecordPlugin extends Plugin {
923
- constructor(config = {}) {
924
- super();
925
- this.config = config;
926
- this.config = Object.assign(Object.assign({}, config), { name: config.name || 'screenRecord', buttons: [
927
- {
928
- name: 'screenRecord',
931
+ class ScreenRecordPlugin extends Plugin {
932
+ constructor(config = {}) {
933
+ super();
934
+ this.config = config;
935
+ this.config = Object.assign(Object.assign({}, config), { name: config.name || 'screenRecord', buttons: [
936
+ {
937
+ name: 'screenRecord',
929
938
  svgPath: `M14.7,7.7v6.1H7.1V7.7H14.7 M16.3,9.6V6.9c0-0.4-0.3-0.8-0.8-0.8H6.4c-0.4,0-0.8,0.3-0.8,0.8v7.6c0,0.4,0.3,0.8,0.8,0.8h9.1c0.4,0,0.8-0.3,0.8-0.8v-2.7l1.7,1.7c0.3,0.3,0.8,0.3,1.1,0c0.1-0.1,0.2-0.3,0.2-0.5V8.4c0-0.4-0.3-0.8-0.8-0.8
930
939
  c-0.2,0-0.4,0.1-0.5,0.2L16.3,9.6z M21.5,1.6H2.9c-0.7,0-1.3,0.7-1.3,1.6v14.6c0,0.9,0.6,1.6,1.3,1.6h7.6v1.1l-5,1c-0.2,0-0.4,0.3-0.4,0.6c0,0.3,0.2,0.4,0.4,0.4c0,0,0,0,0.1,0l5.3-1h2.6l5.3,1c0,0,0,0,0.1,0c0.2,0,0.4-0.2,0.4-0.4
931
- c0-0.3-0.1-0.6-0.4-0.6l-5-1v-1.1h7.6c0.7,0,1.3-0.7,1.3-1.6V3.2C22.9,2.3,22.3,1.6,21.5,1.6z M21.1,17.3H3.3V3.7h17.8L21.1,17.3L21.1,17.3z`,
932
- tooltip: 'Screen Record',
933
- click: (editor) => {
934
- navigator.mediaDevices.getDisplayMedia({ video: true })
935
- .then((stream) => {
936
- const chunks = [];
937
- const options = { mimeType: 'video/webm; codecs=vp9' };
938
- let mediaRecorder = new MediaRecorder(stream, options);
939
- stream.addEventListener('inactive', (e) => {
940
- mediaRecorder.stop();
941
- mediaRecorder = null;
942
- stream.getTracks().forEach((track) => track.stop());
943
- stream = null;
944
- const blob = new Blob(chunks, { type: 'video/webm' });
945
- config.upload(blob)
946
- .subscribe((url) => {
947
- editor.html.insert(`<span class="fr-screen-record fr-deletable fr-draggable"><video controls style="max-width:${config.maxWidth}"><source src="${url}" type="video/webm"></video></span>`);
948
- });
949
- });
950
- mediaRecorder.addEventListener('dataavailable', (event) => {
951
- if (event.data && event.data.size > 0) {
952
- chunks.push(event.data);
953
- }
954
- });
955
- mediaRecorder.start(10);
956
- })
957
- .catch((e) => { });
958
- }
959
- }
960
- ] });
961
- }
962
- initialize() {
963
- return __awaiter(this, void 0, void 0, function* () {
964
- const FroalaEditor = window.FroalaEditor;
965
- this.editor.events.on('mouseup', (e) => {
966
- const el = this._getEl(e.target);
967
- if (el) {
968
- this.editor.popups.hideAll();
969
- this._activeEl = el;
970
- this._showPopup(el);
971
- }
972
- });
973
- FroalaEditor.POPUP_TEMPLATES["screenRecordPlugin.popup"] = '[_BUTTONS_]';
974
- FroalaEditor.DefineIcon('popupClose', { NAME: 'trash', SVG_KEY: 'remove' });
975
- FroalaEditor.RegisterCommand('popupClose', {
976
- title: 'Remove',
977
- undo: false,
978
- focus: false,
979
- callback: () => {
980
- if (this._activeEl) {
981
- this._activeEl.remove();
982
- }
983
- }
984
- });
985
- });
986
- }
987
- _createPopup() {
988
- const template = {
989
- buttons: `<div class="fr-buttons">${this.editor.button.buildList(['popupClose'])}</div>`,
990
- };
991
- return this.editor.popups.create('screenRecordPlugin.popup', template);
992
- }
993
- _showPopup(el) {
994
- var $popup = this.editor.popups.get('screenRecordPlugin.popup');
995
- if (!$popup) {
996
- $popup = this._createPopup();
997
- }
998
- this.editor.popups.setContainer('screenRecordPlugin.popup', this.editor.$(el));
999
- const left = el.offsetLeft + el.offsetWidth / 2;
1000
- this.editor.popups.show('screenRecordPlugin.popup', left, null);
1001
- }
1002
- _getEl(el) {
1003
- if (el && el.classList) {
1004
- if (el.classList.contains('fr-screen-record'))
1005
- return el;
1006
- return this._getEl(el.parentNode);
1007
- }
1008
- }
940
+ c0-0.3-0.1-0.6-0.4-0.6l-5-1v-1.1h7.6c0.7,0,1.3-0.7,1.3-1.6V3.2C22.9,2.3,22.3,1.6,21.5,1.6z M21.1,17.3H3.3V3.7h17.8L21.1,17.3L21.1,17.3z`,
941
+ tooltip: 'Screen Record',
942
+ click: (editor) => {
943
+ navigator.mediaDevices.getDisplayMedia({ video: true })
944
+ .then((stream) => {
945
+ const chunks = [];
946
+ const options = { mimeType: 'video/webm; codecs=vp9' };
947
+ let mediaRecorder = new MediaRecorder(stream, options);
948
+ stream.addEventListener('inactive', (e) => {
949
+ mediaRecorder.stop();
950
+ mediaRecorder = null;
951
+ stream.getTracks().forEach((track) => track.stop());
952
+ stream = null;
953
+ const blob = new Blob(chunks, { type: 'video/webm' });
954
+ config.upload(blob)
955
+ .subscribe((url) => {
956
+ editor.html.insert(`<span class="fr-screen-record fr-deletable fr-draggable"><video controls style="max-width:${config.maxWidth}"><source src="${url}" type="video/webm"></video></span>`);
957
+ });
958
+ });
959
+ mediaRecorder.addEventListener('dataavailable', (event) => {
960
+ if (event.data && event.data.size > 0) {
961
+ chunks.push(event.data);
962
+ }
963
+ });
964
+ mediaRecorder.start(10);
965
+ })
966
+ .catch((e) => { });
967
+ }
968
+ }
969
+ ] });
970
+ }
971
+ initialize() {
972
+ return __awaiter(this, void 0, void 0, function* () {
973
+ const FroalaEditor = window.FroalaEditor;
974
+ this.editor.events.on('mouseup', (e) => {
975
+ const el = this._getEl(e.target);
976
+ if (el) {
977
+ this.editor.popups.hideAll();
978
+ this._activeEl = el;
979
+ this._showPopup(el);
980
+ }
981
+ });
982
+ FroalaEditor.POPUP_TEMPLATES["screenRecordPlugin.popup"] = '[_BUTTONS_]';
983
+ FroalaEditor.DefineIcon('popupClose', { NAME: 'trash', SVG_KEY: 'remove' });
984
+ FroalaEditor.RegisterCommand('popupClose', {
985
+ title: 'Remove',
986
+ undo: false,
987
+ focus: false,
988
+ callback: () => {
989
+ if (this._activeEl) {
990
+ this._activeEl.remove();
991
+ }
992
+ }
993
+ });
994
+ });
995
+ }
996
+ _createPopup() {
997
+ const template = {
998
+ buttons: `<div class="fr-buttons">${this.editor.button.buildList(['popupClose'])}</div>`,
999
+ };
1000
+ return this.editor.popups.create('screenRecordPlugin.popup', template);
1001
+ }
1002
+ _showPopup(el) {
1003
+ var $popup = this.editor.popups.get('screenRecordPlugin.popup');
1004
+ if (!$popup) {
1005
+ $popup = this._createPopup();
1006
+ }
1007
+ this.editor.popups.setContainer('screenRecordPlugin.popup', this.editor.$(el));
1008
+ const left = el.offsetLeft + el.offsetWidth / 2;
1009
+ this.editor.popups.show('screenRecordPlugin.popup', left, null);
1010
+ }
1011
+ _getEl(el) {
1012
+ if (el && el.classList) {
1013
+ if (el.classList.contains('fr-screen-record'))
1014
+ return el;
1015
+ return this._getEl(el.parentNode);
1016
+ }
1017
+ }
1009
1018
  }
1010
1019
 
1011
- class RealtimePlugin extends Plugin {
1012
- constructor(config = { name: 'realtime' }) {
1013
- super();
1014
- this.config = config;
1015
- this.config = Object.assign(Object.assign({}, config), { name: 'realtime' });
1016
- }
1017
- initialize() {
1018
- this.editor.events.on('click', (e) => {
1019
- }, false);
1020
- }
1020
+ class RealtimePlugin extends Plugin {
1021
+ constructor(config = { name: 'realtime' }) {
1022
+ super();
1023
+ this.config = config;
1024
+ this.config = Object.assign(Object.assign({}, config), { name: 'realtime' });
1025
+ }
1026
+ initialize() {
1027
+ this.editor.events.on('click', (e) => {
1028
+ }, false);
1029
+ }
1021
1030
  }
1022
1031
 
1023
- /**
1024
- * Generated bundle index. Do not edit.
1032
+ /**
1033
+ * Generated bundle index. Do not edit.
1025
1034
  */
1026
1035
 
1027
1036
  export { ChecklistPlugin, CodePlugin, FS_HTML_EDITOR_CONFIG, FsHtmlEditorComponent, FsHtmlEditorModule, FsHtmlRendererComponent, FsHtmlRendererModule, MentionPlugin, ParagraphButtons, RealtimePlugin, RichButtons, ScreenRecordPlugin, TextButtons };