@firestitch/html-editor 12.7.5 → 12.7.6

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