croco-html 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +2 -2
  2. package/esm2022/lib/components/add-files-btn/add-files-btn.component.mjs +3 -3
  3. package/esm2022/lib/components/editor/external-video-block/external-video-block.component.mjs +16 -22
  4. package/esm2022/lib/components/editor/external-video-block/vk-video-player/vk-video-player.component.mjs +20 -0
  5. package/esm2022/lib/components/editor/html-raw-editor/html-raw-editor.component.mjs +7 -8
  6. package/esm2022/lib/components/editor/image-editor/image-editor.component.mjs +9 -10
  7. package/esm2022/lib/components/editor/index.mjs +1 -1
  8. package/esm2022/lib/components/editor/main-editor/main-editor.component.mjs +13 -14
  9. package/esm2022/lib/components/editor/main-editor-block/main-editor-block.component.mjs +12 -13
  10. package/esm2022/lib/components/editor/text-editor/text-editor.component.mjs +9 -10
  11. package/esm2022/lib/components/editor/visual-editor/DefaultAligments.mjs +1 -1
  12. package/esm2022/lib/components/editor/visual-editor/DefaultTags.mjs +2 -2
  13. package/esm2022/lib/components/editor/visual-editor/visual-editor.component.mjs +27 -24
  14. package/esm2022/lib/components/file-id-select/file-id-select.component.mjs +3 -3
  15. package/esm2022/lib/components/index.mjs +1 -1
  16. package/esm2022/lib/components/upload-files-btn/upload-files-btn.component.mjs +3 -3
  17. package/esm2022/lib/components/xml-tags/file-image-tag-view/file-image-tag-view.component.mjs +3 -3
  18. package/esm2022/lib/components/xml-tags/index.mjs +1 -1
  19. package/esm2022/lib/components/xml-tags/xml-tag-external-video/resize-observable.mjs +1 -1
  20. package/esm2022/lib/components/xml-tags/xml-tag-external-video/xml-tag-external-video.component.mjs +22 -6
  21. package/esm2022/lib/components/xml-tags/xml-tag-header-inner-text-view/xml-tag-header-inner-text-view.component.mjs +3 -4
  22. package/esm2022/lib/components/xml-tags/xml-tag-header-text-view/xml-tag-header-text-view.component.mjs +4 -5
  23. package/esm2022/lib/components/xml-tags/xml-tag-html-view/xml-tag-html-view.component.mjs +3 -3
  24. package/esm2022/lib/components/xml-tags/xml-tag-rich-text-view/xml-tag-rich-text-view.component.mjs +4 -5
  25. package/esm2022/lib/components/xml-tags/xml-tag-table-view/xml-tag-table-view.component.mjs +4 -5
  26. package/esm2022/lib/components/xml-tags/xml-tag-text-view/xml-tag-text-view.component.mjs +3 -4
  27. package/esm2022/lib/components/xml-tags/xml-tag-view/xml-tag-view.component.mjs +12 -11
  28. package/esm2022/lib/croco-html.module.mjs +6 -3
  29. package/esm2022/lib/extensions/AngularMaterialTableMethods.mjs +1 -1
  30. package/esm2022/lib/extensions/BodyTagsExtensions.mjs +8 -7
  31. package/esm2022/lib/extensions/BootstrapTableMethods.mjs +1 -1
  32. package/esm2022/lib/extensions/HtmlExtractionMethods.mjs +1 -1
  33. package/esm2022/lib/extensions/HtmlRawTagDataConsts.mjs +1 -1
  34. package/esm2022/lib/extensions/ImageMethods.mjs +1 -1
  35. package/esm2022/lib/extensions/InterfaceBlock.mjs +1 -1
  36. package/esm2022/lib/extensions/TableBuilder.mjs +1 -1
  37. package/esm2022/lib/extensions/TableMethods.mjs +1 -1
  38. package/esm2022/lib/extensions/Tags.mjs +20 -0
  39. package/esm2022/lib/extensions/TextMethods.mjs +11 -2
  40. package/esm2022/lib/extensions/TextSimpleMethods.mjs +1 -1
  41. package/esm2022/lib/extensions/VideoMethods.mjs +12 -1
  42. package/esm2022/lib/extensions/XmlExtensions.mjs +1 -1
  43. package/esm2022/lib/extensions/index.mjs +1 -1
  44. package/esm2022/lib/index.mjs +1 -1
  45. package/esm2022/lib/models/models.mjs +1 -1
  46. package/esm2022/lib/pipes/RichTextToHtmlPipe.mjs +1 -1
  47. package/esm2022/lib/pipes/TagToSpanPipe.mjs +1 -1
  48. package/esm2022/lib/pipes/ToHtmlBodyTagsPipe.mjs +1 -1
  49. package/esm2022/lib/pipes/ToPreviewHtmlPipe.mjs +1 -1
  50. package/esm2022/lib/pipes/index.mjs +1 -1
  51. package/esm2022/lib/pipes/to-preview.pipe.mjs +1 -1
  52. package/esm2022/lib/services/file-upload.service.mjs +1 -1
  53. package/esm2022/lib/services/files-query.service.mjs +1 -1
  54. package/esm2022/public-api.mjs +1 -1
  55. package/fesm2022/croco-html.mjs +968 -898
  56. package/fesm2022/croco-html.mjs.map +1 -1
  57. package/lib/components/editor/external-video-block/external-video-block.component.d.ts +5 -6
  58. package/lib/components/editor/external-video-block/vk-video-player/vk-video-player.component.d.ts +10 -0
  59. package/lib/components/editor/main-editor-block/main-editor-block.component.d.ts +0 -1
  60. package/lib/components/editor/visual-editor/visual-editor.component.d.ts +9 -0
  61. package/lib/components/xml-tags/xml-tag-external-video/xml-tag-external-video.component.d.ts +3 -1
  62. package/lib/components/xml-tags/xml-tag-view/xml-tag-view.component.d.ts +1 -1
  63. package/lib/croco-html.module.d.ts +2 -1
  64. package/lib/extensions/Tags.d.ts +15 -0
  65. package/lib/extensions/TextMethods.d.ts +10 -1
  66. package/lib/extensions/VideoMethods.d.ts +5 -0
  67. package/lib/index.d.ts +6 -6
  68. package/package.json +1 -1
@@ -1,47 +1,46 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, Inject, EventEmitter, Component, ViewChild, Input, Output, signal, ChangeDetectionStrategy, ViewEncapsulation, Pipe, NgModule } from '@angular/core';
3
- import * as i2 from '@angular/material/button';
3
+ import * as i1$1 from '@angular/material/button';
4
4
  import { MatButtonModule } from '@angular/material/button';
5
5
  import * as i1 from '@angular/common/http';
6
6
  import { HttpEventType, HttpResponse } from '@angular/common/http';
7
7
  import { throwError, Observable, map, distinctUntilChanged } from 'rxjs';
8
8
  import { filter, switchMap } from 'rxjs/operators';
9
- import * as i1$1 from '@angular/common';
10
- import { CommonModule } from '@angular/common';
11
- import * as i2$2 from '@angular/forms';
9
+ import * as i1$4 from '@angular/forms';
12
10
  import { FormsModule, ReactiveFormsModule } from '@angular/forms';
13
- import * as i3 from '@angular/material/form-field';
11
+ import * as i2 from '@angular/material/form-field';
14
12
  import { MatFormFieldModule } from '@angular/material/form-field';
15
- import * as i4 from '@angular/material/input';
13
+ import * as i3 from '@angular/material/input';
16
14
  import { MatInputModule } from '@angular/material/input';
17
15
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
18
- import * as i2$1 from '@angular/youtube-player';
16
+ import * as i1$3 from '@angular/youtube-player';
19
17
  import { YouTubePlayerModule } from '@angular/youtube-player';
20
- import * as i5 from '@angular/cdk/text-field';
21
- import * as i5$1 from '@angular/material/icon';
18
+ import * as i1$2 from '@angular/platform-browser';
19
+ import * as i4 from '@angular/cdk/text-field';
20
+ import * as i4$1 from '@angular/material/icon';
22
21
  import { MatIconModule } from '@angular/material/icon';
23
- import * as i6 from '@angular/material/button-toggle';
22
+ import * as i5 from '@angular/material/button-toggle';
24
23
  import { MatButtonToggleModule } from '@angular/material/button-toggle';
25
24
  import * as i3$1 from '@ng-select/ng-select';
26
25
  import { NgSelectModule } from '@ng-select/ng-select';
27
- import * as i1$3 from 'ngx-clipboard';
28
- import * as i2$3 from '@angular/material/snack-bar';
26
+ import * as i1$5 from 'ngx-clipboard';
27
+ import * as i2$1 from '@angular/material/snack-bar';
29
28
  import { MatSnackBarModule } from '@angular/material/snack-bar';
30
- import * as i6$2 from '@angular/material/tabs';
29
+ import * as i5$2 from '@angular/material/tabs';
31
30
  import { MatTabsModule } from '@angular/material/tabs';
32
- import * as i5$2 from '@angular/material/card';
31
+ import * as i4$2 from '@angular/material/card';
33
32
  import { MatCardModule } from '@angular/material/card';
34
- import * as i1$2 from '@angular/platform-browser';
35
- import * as i11 from '@angular/cdk/drag-drop';
33
+ import * as i10 from '@angular/cdk/drag-drop';
36
34
  import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
37
- import * as i4$1 from '@angular/material/progress-spinner';
35
+ import * as i3$2 from '@angular/material/progress-spinner';
38
36
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
39
- import * as i6$1 from '@angular/material/select';
37
+ import * as i5$1 from '@angular/material/select';
40
38
  import { MatSelectModule } from '@angular/material/select';
41
- import * as i7 from '@angular/material/core';
39
+ import * as i6 from '@angular/material/core';
42
40
  import { MatNativeDateModule } from '@angular/material/core';
43
- import * as i2$4 from '@angular/material/table';
41
+ import * as i1$6 from '@angular/material/table';
44
42
  import { MatTableModule } from '@angular/material/table';
43
+ import { CommonModule } from '@angular/common';
45
44
  import * as i38 from '@angular/material/tooltip';
46
45
  import { MatTooltipModule } from '@angular/material/tooltip';
47
46
  import * as i39 from '@angular/material/checkbox';
@@ -197,11 +196,11 @@ class UploadFilesBtnComponent {
197
196
  ngOnInit() {
198
197
  }
199
198
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: UploadFilesBtnComponent, deps: [{ token: FileUploadService }], target: i0.ɵɵFactoryTarget.Component }); }
200
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: UploadFilesBtnComponent, selector: "croco-app-upload-files-btn", inputs: { extAccepts: "extAccepts", isMultiple: "isMultiple", btnText: "btnText", createLocalCopiesNow: "createLocalCopiesNow", hidden: "hidden" }, outputs: { postFilesStarted: "postFilesStarted", onFilesUploaded: "onFilesUploaded" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["filesInput"], descendants: true }], ngImport: i0, template: "<button [hidden]=\"hidden\" mat-raised-button color=\"primary\" (click)=\"filesInput.click()\">{{btnText}}</button>\r\n<input [hidden]=\"true\" [accept]=\"extAccepts\" [multiple]=\"isMultiple\" type=\"file\" #filesInput (change)=\"handleFileInput($event.target.files)\" />", styles: [""], dependencies: [{ kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }] }); }
199
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: UploadFilesBtnComponent, selector: "croco-app-upload-files-btn", inputs: { extAccepts: "extAccepts", isMultiple: "isMultiple", btnText: "btnText", createLocalCopiesNow: "createLocalCopiesNow", hidden: "hidden" }, outputs: { postFilesStarted: "postFilesStarted", onFilesUploaded: "onFilesUploaded" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["filesInput"], descendants: true }], ngImport: i0, template: "<button [hidden]=\"hidden\" mat-raised-button color=\"primary\" (click)=\"filesInput.click()\">{{btnText}}</button>\n<input [hidden]=\"true\" [accept]=\"extAccepts\" [multiple]=\"isMultiple\" type=\"file\" #filesInput (change)=\"handleFileInput($event.target.files)\" />", styles: [""], dependencies: [{ kind: "component", type: i1$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }] }); }
201
200
  }
202
201
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: UploadFilesBtnComponent, decorators: [{
203
202
  type: Component,
204
- args: [{ selector: 'croco-app-upload-files-btn', template: "<button [hidden]=\"hidden\" mat-raised-button color=\"primary\" (click)=\"filesInput.click()\">{{btnText}}</button>\r\n<input [hidden]=\"true\" [accept]=\"extAccepts\" [multiple]=\"isMultiple\" type=\"file\" #filesInput (change)=\"handleFileInput($event.target.files)\" />" }]
203
+ args: [{ selector: 'croco-app-upload-files-btn', template: "<button [hidden]=\"hidden\" mat-raised-button color=\"primary\" (click)=\"filesInput.click()\">{{btnText}}</button>\n<input [hidden]=\"true\" [accept]=\"extAccepts\" [multiple]=\"isMultiple\" type=\"file\" #filesInput (change)=\"handleFileInput($event.target.files)\" />" }]
205
204
  }], ctorParameters: () => [{ type: FileUploadService }], propDecorators: { fileInput: [{
206
205
  type: ViewChild,
207
206
  args: ['filesInput']
@@ -255,11 +254,11 @@ class AddFilesBtnComponent {
255
254
  ngOnInit() {
256
255
  }
257
256
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: AddFilesBtnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
258
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: AddFilesBtnComponent, selector: "croco-html-add-files-btn", outputs: { postFilesStarted: "postFilesStarted", filesTagsReady: "filesTagsReady" }, viewQueries: [{ propertyName: "fakeBtn", first: true, predicate: ["fakeBtn"], descendants: true }], ngImport: i0, template: "<div [hidden]=\"true\">\r\n <croco-app-upload-files-btn #fakeBtn (onFilesUploaded)=\"filesUploadedHandler($event)\"\r\n [btnText]=\"'\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F'\" [createLocalCopiesNow]=\"true\"\r\n (postFilesStarted)=\"postFilesStartedEventHandler($event)\" [extAccepts]=\"'image/*'\"></croco-app-upload-files-btn>\r\n</div>\r\n\r\n<div>\r\n <button class=\"w-100\" (click)=\"handleClick()\" mat-stroked-button>\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F</button>\r\n</div>", styles: [""], dependencies: [{ kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: UploadFilesBtnComponent, selector: "croco-app-upload-files-btn", inputs: ["extAccepts", "isMultiple", "btnText", "createLocalCopiesNow", "hidden"], outputs: ["postFilesStarted", "onFilesUploaded"] }] }); }
257
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: AddFilesBtnComponent, selector: "croco-html-add-files-btn", outputs: { postFilesStarted: "postFilesStarted", filesTagsReady: "filesTagsReady" }, viewQueries: [{ propertyName: "fakeBtn", first: true, predicate: ["fakeBtn"], descendants: true }], ngImport: i0, template: "<div [hidden]=\"true\">\n <croco-app-upload-files-btn #fakeBtn (onFilesUploaded)=\"filesUploadedHandler($event)\"\n [btnText]=\"'\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F'\" [createLocalCopiesNow]=\"true\"\n (postFilesStarted)=\"postFilesStartedEventHandler($event)\" [extAccepts]=\"'image/*'\"></croco-app-upload-files-btn>\n</div>\n\n<div>\n <button class=\"w-100\" (click)=\"handleClick()\" mat-stroked-button>\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F</button>\n</div>", styles: [""], dependencies: [{ kind: "component", type: i1$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: UploadFilesBtnComponent, selector: "croco-app-upload-files-btn", inputs: ["extAccepts", "isMultiple", "btnText", "createLocalCopiesNow", "hidden"], outputs: ["postFilesStarted", "onFilesUploaded"] }] }); }
259
258
  }
260
259
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: AddFilesBtnComponent, decorators: [{
261
260
  type: Component,
262
- args: [{ selector: 'croco-html-add-files-btn', template: "<div [hidden]=\"true\">\r\n <croco-app-upload-files-btn #fakeBtn (onFilesUploaded)=\"filesUploadedHandler($event)\"\r\n [btnText]=\"'\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F'\" [createLocalCopiesNow]=\"true\"\r\n (postFilesStarted)=\"postFilesStartedEventHandler($event)\" [extAccepts]=\"'image/*'\"></croco-app-upload-files-btn>\r\n</div>\r\n\r\n<div>\r\n <button class=\"w-100\" (click)=\"handleClick()\" mat-stroked-button>\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F</button>\r\n</div>" }]
261
+ args: [{ selector: 'croco-html-add-files-btn', template: "<div [hidden]=\"true\">\n <croco-app-upload-files-btn #fakeBtn (onFilesUploaded)=\"filesUploadedHandler($event)\"\n [btnText]=\"'\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F'\" [createLocalCopiesNow]=\"true\"\n (postFilesStarted)=\"postFilesStartedEventHandler($event)\" [extAccepts]=\"'image/*'\"></croco-app-upload-files-btn>\n</div>\n\n<div>\n <button class=\"w-100\" (click)=\"handleClick()\" mat-stroked-button>\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u044F</button>\n</div>" }]
263
262
  }], ctorParameters: () => [], propDecorators: { postFilesStarted: [{
264
263
  type: Output
265
264
  }], fakeBtn: [{
@@ -269,942 +268,1040 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
269
268
  type: Output
270
269
  }] } });
271
270
 
272
- class ExternalVideoTagDataConsts {
273
- static { this.TagName = "external-video"; }
274
- static { this.VideoTypeAttrName = "type"; }
275
- static { this.LinkAttrName = "link"; }
276
- }
277
- class ExternalVideoSupportedTypes {
278
- static { this.Youtube = "youtube"; }
279
- }
280
- class VideoMethods {
281
- static ExtractExternalVideoTag(elem) {
282
- return {
283
- type: ExternalVideoTagDataConsts.TagName,
284
- data: {
285
- type: elem.getAttribute(ExternalVideoTagDataConsts.VideoTypeAttrName),
286
- link: elem.getAttribute(ExternalVideoTagDataConsts.LinkAttrName)
271
+ class AngularMaterialTableMethods {
272
+ static getAngularMaterialTableData(columns, rows) {
273
+ let data = [];
274
+ for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
275
+ const row = rows[rowIndex];
276
+ var elem = {};
277
+ for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {
278
+ const column = columns[columnIndex];
279
+ elem[column] = row.columns[columnIndex].data.text;
287
280
  }
281
+ data.push(elem);
282
+ }
283
+ return {
284
+ displayedColumns: columns,
285
+ data: data,
288
286
  };
289
287
  }
290
- }
291
-
292
- function resizeObservable(elem, options) {
293
- return new Observable((subscriber) => {
294
- const resizeObserver = new ResizeObserver(([entry]) => {
295
- subscriber.next(entry);
296
- });
297
- resizeObserver.observe(elem, options);
298
- return function unsubscribe() {
299
- resizeObserver.unobserve(elem);
300
- };
301
- });
302
- }
303
-
304
- class XmlTagExternalVideoComponent {
305
- set data(value) {
306
- this.tagData = value.data;
307
- }
308
- ;
309
- set tagData(value) {
310
- this.videoId = this.getYouTubeId(value.link);
311
- }
312
- ;
313
- constructor(destroyRef) {
314
- this.destroyRef = destroyRef;
315
- this.playerWidth = signal(NaN);
316
- this.playerHeight = signal(NaN);
317
- }
318
- ngOnInit() {
319
- const youtubeIframeApiUrl = 'https://www.youtube.com/iframe_api';
320
- if (!document.querySelector(`script[src="${youtubeIframeApiUrl}"]`)) {
321
- // This code loads the IFrame Player API code asynchronously, according to the instructions at
322
- // https://developers.google.com/youtube/iframe_api_reference#Getting_Started
323
- const tag = document.createElement('script');
324
- tag.setAttribute('src', youtubeIframeApiUrl);
325
- document.body.appendChild(tag);
288
+ static checkHeaders(tableData) {
289
+ if (tableData.header === null) {
290
+ return {
291
+ isSucceeded: false,
292
+ message: "Необходимо указать заголовок таблицы"
293
+ };
326
294
  }
327
- if (this.playerContainerRef) {
328
- resizeObservable(this.playerContainerRef.nativeElement)
329
- .pipe(map(({ contentRect: { height, width } }) => ({ height, width })), distinctUntilChanged((a, b) => a.height === b.height && a.width === b.width), takeUntilDestroyed(this.destroyRef))
330
- .subscribe(({ height, width }) => {
331
- this.playerHeight.set(height);
332
- this.playerWidth.set(width);
333
- });
295
+ let columns = tableData.header.columns;
296
+ var uniqueDislayedColumns = columns.filter((v, i, a) => a.indexOf(v) === i);
297
+ if (uniqueDislayedColumns.length !== columns.length) {
298
+ return {
299
+ isSucceeded: false,
300
+ message: "Ошибка при обработке разметки таблицы. Обнаружены дубликаты заголовков."
301
+ };
334
302
  }
303
+ return {
304
+ isSucceeded: true,
305
+ message: "Ok"
306
+ };
335
307
  }
336
- getYouTubeId(youtubeLink) {
337
- //https://www.youtube.com/watch?v=l3KfbfkxJOU
338
- const url = new URL(youtubeLink);
339
- if (url.pathname.endsWith('watch')) {
340
- return url.searchParams.get("v");
308
+ static checkAngularMaterialTableData(tableData, checkHeaders = true) {
309
+ if (checkHeaders) {
310
+ var checkHeadersResult = this.checkHeaders(tableData);
311
+ if (!checkHeadersResult.isSucceeded) {
312
+ return checkHeadersResult;
313
+ }
341
314
  }
342
- //https://youtu.be/jzBneaWSswY
343
- const bits = url.pathname.split('/');
344
- return bits[bits.length - 1];
315
+ let rows = tableData.rows;
316
+ let columns = tableData.header.columns;
317
+ for (let i = 0; i < rows.length; i++) {
318
+ const row = rows[i];
319
+ if (row.columns.length !== columns.length) {
320
+ return {
321
+ isSucceeded: false,
322
+ message: `Ошибка при обработке разметки таблицы. `
323
+ + `Количество колонок в каждой строке таблицы должно соотвествовать количеству колонок указанных в заголовке. `
324
+ + `В строке таблицы №${i + 1} количество колонок = ${row.columns.length}, а должно быть ${columns.length}.`
325
+ };
326
+ }
327
+ }
328
+ return {
329
+ isSucceeded: true,
330
+ message: "Ok"
331
+ };
345
332
  }
346
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagExternalVideoComponent, deps: [{ token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Component }); }
347
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagExternalVideoComponent, selector: "croco-html-xml-tag-external-video", inputs: { data: "data", tagData: "tagData" }, viewQueries: [{ propertyName: "playerContainerRef", first: true, predicate: ["playerContainer"], descendants: true, static: true }], ngImport: i0, template: "<div #playerContainer class=\"d-flex justify-content-center y-video\">\r\n <youtube-player [height]=\"playerHeight()\" [width]=\"playerWidth()\" *ngIf=\"videoId\" [videoId]=\"videoId\"></youtube-player>\r\n</div>\r\n", styles: ["@media only screen and (min-width: 769px){.y-video{display:block;width:640px;height:360px;margin:0 auto}}@media only screen and (max-width: 827px){.y-video{display:block;width:100%;height:315px}}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.YouTubePlayer, selector: "youtube-player", inputs: ["videoId", "height", "width", "startSeconds", "endSeconds", "suggestedQuality", "playerVars", "disableCookies", "loadApi", "disablePlaceholder", "showBeforeIframeApiLoads", "placeholderButtonLabel", "placeholderImageQuality"], outputs: ["ready", "stateChange", "error", "apiChange", "playbackQualityChange", "playbackRateChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
348
333
  }
349
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagExternalVideoComponent, decorators: [{
350
- type: Component,
351
- args: [{ selector: 'croco-html-xml-tag-external-video', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div #playerContainer class=\"d-flex justify-content-center y-video\">\r\n <youtube-player [height]=\"playerHeight()\" [width]=\"playerWidth()\" *ngIf=\"videoId\" [videoId]=\"videoId\"></youtube-player>\r\n</div>\r\n", styles: ["@media only screen and (min-width: 769px){.y-video{display:block;width:640px;height:360px;margin:0 auto}}@media only screen and (max-width: 827px){.y-video{display:block;width:100%;height:315px}}\n"] }]
352
- }], ctorParameters: () => [{ type: i0.DestroyRef }], propDecorators: { data: [{
353
- type: Input
354
- }], tagData: [{
355
- type: Input
356
- }], playerContainerRef: [{
357
- type: ViewChild,
358
- args: ['playerContainer', { static: true }]
359
- }] } });
360
334
 
361
- class ExternalVideoBlockComponent {
362
- constructor() {
363
- this.onTagUpdated = new EventEmitter();
364
- this.defaultLink = "https://youtu.be/jzBneaWSswY";
365
- this.data = {
366
- youtubeLink: this.defaultLink
335
+ var EAlignments;
336
+ (function (EAlignments) {
337
+ EAlignments["Left"] = "left";
338
+ EAlignments["Center"] = "center";
339
+ EAlignments["Right"] = "right";
340
+ })(EAlignments || (EAlignments = {}));
341
+ const AlignmentsData = [
342
+ { value: EAlignments.Left, text: 'Слева' },
343
+ { value: EAlignments.Center, text: 'По центру' },
344
+ { value: EAlignments.Right, text: 'Справа' },
345
+ ];
346
+
347
+ const TextTag = "text";
348
+ class TextSimpleMethods {
349
+ static { this.supportedTags = ["sup", "sub", "strong", "b", "i", "u"]; }
350
+ static ExtractTextTag(elem) {
351
+ var hAlignValue = elem.getAttribute("h-align") ?? EAlignments.Left;
352
+ var data = {
353
+ textTagName: elem.tagName.toLowerCase(),
354
+ text: elem.innerText.trim().replace('\n\t', ''),
355
+ html: elem.innerHTML.trim().replace('\n\t', ''),
356
+ horizontalAlignment: hAlignValue,
357
+ validationResult: {
358
+ isSucceeded: true,
359
+ message: "Ok"
360
+ }
367
361
  };
368
- this.tagData = {
369
- link: this.defaultLink,
370
- type: ExternalVideoSupportedTypes.Youtube
362
+ let result = {
363
+ type: TextTag,
364
+ data: data
371
365
  };
366
+ if (result.data.text === '\n') {
367
+ result.data.text = '';
368
+ }
369
+ if (result.data.html === '\n') {
370
+ result.data.html = '';
371
+ }
372
+ var alignmentVals = [EAlignments.Left, EAlignments.Right, EAlignments.Center];
373
+ if (alignmentVals.indexOf(hAlignValue) < 0) {
374
+ result.data.validationResult = {
375
+ isSucceeded: false,
376
+ message: `Недопустимое значение атрибута h-align. Допустимые значения: ${alignmentVals.join(', ')}. `
377
+ + 'Данный тег можно не указывать, по-умолчанию будет применено выравнивание слева.'
378
+ };
379
+ }
380
+ var html = result.data.html;
381
+ var htmlValidation = this.ValidateTextHtml(html);
382
+ if (!htmlValidation.isSucceeded) {
383
+ result.data.validationResult = htmlValidation;
384
+ }
385
+ return result;
372
386
  }
373
- linkChanged() {
374
- this.tagData.link = this.data.youtubeLink;
375
- this.tag.attributes = this.tagData;
387
+ static ValidateTextHtml(html) {
388
+ var p = document.createElement("p");
389
+ p.innerHTML = html;
390
+ for (let i = 0; i < p.children.length; i++) {
391
+ const element = p.children.item(i);
392
+ var validationResult = this.ValidateTag(element);
393
+ if (!validationResult.isSucceeded) {
394
+ return validationResult;
395
+ }
396
+ }
397
+ return {
398
+ isSucceeded: true,
399
+ message: `Ok`
400
+ };
376
401
  }
377
- ngOnInit() {
378
- if (!this.tag?.attributes?.['link']) {
379
- this.linkChanged();
402
+ static ValidateTag(element) {
403
+ let lowerTag = element.tagName.toLowerCase();
404
+ if (!this.supportedTags.includes(lowerTag)) {
405
+ return {
406
+ isSucceeded: false,
407
+ message: `Тег <${lowerTag}> не поддерживается внутри тега <text>`
408
+ };
409
+ }
410
+ for (let i = 0; i < element.children.length; i++) {
411
+ const nElement = element.children.item(i);
412
+ var innerValidationResult = this.ValidateTag(nElement);
413
+ if (!innerValidationResult.isSucceeded) {
414
+ return innerValidationResult;
415
+ }
380
416
  }
381
- this.tagData = this.tag.attributes;
382
- this.data.youtubeLink = this.tagData.link;
417
+ return {
418
+ isSucceeded: true,
419
+ message: "Ok"
420
+ };
383
421
  }
384
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: ExternalVideoBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
385
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: ExternalVideoBlockComponent, selector: "croco-html-external-video-block", inputs: { tag: "tag" }, outputs: { onTagUpdated: "onTagUpdated" }, ngImport: i0, template: "<div *ngIf=\"tag.presentOrEdit\">\r\n \r\n <div>\r\n \u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 YouTube: {{data.youtubeLink}}\r\n </div>\r\n\r\n <div style=\"height: 10px;\"></div>\r\n\r\n <croco-html-xml-tag-external-video [tagData]=\"tagData\">\r\n </croco-html-xml-tag-external-video>\r\n</div>\r\n\r\n<div *ngIf=\"!tag.presentOrEdit\">\r\n <div>\r\n <div>\r\n <mat-form-field class=\"w-100\">\r\n <input matInput placeholder=\"\u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 YouTube\"\r\n new-autocomplete=\"off\"\r\n autocomplete=\"off\"\r\n [(ngModel)]=\"data.youtubeLink\"\r\n (ngModelChange)=\"linkChanged()\">\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: XmlTagExternalVideoComponent, selector: "croco-html-xml-tag-external-video", inputs: ["data", "tagData"] }] }); }
386
422
  }
387
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: ExternalVideoBlockComponent, decorators: [{
388
- type: Component,
389
- args: [{ selector: 'croco-html-external-video-block', template: "<div *ngIf=\"tag.presentOrEdit\">\r\n \r\n <div>\r\n \u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 YouTube: {{data.youtubeLink}}\r\n </div>\r\n\r\n <div style=\"height: 10px;\"></div>\r\n\r\n <croco-html-xml-tag-external-video [tagData]=\"tagData\">\r\n </croco-html-xml-tag-external-video>\r\n</div>\r\n\r\n<div *ngIf=\"!tag.presentOrEdit\">\r\n <div>\r\n <div>\r\n <mat-form-field class=\"w-100\">\r\n <input matInput placeholder=\"\u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 YouTube\"\r\n new-autocomplete=\"off\"\r\n autocomplete=\"off\"\r\n [(ngModel)]=\"data.youtubeLink\"\r\n (ngModelChange)=\"linkChanged()\">\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n" }]
390
- }], propDecorators: { tag: [{
391
- type: Input
392
- }], onTagUpdated: [{
393
- type: Output
394
- }] } });
395
423
 
396
- class HtmlRawEditorComponent {
397
- constructor() {
398
- this.onTagUpdated = new EventEmitter();
424
+ class BootstrapTableMethods {
425
+ static BuildTable(data) {
426
+ let result = `<table class="table table-bordered">`;
427
+ result += this.BuildHeader(data.header);
428
+ result += this.BuildBody(data.rows);
429
+ result += "</table>";
430
+ return result;
399
431
  }
400
- ngOnInit() {
432
+ static BuildHeader(data) {
433
+ if (data === null) {
434
+ return "";
435
+ }
436
+ let result = "<thead>";
437
+ result += "<tr>";
438
+ for (let index = 0; index < data.columns.length; index++) {
439
+ result += `<th>${data.columns[index]}</th>`;
440
+ }
441
+ result += "</tr>";
442
+ result += "</thead>";
443
+ return result;
401
444
  }
402
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: HtmlRawEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
403
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: HtmlRawEditorComponent, selector: "croco-html-html-raw-editor", inputs: { tag: "tag" }, outputs: { onTagUpdated: "onTagUpdated" }, ngImport: i0, template: "<div *ngIf=\"tag.presentOrEdit\">\r\n <div [innerHTML]=\"tag.innerHtml\"></div>\r\n</div>\r\n\r\n<div *ngIf=\"!tag.presentOrEdit\">\r\n <div style=\"height: 10px;\">\r\n </div>\r\n <div>\r\n <mat-form-field class=\"w-100\">\r\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\r\n cdkAutosizeMinRows=\"1\"\r\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u0433\u0430\"\r\n [(ngModel)]=\"tag.innerHtml\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n</div>\r\n\r\n", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i5.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }] }); }
404
- }
405
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: HtmlRawEditorComponent, decorators: [{
406
- type: Component,
407
- args: [{ selector: 'croco-html-html-raw-editor', template: "<div *ngIf=\"tag.presentOrEdit\">\r\n <div [innerHTML]=\"tag.innerHtml\"></div>\r\n</div>\r\n\r\n<div *ngIf=\"!tag.presentOrEdit\">\r\n <div style=\"height: 10px;\">\r\n </div>\r\n <div>\r\n <mat-form-field class=\"w-100\">\r\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\r\n cdkAutosizeMinRows=\"1\"\r\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u0433\u0430\"\r\n [(ngModel)]=\"tag.innerHtml\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n</div>\r\n\r\n" }]
408
- }], ctorParameters: () => [], propDecorators: { tag: [{
409
- type: Input
410
- }], onTagUpdated: [{
411
- type: Output
412
- }] } });
413
-
414
- const CrocoHtmlOptionsToken = "croco-html-options";
415
-
416
- var FileType;
417
- (function (FileType) {
418
- FileType["Undefined"] = "Undefined";
419
- FileType["Unknown"] = "Unknown";
420
- FileType["Image"] = "Image";
421
- FileType["Audio"] = "Audio";
422
- FileType["Video"] = "Video";
423
- FileType["Document"] = "Document";
424
- FileType["Archive"] = "Archive";
425
- })(FileType || (FileType = {}));
426
- class FilesQueryService {
427
- constructor(_httpClient, baseUrl) {
428
- this._httpClient = _httpClient;
429
- this._baseControllerUrl = `${baseUrl}Api/Files`;
445
+ static BuildBody(rows) {
446
+ let result = "<tbody>";
447
+ for (let i = 0; i < rows.length; i++) {
448
+ const row = rows[i];
449
+ result += "<tr>";
450
+ for (let j = 0; j < row.columns.length; j++) {
451
+ const col = row.columns[j];
452
+ result += `<td class="align-middle">${this.BuildInnerTags(col.data.children)}</td>`;
453
+ }
454
+ result += "</tr>";
455
+ }
456
+ result += "</tbody>";
457
+ return result;
430
458
  }
431
- getFilesWithRelations(model) {
432
- return this._httpClient.post(this._baseControllerUrl + `/GetFiles/WithRelations`, model);
459
+ static BuildInnerTags(tags) {
460
+ let result = "";
461
+ for (let i = 0; i < tags.length; i++) {
462
+ result += this.BuildInnerTag(tags[i]);
463
+ }
464
+ return result;
433
465
  }
434
- getFiles(model) {
435
- return this._httpClient.post(this._baseControllerUrl + `/GetFiles`, model);
466
+ static BuildInnerTag(data) {
467
+ if (data.type === FileImageTagDataConsts.TagName) {
468
+ let fileImageTag = data;
469
+ return `<img src=${fileImageTag.data.src} class="mx-auto d-block img-fluid" />`;
470
+ }
471
+ else if (data.type === TextTag) {
472
+ let simpleTextTag = data;
473
+ var map = {
474
+ ["left"]: "text-start",
475
+ ["center"]: "text-center",
476
+ ["right"]: "text-end"
477
+ };
478
+ if (!simpleTextTag.data.validationResult.isSucceeded) {
479
+ return `<span>Ошибка в тексте ${simpleTextTag.data.validationResult.message}</span>`;
480
+ }
481
+ return `<div class="${map[simpleTextTag.data.horizontalAlignment]}"><span>${simpleTextTag.data.html}</span></div>`;
482
+ }
483
+ else {
484
+ return `<p>Тег ${data.type} не поддерживается</p>`;
485
+ }
436
486
  }
437
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FilesQueryService, deps: [{ token: i1.HttpClient }, { token: 'BASE_URL' }], target: i0.ɵɵFactoryTarget.Injectable }); }
438
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FilesQueryService, providedIn: 'root' }); }
439
487
  }
440
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FilesQueryService, decorators: [{
441
- type: Injectable,
442
- args: [{
443
- providedIn: 'root'
444
- }]
445
- }], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
446
- type: Inject,
447
- args: ['BASE_URL']
448
- }] }] });
449
488
 
450
- class FileIdSelectComponent {
451
- constructor(_fileService, _options) {
452
- this._fileService = _fileService;
453
- this._options = _options;
454
- this.labelText = "Поиск файлов";
455
- this.loading = false;
456
- this.files = [];
457
- this.onFileIdChanged = new EventEmitter();
458
- }
459
- onModelChanged(fileId) {
460
- this.onFileIdChanged.emit(fileId);
461
- }
462
- getSrc(fileId) {
463
- return ImageMethods.buildSmallUrl(fileId, this._options);
464
- }
465
- ngOnInit() {
466
- this.loadFiles();
489
+ class TableTypes {
490
+ static { this.TableRowColumnData = "table-row-column-data"; }
491
+ static { this.Table = "table"; }
492
+ static { this.TableRowColumn = "table-row-column"; }
493
+ }
494
+ class TableMethods {
495
+ static getTableFromHtmlTag(tableTag, options) {
496
+ let tableData = {
497
+ header: TableMethods.getHeader(tableTag),
498
+ rows: TableMethods.getTableRows(tableTag, options)
499
+ };
500
+ var result = {
501
+ type: TableTypes.Table,
502
+ data: tableData,
503
+ validationResult: this.checkTable(tableData),
504
+ bootstrapHtml: ""
505
+ };
506
+ if (!result.validationResult) {
507
+ return result;
508
+ }
509
+ result.bootstrapHtml = BootstrapTableMethods.BuildTable(result.data);
510
+ var angularMaterialTableDataCheck = AngularMaterialTableMethods.checkAngularMaterialTableData(tableData);
511
+ if (!angularMaterialTableDataCheck.isSucceeded) {
512
+ return {
513
+ ...result,
514
+ angularMaterialTableDataCheck
515
+ };
516
+ }
517
+ return {
518
+ ...result,
519
+ angularMaterialTableDataCheck,
520
+ html: tableTag.outerHTML,
521
+ angularMaterialTableData: AngularMaterialTableMethods.getAngularMaterialTableData(tableData.header.columns, tableData.rows),
522
+ };
467
523
  }
468
- loadFiles() {
469
- this.loading = true;
470
- this._fileService.getFiles({
471
- count: 10,
472
- offSet: 0,
473
- fileName: null,
474
- fileTypes: [FileType.Image],
475
- applicationId: null,
476
- q: this.q
477
- }).subscribe(data => {
478
- this.files = [...data.list];
479
- this.loading = false;
480
- });
524
+ static checkTable(tableData) {
525
+ let rows = tableData.rows;
526
+ let prevRowCount = -1;
527
+ for (let i = 0; i < rows.length; i++) {
528
+ const row = rows[i];
529
+ if (row.columns.length !== prevRowCount && prevRowCount != -1) {
530
+ return {
531
+ isSucceeded: false,
532
+ message: `Ошибка при обработке разметки таблицы. `
533
+ + `Количество колонок в каждой строке таблицы должно соотвествовать друг другу. `
534
+ + `В строке таблицы №${i + 1} количество колонок = ${row.columns.length}, а в строке выше ${prevRowCount}.`
535
+ };
536
+ }
537
+ prevRowCount = row.columns.length;
538
+ }
539
+ return {
540
+ isSucceeded: true,
541
+ message: "Ok"
542
+ };
481
543
  }
482
- onSearchChanged(q) {
483
- this.q = q.term;
484
- this.loadFiles();
544
+ static getHeader(tableTag) {
545
+ let header = tableTag.tHead;
546
+ if (header === null) {
547
+ return null;
548
+ }
549
+ let tr = header.children.item(0);
550
+ let headerColumns = [];
551
+ for (let j = 0; j < tr.children.length; j++) {
552
+ const jElement = tr.children.item(j);
553
+ headerColumns.push(jElement.innerHTML);
554
+ }
555
+ return {
556
+ type: "table-header",
557
+ columns: headerColumns
558
+ };
485
559
  }
486
- ngOnChanges(changes) {
487
- this.loadFiles();
560
+ static getTableRows(tableTag, options) {
561
+ let tBody = tableTag.tBodies.item(0);
562
+ let rows = [];
563
+ for (let i = 0; i < tBody.children.length; i++) {
564
+ const iElement = tBody.children.item(i);
565
+ let rowColumns = [];
566
+ for (let j = 0; j < iElement.children.length; j++) {
567
+ const jElement = iElement.children.item(j);
568
+ let children = HtmlExtractionMethods.transformHtmlElementToBlocks(jElement, options);
569
+ if (children.length === 0) {
570
+ var textTag = document.createElement("p");
571
+ textTag.innerHTML = jElement.innerHTML;
572
+ var textElem = TextSimpleMethods.ExtractTextTag(textTag);
573
+ children.push(textElem);
574
+ }
575
+ var result = {
576
+ type: TableTypes.TableRowColumnData,
577
+ data: {
578
+ text: jElement.innerHTML,
579
+ children
580
+ }
581
+ };
582
+ rowColumns.push(result);
583
+ }
584
+ rows.push({
585
+ type: TableTypes.TableRowColumn,
586
+ columns: rowColumns
587
+ });
588
+ }
589
+ return rows;
488
590
  }
489
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FileIdSelectComponent, deps: [{ token: FilesQueryService }, { token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
490
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: FileIdSelectComponent, selector: "croco-html-file-id-select", inputs: { labelText: "labelText", fileId: "fileId" }, outputs: { fileId: "fileId", onFileIdChanged: "onFileIdChanged" }, usesOnChanges: true, ngImport: i0, template: "<div>\r\n <div class=\"form-group\">\r\n <label for=\"fileName\">{{labelText}}</label>\r\n <ng-select [(ngModel)]=\"fileId\" (ngModelChange)=\"onModelChanged($event)\"\r\n [items]=\"files\"\r\n #select\r\n bindLabel=\"fileName\"\r\n (search)=\"onSearchChanged($event)\"\r\n [loading]=\"loading\"\r\n [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\r\n dropdownPosition=\"auto\"\r\n bindValue=\"fileId\"\r\n labelForId=\"fileName\"\r\n placeholder=\"\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B\"\r\n [virtualScroll]=\"true\">\r\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\r\n <div>\r\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc(item.fileId)\"/>\r\n </div>\r\n <div>\r\n <span class=\"h5\">\u0424\u0430\u0439\u043B: </span>\r\n <span class=\"h5\" [ngOptionHighlight]=\"search\"><b>{{item.fileName}}</b></span>\r\n </div>\r\n <div>\r\n <small>\r\n <span>\r\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: <b>{{item.fileId}}</b>\r\n </span>\r\n </small>\r\n </div>\r\n </ng-template>\r\n </ng-select>\r\n </div>\r\n</div>\r\n\r\n<div>\r\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: {{fileId}}\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: i3$1.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }] }); }
491
591
  }
492
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FileIdSelectComponent, decorators: [{
493
- type: Component,
494
- args: [{ selector: 'croco-html-file-id-select', template: "<div>\r\n <div class=\"form-group\">\r\n <label for=\"fileName\">{{labelText}}</label>\r\n <ng-select [(ngModel)]=\"fileId\" (ngModelChange)=\"onModelChanged($event)\"\r\n [items]=\"files\"\r\n #select\r\n bindLabel=\"fileName\"\r\n (search)=\"onSearchChanged($event)\"\r\n [loading]=\"loading\"\r\n [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\r\n dropdownPosition=\"auto\"\r\n bindValue=\"fileId\"\r\n labelForId=\"fileName\"\r\n placeholder=\"\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B\"\r\n [virtualScroll]=\"true\">\r\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\r\n <div>\r\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc(item.fileId)\"/>\r\n </div>\r\n <div>\r\n <span class=\"h5\">\u0424\u0430\u0439\u043B: </span>\r\n <span class=\"h5\" [ngOptionHighlight]=\"search\"><b>{{item.fileName}}</b></span>\r\n </div>\r\n <div>\r\n <small>\r\n <span>\r\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: <b>{{item.fileId}}</b>\r\n </span>\r\n </small>\r\n </div>\r\n </ng-template>\r\n </ng-select>\r\n </div>\r\n</div>\r\n\r\n<div>\r\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: {{fileId}}\r\n</div>\r\n" }]
495
- }], ctorParameters: () => [{ type: FilesQueryService }, { type: undefined, decorators: [{
496
- type: Inject,
497
- args: [CrocoHtmlOptionsToken]
498
- }] }], propDecorators: { labelText: [{
499
- type: Input
500
- }], fileId: [{
501
- type: Input
502
- }, {
503
- type: Output
504
- }], onFileIdChanged: [{
505
- type: Output
506
- }] } });
507
592
 
508
- class ImageEditorComponent {
509
- onErrorHandler() {
510
- this.hasImageError = true;
511
- }
512
- constructor(_options) {
513
- this._options = _options;
514
- this.hasImageError = false;
515
- this.searchOrEdit = "search";
516
- this.onTagUpdated = new EventEmitter();
517
- }
518
- getSrc() {
519
- return ImageMethods.buildUrl(this.tag.attributes[FileImageTagDataConsts.FileIdAttrName], "Medium", this._options);
520
- }
521
- hasFileId() {
522
- return this.tag.attributes.hasOwnProperty(FileImageTagDataConsts.FileIdAttrName) && !isNaN(this.tag.attributes[FileImageTagDataConsts.FileIdAttrName]);
523
- }
524
- onFileIdChanged(fileId) {
525
- this.tag.attributes[FileImageTagDataConsts.FileIdAttrName] = fileId;
526
- this.removeImageError();
527
- }
528
- removeImageError() {
529
- this.hasImageError = false;
530
- }
531
- ngOnInit() {
532
- }
533
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: ImageEditorComponent, deps: [{ token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
534
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: ImageEditorComponent, selector: "croco-html-image-editor", inputs: { tag: "tag" }, outputs: { onTagUpdated: "onTagUpdated" }, ngImport: i0, template: "<div>\r\n <div style=\"height: 10px;\">\r\n </div>\r\n \r\n <div *ngIf=\"hasImageError\" class=\"error-block\">\r\n \u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0444\u0430\u0439\u043B \u043D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043B\u0438 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.\r\n </div>\r\n\r\n <div *ngIf=\"hasFileId() && !hasImageError\">\r\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc()\" (error)=\"onErrorHandler()\"/>\r\n </div>\r\n\r\n <div *ngIf=\"!hasFileId()\">\r\n <h5>[\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043E]</h5>\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"!tag.presentOrEdit\">\r\n <div style=\"height: 10px;\"></div>\r\n\r\n <div style=\"overflow-x:auto;\">\r\n <mat-button-toggle-group [(ngModel)]=\"searchOrEdit\">\r\n <mat-button-toggle value=\"search\">\r\n \u0418\u0441\u043A\u0430\u0442\u044C \u0444\u0430\u0439\u043B <mat-icon>search</mat-icon>\r\n </mat-button-toggle>\r\n <mat-button-toggle value=\"edit\">\r\n \u0423\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443 <mat-icon>settings</mat-icon>\r\n </mat-button-toggle>\r\n </mat-button-toggle-group>\r\n </div>\r\n \r\n\r\n <div style=\"height: 10px;\"></div>\r\n\r\n <div [hidden]=\"searchOrEdit !== 'search'\">\r\n <croco-html-file-id-select\r\n [labelText]=\"'\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B'\"\r\n [(fileId)]=\"tag.attributes['file-id']\"\r\n (onFileIdChanged)=\"onFileIdChanged($event)\">\r\n </croco-html-file-id-select>\r\n </div>\r\n\r\n <div [hidden]=\"searchOrEdit !== 'edit'\">\r\n <div>\r\n <mat-form-field class=\"w-100\">\r\n <input matInput placeholder=\"\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430\" new-autocomplete=\"off\" autocomplete=\"off\"\r\n type=\"number\"\r\n [(ngModel)]=\"tag.attributes['file-id']\"\r\n (ngModelChange)=\"removeImageError()\">\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>", styles: [".error-block{background-color:#f32323;color:#fff;text-align:center;border-radius:10px;padding:10px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i6.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i6.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: FileIdSelectComponent, selector: "croco-html-file-id-select", inputs: ["labelText", "fileId"], outputs: ["fileId", "onFileIdChanged"] }] }); }
593
+ class TextTags {
594
+ static { this.text = "text"; }
595
+ static { this.h1 = "h1"; }
596
+ static { this.h2 = "h2"; }
597
+ static { this.h3 = "h3"; }
598
+ static { this.h4 = "h4"; }
599
+ static { this.h5 = "h5"; }
600
+ static { this.h6 = "h6"; }
601
+ static { this.allTextTags = [TextTags.text, TextTags.h1, TextTags.h2, TextTags.h3, TextTags.h4, TextTags.h5, TextTags.h6]; }
535
602
  }
536
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: ImageEditorComponent, decorators: [{
537
- type: Component,
538
- args: [{ selector: 'croco-html-image-editor', template: "<div>\r\n <div style=\"height: 10px;\">\r\n </div>\r\n \r\n <div *ngIf=\"hasImageError\" class=\"error-block\">\r\n \u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0444\u0430\u0439\u043B \u043D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043B\u0438 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.\r\n </div>\r\n\r\n <div *ngIf=\"hasFileId() && !hasImageError\">\r\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc()\" (error)=\"onErrorHandler()\"/>\r\n </div>\r\n\r\n <div *ngIf=\"!hasFileId()\">\r\n <h5>[\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043E]</h5>\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"!tag.presentOrEdit\">\r\n <div style=\"height: 10px;\"></div>\r\n\r\n <div style=\"overflow-x:auto;\">\r\n <mat-button-toggle-group [(ngModel)]=\"searchOrEdit\">\r\n <mat-button-toggle value=\"search\">\r\n \u0418\u0441\u043A\u0430\u0442\u044C \u0444\u0430\u0439\u043B <mat-icon>search</mat-icon>\r\n </mat-button-toggle>\r\n <mat-button-toggle value=\"edit\">\r\n \u0423\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443 <mat-icon>settings</mat-icon>\r\n </mat-button-toggle>\r\n </mat-button-toggle-group>\r\n </div>\r\n \r\n\r\n <div style=\"height: 10px;\"></div>\r\n\r\n <div [hidden]=\"searchOrEdit !== 'search'\">\r\n <croco-html-file-id-select\r\n [labelText]=\"'\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B'\"\r\n [(fileId)]=\"tag.attributes['file-id']\"\r\n (onFileIdChanged)=\"onFileIdChanged($event)\">\r\n </croco-html-file-id-select>\r\n </div>\r\n\r\n <div [hidden]=\"searchOrEdit !== 'edit'\">\r\n <div>\r\n <mat-form-field class=\"w-100\">\r\n <input matInput placeholder=\"\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430\" new-autocomplete=\"off\" autocomplete=\"off\"\r\n type=\"number\"\r\n [(ngModel)]=\"tag.attributes['file-id']\"\r\n (ngModelChange)=\"removeImageError()\">\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>", styles: [".error-block{background-color:#f32323;color:#fff;text-align:center;border-radius:10px;padding:10px}\n"] }]
539
- }], ctorParameters: () => [{ type: undefined, decorators: [{
540
- type: Inject,
541
- args: [CrocoHtmlOptionsToken]
542
- }] }], propDecorators: { tag: [{
543
- type: Input
544
- }], onTagUpdated: [{
545
- type: Output
546
- }] } });
547
-
548
- class XmlTagHtmlViewComponent {
549
- constructor() {
550
- this.html = "";
603
+ class TextMethods {
604
+ static ExtractRichTextData(elem) {
605
+ let children = [];
606
+ for (let i = 0; i < elem.children.length; i++) {
607
+ const child = elem.children.item(i);
608
+ if (child.tagName === "text-block".toUpperCase()) {
609
+ children.push({
610
+ type: "text-block",
611
+ data: {
612
+ text: child.innerHTML
613
+ }
614
+ });
615
+ }
616
+ else if (child.tagName === "line-break".toUpperCase()) {
617
+ children.push({
618
+ type: "line-break"
619
+ });
620
+ }
621
+ }
622
+ return {
623
+ type: "rich-text",
624
+ data: {
625
+ children
626
+ }
627
+ };
551
628
  }
552
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHtmlViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
553
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagHtmlViewComponent, selector: "croco-html-xml-tag-html-view", inputs: { html: "html" }, ngImport: i0, template: "<div class=\"col\" [innerHTML]=\"html\">\r\n</div>", styles: [""] }); }
554
629
  }
555
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHtmlViewComponent, decorators: [{
556
- type: Component,
557
- args: [{ selector: 'croco-html-xml-tag-html-view', template: "<div class=\"col\" [innerHTML]=\"html\">\r\n</div>" }]
558
- }], ctorParameters: () => [], propDecorators: { html: [{
559
- type: Input
560
- }] } });
561
630
 
562
- class XmlTagTextViewComponent {
563
- constructor() { }
564
- ngOnInit() {
565
- }
566
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagTextViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
567
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagTextViewComponent, selector: "croco-html-xml-tag-text-view", inputs: { item: "item" }, ngImport: i0, template: "<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'left'\" style=\"text-align: left;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <span *ngIf=\"item.data.html.length > 0\" [innerHtml]=\"item.data.html\"></span>\r\n</div>\r\n\r\n<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'right'\" style=\"text-align: right;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <span *ngIf=\"item.data.html.length > 0\" [innerHtml]=\"item.data.html\"></span>\r\n</div>\r\n\r\n<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'center'\" style=\"text-align: center;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <span *ngIf=\"item.data.html.length > 0\" [innerHtml]=\"item.data.html\"></span>\r\n</div>\r\n\r\n<div *ngIf=\"!item.data.validationResult.isSucceeded\" class=\"red\" style=\"margin-top: 10px;\" >\r\n <h4>\u0414\u043E\u043F\u0443\u0449\u0435\u043D\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0442\u0435\u0433\u0435 &lt;text&gt;</h4>\r\n <span>\r\n {{item.data.validationResult.message}}\r\n </span>\r\n</div>", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
631
+ class ExternalVideoTagDataConsts {
632
+ static { this.TagName = "external-video"; }
633
+ static { this.VideoTypeAttrName = "type"; }
634
+ static { this.LinkAttrName = "link"; }
568
635
  }
569
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagTextViewComponent, decorators: [{
570
- type: Component,
571
- args: [{ selector: 'croco-html-xml-tag-text-view', template: "<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'left'\" style=\"text-align: left;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <span *ngIf=\"item.data.html.length > 0\" [innerHtml]=\"item.data.html\"></span>\r\n</div>\r\n\r\n<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'right'\" style=\"text-align: right;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <span *ngIf=\"item.data.html.length > 0\" [innerHtml]=\"item.data.html\"></span>\r\n</div>\r\n\r\n<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'center'\" style=\"text-align: center;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <span *ngIf=\"item.data.html.length > 0\" [innerHtml]=\"item.data.html\"></span>\r\n</div>\r\n\r\n<div *ngIf=\"!item.data.validationResult.isSucceeded\" class=\"red\" style=\"margin-top: 10px;\" >\r\n <h4>\u0414\u043E\u043F\u0443\u0449\u0435\u043D\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0442\u0435\u0433\u0435 &lt;text&gt;</h4>\r\n <span>\r\n {{item.data.validationResult.message}}\r\n </span>\r\n</div>" }]
572
- }], ctorParameters: () => [], propDecorators: { item: [{
573
- type: Input
574
- }] } });
575
-
576
- class XmlTagHeaderInnerTextViewComponent {
577
- constructor() { }
578
- ngOnInit() {
579
- }
580
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHeaderInnerTextViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
581
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagHeaderInnerTextViewComponent, selector: "croco-html-xml-tag-header-inner-text-view", inputs: { item: "item" }, ngImport: i0, template: "<h1 *ngIf=\"item.type === 'h1'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h1>\r\n<h2 *ngIf=\"item.type === 'h2'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h2>\r\n<h3 *ngIf=\"item.type === 'h3'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h3>\r\n<h4 *ngIf=\"item.type === 'h4'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h4>\r\n<h5 *ngIf=\"item.type === 'h5'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h5>\r\n<h6 *ngIf=\"item.type === 'h6'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h6>", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
636
+ class ExternalVideoSupportedTypes {
637
+ static { this.Youtube = "youtube"; }
638
+ static { this.VkVideo = "vk-video"; }
582
639
  }
583
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHeaderInnerTextViewComponent, decorators: [{
584
- type: Component,
585
- args: [{ selector: 'croco-html-xml-tag-header-inner-text-view', template: "<h1 *ngIf=\"item.type === 'h1'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h1>\r\n<h2 *ngIf=\"item.type === 'h2'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h2>\r\n<h3 *ngIf=\"item.type === 'h3'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h3>\r\n<h4 *ngIf=\"item.type === 'h4'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h4>\r\n<h5 *ngIf=\"item.type === 'h5'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h5>\r\n<h6 *ngIf=\"item.type === 'h6'\" \r\n [innerHtml]=\"item.data.html\">\r\n</h6>" }]
586
- }], ctorParameters: () => [], propDecorators: { item: [{
587
- type: Input
588
- }] } });
589
-
590
- class XmlTagHeaderTextViewComponent {
591
- constructor() { }
592
- ngOnInit() {
640
+ const ExternalVideoPlayers = [
641
+ {
642
+ type: ExternalVideoSupportedTypes.Youtube,
643
+ displayValue: 'Youtube',
644
+ },
645
+ {
646
+ type: ExternalVideoSupportedTypes.VkVideo,
647
+ displayValue: 'Vk Video',
648
+ }
649
+ ];
650
+ class VideoMethods {
651
+ static ExtractExternalVideoTag(elem) {
652
+ return {
653
+ type: ExternalVideoTagDataConsts.TagName,
654
+ data: {
655
+ type: elem.getAttribute(ExternalVideoTagDataConsts.VideoTypeAttrName),
656
+ link: elem.getAttribute(ExternalVideoTagDataConsts.LinkAttrName)
657
+ }
658
+ };
593
659
  }
594
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHeaderTextViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
595
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagHeaderTextViewComponent, selector: "croco-html-xml-tag-header-text-view", inputs: { item: "item" }, ngImport: i0, template: "<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'left'\" style=\"text-align: left;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <croco-html-xml-tag-header-inner-text-view *ngIf=\"item.data.html.length > 0\" [item]=\"item\">\r\n </croco-html-xml-tag-header-inner-text-view>\r\n</div>\r\n\r\n<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'right'\" style=\"text-align: right;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <croco-html-xml-tag-header-inner-text-view *ngIf=\"item.data.html.length > 0\" [item]=\"item\">\r\n </croco-html-xml-tag-header-inner-text-view>\r\n</div>\r\n\r\n<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'center'\" style=\"text-align: center;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n\r\n <croco-html-xml-tag-header-inner-text-view *ngIf=\"item.data.html.length > 0\" [item]=\"item\">\r\n </croco-html-xml-tag-header-inner-text-view>\r\n</div>\r\n\r\n<div *ngIf=\"!item.data.validationResult.isSucceeded\" class=\"red\" style=\"margin-top: 10px;\" >\r\n <h4>\u0414\u043E\u043F\u0443\u0449\u0435\u043D\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0442\u0435\u0433\u0435 &lt;text&gt;</h4>\r\n <span>\r\n {{item.data.validationResult.message}}\r\n </span>\r\n</div>", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: XmlTagHeaderInnerTextViewComponent, selector: "croco-html-xml-tag-header-inner-text-view", inputs: ["item"] }] }); }
596
660
  }
597
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHeaderTextViewComponent, decorators: [{
598
- type: Component,
599
- args: [{ selector: 'croco-html-xml-tag-header-text-view', template: "<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'left'\" style=\"text-align: left;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <croco-html-xml-tag-header-inner-text-view *ngIf=\"item.data.html.length > 0\" [item]=\"item\">\r\n </croco-html-xml-tag-header-inner-text-view>\r\n</div>\r\n\r\n<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'right'\" style=\"text-align: right;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n <croco-html-xml-tag-header-inner-text-view *ngIf=\"item.data.html.length > 0\" [item]=\"item\">\r\n </croco-html-xml-tag-header-inner-text-view>\r\n</div>\r\n\r\n<div *ngIf=\"item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'center'\" style=\"text-align: center;\">\r\n <span *ngIf=\"item.data.html.length === 0 || !item.data.html\">&nbsp;</span>\r\n\r\n <croco-html-xml-tag-header-inner-text-view *ngIf=\"item.data.html.length > 0\" [item]=\"item\">\r\n </croco-html-xml-tag-header-inner-text-view>\r\n</div>\r\n\r\n<div *ngIf=\"!item.data.validationResult.isSucceeded\" class=\"red\" style=\"margin-top: 10px;\" >\r\n <h4>\u0414\u043E\u043F\u0443\u0449\u0435\u043D\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0442\u0435\u0433\u0435 &lt;text&gt;</h4>\r\n <span>\r\n {{item.data.validationResult.message}}\r\n </span>\r\n</div>" }]
600
- }], ctorParameters: () => [], propDecorators: { item: [{
601
- type: Input
602
- }] } });
603
661
 
604
- class HtmlRawViewComponent {
605
- constructor(_sanitizer) {
606
- this._sanitizer = _sanitizer;
607
- this.rawHtml = "";
608
- this.isInitialized = false;
662
+ class HtmlExtractionMethods {
663
+ static ExtractHeaderTag(elem, tagName) {
664
+ var data = TextSimpleMethods.ExtractTextTag(elem);
665
+ data.type = tagName;
666
+ return data;
609
667
  }
610
- ngOnInit() {
611
- this.safeHtml = this._sanitizer.bypassSecurityTrustHtml(this.rawHtml);
668
+ static { this.Extractors = {
669
+ ["TEXT"]: (elem, options) => TextSimpleMethods.ExtractTextTag(elem),
670
+ ["FILE-IMAGE"]: (elem, options) => ImageMethods.ExtractImage(elem, options),
671
+ ["TABLE"]: (elem, options) => TableMethods.getTableFromHtmlTag(elem, options),
672
+ ["RICH-TEXT"]: (elem, options) => TextMethods.ExtractRichTextData(elem),
673
+ ["HTML-RAW"]: (elem, options) => ({
674
+ type: "html-raw",
675
+ data: {
676
+ innerHTML: elem.innerHTML
677
+ }
678
+ }),
679
+ ["H1"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h1"),
680
+ ["H2"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h2"),
681
+ ["H3"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h3"),
682
+ ["H4"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h4"),
683
+ ["H5"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h5"),
684
+ ["H6"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h6"),
685
+ [ExternalVideoTagDataConsts.TagName.toUpperCase()]: (elem, options) => VideoMethods.ExtractExternalVideoTag(elem)
686
+ }; }
687
+ static transformHtmlElementToBlocks(element, options) {
688
+ var data = [];
689
+ for (let i = 0; i < element.children.length; i++) {
690
+ var elem = element.children.item(i);
691
+ if (!HtmlExtractionMethods.Extractors.hasOwnProperty(elem.tagName)) {
692
+ data.push({
693
+ type: "unsupported-tag",
694
+ data: {
695
+ tagString: elem.outerHTML
696
+ }
697
+ });
698
+ }
699
+ else {
700
+ var extractor = HtmlExtractionMethods.Extractors[elem.tagName];
701
+ var result = extractor(elem, options);
702
+ data.push(result);
703
+ }
704
+ }
705
+ return data;
706
+ }
707
+ static transformHtmlStringToBlocks(value, options) {
708
+ if (value === undefined || value === null) {
709
+ return [];
710
+ }
711
+ value = value
712
+ .replace('\n', '')
713
+ .replace('\t', '');
714
+ var div = document.createElement("div");
715
+ div.innerHTML = value;
716
+ return this.transformHtmlElementToBlocks(div, options);
612
717
  }
613
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: HtmlRawViewComponent, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
614
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: HtmlRawViewComponent, selector: "croco-html-raw-view", inputs: { rawHtml: "rawHtml" }, ngImport: i0, template: "<div [innerHTML]=\"safeHtml\">\n</div>", styles: [""] }); }
615
718
  }
616
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: HtmlRawViewComponent, decorators: [{
617
- type: Component,
618
- args: [{ selector: 'croco-html-raw-view', template: "<div [innerHTML]=\"safeHtml\">\n</div>" }]
619
- }], ctorParameters: () => [{ type: i1$2.DomSanitizer }], propDecorators: { rawHtml: [{
620
- type: Input
621
- }] } });
622
719
 
623
- class FileImageTagViewComponent {
624
- constructor() {
625
- this.imageSrc = "";
626
- }
627
- ngOnInit() {
628
- let data = this.item.data;
629
- this.imageSrc = data.src;
630
- }
631
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FileImageTagViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
632
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: FileImageTagViewComponent, selector: "croco-html-file-image-tag-view", inputs: { item: "item" }, ngImport: i0, template: "\r\n<img class=\"mx-auto d-block img-fluid\" [src]=\"imageSrc\" alt=\"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E\"/>", styles: [""] }); }
720
+ class HtmlRawTagDataConsts {
721
+ static { this.TagName = "html-raw"; }
633
722
  }
634
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FileImageTagViewComponent, decorators: [{
635
- type: Component,
636
- args: [{ selector: 'croco-html-file-image-tag-view', template: "\r\n<img class=\"mx-auto d-block img-fluid\" [src]=\"imageSrc\" alt=\"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E\"/>" }]
637
- }], propDecorators: { item: [{
638
- type: Input
639
- }] } });
640
723
 
641
- class XmlTagViewComponent {
642
- constructor() {
643
- this.data = [];
644
- }
645
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
646
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagViewComponent, selector: "croco-html-xml-tag-view", inputs: { data: "data" }, ngImport: i0, template: "<div>\r\n <div class=\"row\" *ngFor=\"let item of data\">\r\n <div *ngIf=\"item.type === 'text'\">\r\n <croco-html-xml-tag-text-view [item]=\"item\"></croco-html-xml-tag-text-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'html-raw'\">\r\n <croco-html-raw-view [rawHtml]=\"item.data.innerHTML\">\r\n </croco-html-raw-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'h1' || item.type === 'h2' || item.type === 'h3' || item.type === 'h4' || item.type === 'h5' || item.type === 'h6'\">\r\n <croco-html-xml-tag-header-text-view [item]=\"item\"></croco-html-xml-tag-header-text-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'file-image'\">\r\n <croco-html-file-image-tag-view [item]=\"item\" [viewOptions]=\"viewOptions\"></croco-html-file-image-tag-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'table'\">\r\n \r\n <croco-html-xml-tag-html-view *ngIf=\"item.validationResult.isSucceeded\" [html]=\"item.bootstrapHtml\">\r\n </croco-html-xml-tag-html-view>\r\n \r\n <app-tutor-baseapiresponse-banner \r\n *ngIf=\"item.validationResult && !item.validationResult.isSucceeded\" \r\n [message]=\"item.validationResult.message\">\r\n </app-tutor-baseapiresponse-banner>\r\n </div>\r\n \r\n <div *ngIf=\"item.type === 'rich-text'\">\r\n <croco-html-xml-tag-text-view [richTextData]=\"item\"></croco-html-xml-tag-text-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'external-video'\">\r\n <croco-html-xml-tag-external-video [data]=\"item\"></croco-html-xml-tag-external-video>\r\n </div>\r\n <div *ngIf=\"item.type === 'unsupported-tag'\" class=\"red\" style=\"margin-top: 10px;\" >\r\n <h4>\u0414\u0430\u043D\u043D\u044B\u0439 \u0442\u0435\u0433 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F</h4>\r\n <span>\r\n {{item.data.tagString}}\r\n </span>\r\n </div>\r\n </div>\r\n</div>", styles: [".red{background-color:#c94444;color:#fff}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: XmlTagHtmlViewComponent, selector: "croco-html-xml-tag-html-view", inputs: ["html"] }, { kind: "component", type: XmlTagTextViewComponent, selector: "croco-html-xml-tag-text-view", inputs: ["item"] }, { kind: "component", type: XmlTagHeaderTextViewComponent, selector: "croco-html-xml-tag-header-text-view", inputs: ["item"] }, { kind: "component", type: XmlTagExternalVideoComponent, selector: "croco-html-xml-tag-external-video", inputs: ["data", "tagData"] }, { kind: "component", type: HtmlRawViewComponent, selector: "croco-html-raw-view", inputs: ["rawHtml"] }, { kind: "component", type: FileImageTagViewComponent, selector: "croco-html-file-image-tag-view", inputs: ["item"] }], encapsulation: i0.ViewEncapsulation.None }); }
724
+ class Tags {
725
+ static { this.Text = TextTags.text; }
726
+ static { this.H1 = TextTags.h1; }
727
+ static { this.H2 = TextTags.h2; }
728
+ static { this.H3 = TextTags.h3; }
729
+ static { this.H4 = TextTags.h4; }
730
+ static { this.H5 = TextTags.h5; }
731
+ static { this.H6 = TextTags.h6; }
732
+ static { this.HtmlRaw = HtmlRawTagDataConsts.TagName; }
733
+ static { this.FileImage = FileImageTagDataConsts.TagName; }
734
+ static { this.Table = 'table'; }
735
+ static { this.RichText = 'rich-text'; }
736
+ static { this.ExternalVideo = ExternalVideoTagDataConsts.TagName; }
737
+ static { this.UnsupportedTag = 'unsupported-tag'; }
647
738
  }
648
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagViewComponent, decorators: [{
649
- type: Component,
650
- args: [{ selector: 'croco-html-xml-tag-view', encapsulation: ViewEncapsulation.None, template: "<div>\r\n <div class=\"row\" *ngFor=\"let item of data\">\r\n <div *ngIf=\"item.type === 'text'\">\r\n <croco-html-xml-tag-text-view [item]=\"item\"></croco-html-xml-tag-text-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'html-raw'\">\r\n <croco-html-raw-view [rawHtml]=\"item.data.innerHTML\">\r\n </croco-html-raw-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'h1' || item.type === 'h2' || item.type === 'h3' || item.type === 'h4' || item.type === 'h5' || item.type === 'h6'\">\r\n <croco-html-xml-tag-header-text-view [item]=\"item\"></croco-html-xml-tag-header-text-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'file-image'\">\r\n <croco-html-file-image-tag-view [item]=\"item\" [viewOptions]=\"viewOptions\"></croco-html-file-image-tag-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'table'\">\r\n \r\n <croco-html-xml-tag-html-view *ngIf=\"item.validationResult.isSucceeded\" [html]=\"item.bootstrapHtml\">\r\n </croco-html-xml-tag-html-view>\r\n \r\n <app-tutor-baseapiresponse-banner \r\n *ngIf=\"item.validationResult && !item.validationResult.isSucceeded\" \r\n [message]=\"item.validationResult.message\">\r\n </app-tutor-baseapiresponse-banner>\r\n </div>\r\n \r\n <div *ngIf=\"item.type === 'rich-text'\">\r\n <croco-html-xml-tag-text-view [richTextData]=\"item\"></croco-html-xml-tag-text-view>\r\n </div>\r\n <div *ngIf=\"item.type === 'external-video'\">\r\n <croco-html-xml-tag-external-video [data]=\"item\"></croco-html-xml-tag-external-video>\r\n </div>\r\n <div *ngIf=\"item.type === 'unsupported-tag'\" class=\"red\" style=\"margin-top: 10px;\" >\r\n <h4>\u0414\u0430\u043D\u043D\u044B\u0439 \u0442\u0435\u0433 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F</h4>\r\n <span>\r\n {{item.data.tagString}}\r\n </span>\r\n </div>\r\n </div>\r\n</div>", styles: [".red{background-color:#c94444;color:#fff}\n"] }]
651
- }], ctorParameters: () => [], propDecorators: { data: [{
652
- type: Input
653
- }] } });
654
739
 
655
- class AngularMaterialTableMethods {
656
- static getAngularMaterialTableData(columns, rows) {
657
- let data = [];
658
- for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
659
- const row = rows[rowIndex];
660
- var elem = {};
661
- for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {
662
- const column = columns[columnIndex];
663
- elem[column] = row.columns[columnIndex].data.text;
740
+ class BodyTagsExtensions {
741
+ static getDescription(tagName) {
742
+ var descriptions = {
743
+ "text": "Текст",
744
+ "h1": "Заголовок 1 уровня",
745
+ "h2": "Заголовок 2 уровня",
746
+ "h3": "Заголовок 3 уровня",
747
+ "h4": "Заголовок 4 уровня",
748
+ "h5": "Заголовок 5 уровня",
749
+ "h6": "Заголовок 6 уровня",
750
+ [FileImageTagDataConsts.TagName]: "Изображение",
751
+ [ExternalVideoTagDataConsts.TagName]: "Внешнее видео",
752
+ [HtmlRawTagDataConsts.TagName]: "Html разметка"
753
+ };
754
+ return descriptions[tagName];
755
+ }
756
+ static toHtml(bodyTags) {
757
+ let htmls = bodyTags.map(x => {
758
+ if (TextTags.allTextTags.includes(x.tagDescription.tag)) {
759
+ return `<${x.tagDescription.tag} h-align="${x.attributes['h-align']}">${x.innerHtml}</${x.tagDescription.tag}>`;
664
760
  }
665
- data.push(elem);
761
+ if (x.tagDescription.tag === ExternalVideoTagDataConsts.TagName) {
762
+ return `<${x.tagDescription.tag} type="${x.attributes['type']}" link="${x.attributes['link']}">${x.innerHtml}</${x.tagDescription.tag}>`;
763
+ }
764
+ if (x.tagDescription.tag === "html-raw") {
765
+ return `<${x.tagDescription.tag}>${x.innerHtml}</${x.tagDescription.tag}>`;
766
+ }
767
+ return BodyTagsExtensions.imageTagToHtml(x);
768
+ });
769
+ let result = "";
770
+ for (let index = 0; index < htmls.length; index++) {
771
+ const element = htmls[index];
772
+ result += element;
666
773
  }
667
- return {
668
- displayedColumns: columns,
669
- data: data,
670
- };
774
+ return result;
671
775
  }
672
- static checkHeaders(tableData) {
673
- if (tableData.header === null) {
776
+ static imageTagToHtml(imageTag) {
777
+ var attrStr = "";
778
+ var attrValue = imageTag.attributes[FileImageTagDataConsts.FileIdAttrName];
779
+ if (imageTag.attributes.hasOwnProperty(FileImageTagDataConsts.FileIdAttrName) && attrValue) {
780
+ attrStr = `${FileImageTagDataConsts.FileIdAttrName}="${attrValue}"`;
781
+ }
782
+ return `<${FileImageTagDataConsts.TagName} ${attrStr}></${FileImageTagDataConsts.TagName}>`;
783
+ }
784
+ static getBodyTags(html, options) {
785
+ let result = HtmlExtractionMethods.transformHtmlStringToBlocks(html, options);
786
+ return result.map(x => BodyTagsExtensions.toBodyTag(x));
787
+ }
788
+ static sanitizeInnerHtml(html) {
789
+ return html.trim().replace('\n\t', '');
790
+ }
791
+ static toBodyTag(data) {
792
+ if (TextTags.allTextTags.includes(data.type)) {
793
+ let textTagData = data.data;
674
794
  return {
675
- isSucceeded: false,
676
- message: "Необходимо указать заголовок таблицы"
795
+ presentOrEdit: true,
796
+ tagDescription: {
797
+ tag: textTagData.textTagName,
798
+ displayValue: BodyTagsExtensions.getDescription(data.type)
799
+ },
800
+ attributes: { "h-align": textTagData.horizontalAlignment },
801
+ innerHtml: BodyTagsExtensions.sanitizeInnerHtml(textTagData.html)
677
802
  };
678
803
  }
679
- let columns = tableData.header.columns;
680
- var uniqueDislayedColumns = columns.filter((v, i, a) => a.indexOf(v) === i);
681
- if (uniqueDislayedColumns.length !== columns.length) {
804
+ if (data.type === FileImageTagDataConsts.TagName) {
805
+ let fileData = data.data;
806
+ let attrs = {};
807
+ if (fileData.fileId) {
808
+ attrs[FileImageTagDataConsts.FileIdAttrName] = fileData.fileId;
809
+ }
682
810
  return {
683
- isSucceeded: false,
684
- message: "Ошибка при обработке разметки таблицы. Обнаружены дубликаты заголовков."
811
+ presentOrEdit: true,
812
+ tagDescription: {
813
+ tag: FileImageTagDataConsts.TagName,
814
+ displayValue: BodyTagsExtensions.getDescription(data.type)
815
+ },
816
+ attributes: attrs,
817
+ innerHtml: ""
685
818
  };
686
819
  }
687
- return {
688
- isSucceeded: true,
689
- message: "Ok"
690
- };
691
- }
692
- static checkAngularMaterialTableData(tableData, checkHeaders = true) {
693
- if (checkHeaders) {
694
- var checkHeadersResult = this.checkHeaders(tableData);
695
- if (!checkHeadersResult.isSucceeded) {
696
- return checkHeadersResult;
697
- }
820
+ if (data.type === ExternalVideoTagDataConsts.TagName) {
821
+ let fileData = data.data;
822
+ return {
823
+ presentOrEdit: true,
824
+ tagDescription: {
825
+ tag: data.type,
826
+ displayValue: BodyTagsExtensions.getDescription(data.type)
827
+ },
828
+ attributes: fileData,
829
+ innerHtml: ""
830
+ };
698
831
  }
699
- let rows = tableData.rows;
700
- let columns = tableData.header.columns;
701
- for (let i = 0; i < rows.length; i++) {
702
- const row = rows[i];
703
- if (row.columns.length !== columns.length) {
704
- return {
705
- isSucceeded: false,
706
- message: `Ошибка при обработке разметки таблицы. `
707
- + `Количество колонок в каждой строке таблицы должно соотвествовать количеству колонок указанных в заголовке. `
708
- + `В строке таблицы №${i + 1} количество колонок = ${row.columns.length}, а должно быть ${columns.length}.`
709
- };
710
- }
832
+ if (data.type === HtmlRawTagDataConsts.TagName) {
833
+ return {
834
+ presentOrEdit: true,
835
+ tagDescription: {
836
+ tag: HtmlRawTagDataConsts.TagName,
837
+ displayValue: BodyTagsExtensions.getDescription(data.type)
838
+ },
839
+ attributes: {},
840
+ innerHtml: BodyTagsExtensions.sanitizeInnerHtml(data.data["innerHTML"])
841
+ };
711
842
  }
712
843
  return {
713
- isSucceeded: true,
714
- message: "Ok"
844
+ presentOrEdit: true,
845
+ tagDescription: {
846
+ tag: Tags.UnsupportedTag,
847
+ displayValue: "Неподдерживаемый тег"
848
+ },
849
+ attributes: {},
850
+ innerHtml: JSON.stringify(data)
715
851
  };
716
852
  }
717
853
  }
718
854
 
719
- var EAlignments;
720
- (function (EAlignments) {
721
- EAlignments["Left"] = "left";
722
- EAlignments["Center"] = "center";
723
- EAlignments["Right"] = "right";
724
- })(EAlignments || (EAlignments = {}));
725
- const AlignmentsData = [
726
- { value: EAlignments.Left, text: 'Слева' },
727
- { value: EAlignments.Center, text: 'По центру' },
728
- { value: EAlignments.Right, text: 'Справа' },
729
- ];
730
-
731
- const TextTag = "text";
732
- class TextSimpleMethods {
733
- static { this.supportedTags = ["sup", "sub", "strong", "b", "i", "u"]; }
734
- static ExtractTextTag(elem) {
735
- var hAlignValue = elem.getAttribute("h-align") ?? EAlignments.Left;
736
- var data = {
737
- textTagName: elem.tagName.toLowerCase(),
738
- text: elem.innerText.trim().replace('\n\t', ''),
739
- html: elem.innerHTML.trim().replace('\n\t', ''),
740
- horizontalAlignment: hAlignValue,
741
- validationResult: {
742
- isSucceeded: true,
743
- message: "Ok"
744
- }
745
- };
746
- let result = {
747
- type: TextTag,
748
- data: data
749
- };
750
- if (result.data.text === '\n') {
751
- result.data.text = '';
752
- }
753
- if (result.data.html === '\n') {
754
- result.data.html = '';
755
- }
756
- var alignmentVals = [EAlignments.Left, EAlignments.Right, EAlignments.Center];
757
- if (alignmentVals.indexOf(hAlignValue) < 0) {
758
- result.data.validationResult = {
759
- isSucceeded: false,
760
- message: `Недопустимое значение атрибута h-align. Допустимые значения: ${alignmentVals.join(', ')}. `
761
- + 'Данный тег можно не указывать, по-умолчанию будет применено выравнивание слева.'
762
- };
763
- }
764
- var html = result.data.html;
765
- var htmlValidation = this.ValidateTextHtml(html);
766
- if (!htmlValidation.isSucceeded) {
767
- result.data.validationResult = htmlValidation;
768
- }
769
- return result;
855
+ class XmlExtensions {
856
+ static formatXml(xml, tab = '\t') {
857
+ var formatted = '', indent = '';
858
+ tab = tab || '\t';
859
+ xml.split(/>\s*</).forEach(function (node) {
860
+ if (node.match(/^\/\w/))
861
+ indent = indent.substring(tab.length); // decrease indent by one 'tab'
862
+ formatted += indent + '<' + node + '>\r\n';
863
+ if (node.match(/^<?\w[^>]*[^\/]$/))
864
+ indent += tab; // increase indent
865
+ });
866
+ return formatted.substring(1, formatted.length - 3);
770
867
  }
771
- static ValidateTextHtml(html) {
772
- var p = document.createElement("p");
773
- p.innerHTML = html;
774
- for (let i = 0; i < p.children.length; i++) {
775
- const element = p.children.item(i);
776
- var validationResult = this.ValidateTag(element);
777
- if (!validationResult.isSucceeded) {
778
- return validationResult;
779
- }
780
- }
781
- return {
782
- isSucceeded: true,
783
- message: `Ok`
784
- };
868
+ static tagsToLower(xml) {
869
+ xml = this.replaceTagToLower(xml, "Body");
870
+ xml = this.replaceTagToLower(xml, "Image");
871
+ xml = this.replaceTagToLower(xml, "Text");
872
+ return xml;
785
873
  }
786
- static ValidateTag(element) {
787
- let lowerTag = element.tagName.toLowerCase();
788
- if (!this.supportedTags.includes(lowerTag)) {
789
- return {
790
- isSucceeded: false,
791
- message: `Тег <${lowerTag}> не поддерживается внутри тега <text>`
792
- };
793
- }
794
- for (let i = 0; i < element.children.length; i++) {
795
- const nElement = element.children.item(i);
796
- var innerValidationResult = this.ValidateTag(nElement);
797
- if (!innerValidationResult.isSucceeded) {
798
- return innerValidationResult;
799
- }
800
- }
801
- return {
802
- isSucceeded: true,
803
- message: "Ok"
804
- };
874
+ static replaceTagToLower(xml, tag) {
875
+ return xml
876
+ .replace(new RegExp(`<${tag}`, 'g'), `<${tag.toLowerCase()}`)
877
+ .replace(new RegExp(`</${tag}>`, 'g'), `</${tag.toLowerCase()}>`);
805
878
  }
806
879
  }
807
880
 
808
- class BootstrapTableMethods {
809
- static BuildTable(data) {
810
- let result = `<table class="table table-bordered">`;
811
- result += this.BuildHeader(data.header);
812
- result += this.BuildBody(data.rows);
881
+ class TableBuilder {
882
+ static getTableMarkUp(rows, cols, generateHeaders) {
883
+ rows = +rows;
884
+ cols = +cols;
885
+ let result = "<table>";
886
+ if (generateHeaders) {
887
+ result += TableBuilder.getTableHeaderMarkUp(cols);
888
+ }
889
+ result += TableBuilder.getTableBodyMarkUp(cols, rows);
813
890
  result += "</table>";
814
- return result;
891
+ return XmlExtensions.formatXml(result);
815
892
  }
816
- static BuildHeader(data) {
817
- if (data === null) {
818
- return "";
819
- }
820
- let result = "<thead>";
821
- result += "<tr>";
822
- for (let index = 0; index < data.columns.length; index++) {
823
- result += `<th>${data.columns[index]}</th>`;
893
+ static getTableHeaderMarkUp(cols) {
894
+ let result = "<thead><tr>";
895
+ for (let i = 0; i < cols; i++) {
896
+ result += `<th>Колонка #${i + 1}</th>`;
824
897
  }
825
- result += "</tr>";
826
- result += "</thead>";
898
+ result += "</tr></thead>";
827
899
  return result;
828
900
  }
829
- static BuildBody(rows) {
901
+ static getTableBodyMarkUp(cols, rows) {
830
902
  let result = "<tbody>";
831
- for (let i = 0; i < rows.length; i++) {
832
- const row = rows[i];
903
+ for (let row = 0; row < rows; row++) {
833
904
  result += "<tr>";
834
- for (let j = 0; j < row.columns.length; j++) {
835
- const col = row.columns[j];
836
- result += `<td class="align-middle">${this.BuildInnerTags(col.data.children)}</td>`;
905
+ for (let i = 0; i < cols; i++) {
906
+ result += `<td>Ряд№${row + 1} Колонка #${i + 1}</td>`;
837
907
  }
838
908
  result += "</tr>";
839
909
  }
840
910
  result += "</tbody>";
841
911
  return result;
842
912
  }
843
- static BuildInnerTags(tags) {
844
- let result = "";
845
- for (let i = 0; i < tags.length; i++) {
846
- result += this.BuildInnerTag(tags[i]);
847
- }
848
- return result;
913
+ }
914
+
915
+ function resizeObservable(elem, options) {
916
+ return new Observable((subscriber) => {
917
+ const resizeObserver = new ResizeObserver(([entry]) => {
918
+ subscriber.next(entry);
919
+ });
920
+ resizeObserver.observe(elem, options);
921
+ return function unsubscribe() {
922
+ resizeObserver.unobserve(elem);
923
+ };
924
+ });
925
+ }
926
+
927
+ class VkVideoPlayerComponent {
928
+ set link(link) {
929
+ this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(link);
849
930
  }
850
- static BuildInnerTag(data) {
851
- if (data.type === FileImageTagDataConsts.TagName) {
852
- let fileImageTag = data;
853
- return `<img src=${fileImageTag.data.src} class="mx-auto d-block img-fluid" />`;
854
- }
855
- else if (data.type === TextTag) {
856
- let simpleTextTag = data;
857
- var map = {
858
- ["left"]: "text-start",
859
- ["center"]: "text-center",
860
- ["right"]: "text-end"
861
- };
862
- if (!simpleTextTag.data.validationResult.isSucceeded) {
863
- return `<span>Ошибка в тексте ${simpleTextTag.data.validationResult.message}</span>`;
864
- }
865
- return `<div class="${map[simpleTextTag.data.horizontalAlignment]}"><span>${simpleTextTag.data.html}</span></div>`;
866
- }
867
- else {
868
- return `<p>Тег ${data.type} не поддерживается</p>`;
869
- }
931
+ constructor(sanitizer) {
932
+ this.sanitizer = sanitizer;
870
933
  }
934
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: VkVideoPlayerComponent, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
935
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: VkVideoPlayerComponent, isStandalone: true, selector: "vk-video-player", inputs: { link: "link" }, ngImport: i0, template: "<div class=\"vk-video-player\">\n <iframe\n [src]=\"safeUrl\"\n width=\"100%\"\n height=\"100%\"\n allow=\"autoplay; encrypted-media; fullscreen; picture-in-picture;\"\n frameborder=\"0\"\n allowfullscreen></iframe>\n</div>\n", styles: [".vk-video-player{margin:0 auto;max-width:640px;width:100%;height:360px}@media screen and (max-width: 760px){.vk-video-player{height:300px}}@media screen and (max-width: 540px){.vk-video-player{height:250px}}@media screen and (max-width: 450px){.vk-video-player{height:200px}}@media screen and (max-width: 380px){.vk-video-player{height:180px}}\n"] }); }
871
936
  }
872
-
873
- class TableTypes {
874
- static { this.TableRowColumnData = "table-row-column-data"; }
875
- static { this.Table = "table"; }
876
- static { this.TableRowColumn = "table-row-column"; }
877
- }
878
- class TableMethods {
879
- static getTableFromHtmlTag(tableTag, options) {
880
- let tableData = {
881
- header: TableMethods.getHeader(tableTag),
882
- rows: TableMethods.getTableRows(tableTag, options)
883
- };
884
- var result = {
885
- type: TableTypes.Table,
886
- data: tableData,
887
- validationResult: this.checkTable(tableData),
888
- bootstrapHtml: ""
937
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: VkVideoPlayerComponent, decorators: [{
938
+ type: Component,
939
+ args: [{ selector: 'vk-video-player', standalone: true, imports: [], template: "<div class=\"vk-video-player\">\n <iframe\n [src]=\"safeUrl\"\n width=\"100%\"\n height=\"100%\"\n allow=\"autoplay; encrypted-media; fullscreen; picture-in-picture;\"\n frameborder=\"0\"\n allowfullscreen></iframe>\n</div>\n", styles: [".vk-video-player{margin:0 auto;max-width:640px;width:100%;height:360px}@media screen and (max-width: 760px){.vk-video-player{height:300px}}@media screen and (max-width: 540px){.vk-video-player{height:250px}}@media screen and (max-width: 450px){.vk-video-player{height:200px}}@media screen and (max-width: 380px){.vk-video-player{height:180px}}\n"] }]
940
+ }], ctorParameters: () => [{ type: i1$2.DomSanitizer }], propDecorators: { link: [{
941
+ type: Input
942
+ }] } });
943
+
944
+ class XmlTagExternalVideoComponent {
945
+ set data(value) {
946
+ this.tagData = value.data;
947
+ }
948
+ ;
949
+ set tagData(value) {
950
+ this._block = {
951
+ type: value.type,
952
+ link: value.link
889
953
  };
890
- if (!result.validationResult) {
891
- return result;
954
+ if (this._block.type === ExternalVideoSupportedTypes.VkVideo) {
955
+ return;
892
956
  }
893
- result.bootstrapHtml = BootstrapTableMethods.BuildTable(result.data);
894
- var angularMaterialTableDataCheck = AngularMaterialTableMethods.checkAngularMaterialTableData(tableData);
895
- if (!angularMaterialTableDataCheck.isSucceeded) {
896
- return {
897
- ...result,
898
- angularMaterialTableDataCheck
899
- };
900
- }
901
- return {
902
- ...result,
903
- angularMaterialTableDataCheck,
904
- html: tableTag.outerHTML,
905
- angularMaterialTableData: AngularMaterialTableMethods.getAngularMaterialTableData(tableData.header.columns, tableData.rows),
906
- };
957
+ this.videoId = this.getYouTubeId(this._block.link);
907
958
  }
908
- static checkTable(tableData) {
909
- let rows = tableData.rows;
910
- let prevRowCount = -1;
911
- for (let i = 0; i < rows.length; i++) {
912
- const row = rows[i];
913
- if (row.columns.length !== prevRowCount && prevRowCount != -1) {
914
- return {
915
- isSucceeded: false,
916
- message: `Ошибка при обработке разметки таблицы. `
917
- + `Количество колонок в каждой строке таблицы должно соотвествовать друг другу. `
918
- + `В строке таблицы №${i + 1} количество колонок = ${row.columns.length}, а в строке выше ${prevRowCount}.`
919
- };
920
- }
921
- prevRowCount = row.columns.length;
922
- }
923
- return {
924
- isSucceeded: true,
925
- message: "Ok"
959
+ ;
960
+ constructor(destroyRef) {
961
+ this.destroyRef = destroyRef;
962
+ this._block = {
963
+ type: '',
964
+ link: ''
926
965
  };
966
+ this.playerWidth = signal(NaN);
967
+ this.playerHeight = signal(NaN);
968
+ this.ExternalVideoSupportedTypes = ExternalVideoSupportedTypes;
927
969
  }
928
- static getHeader(tableTag) {
929
- let header = tableTag.tHead;
930
- if (header === null) {
931
- return null;
970
+ ngOnInit() {
971
+ if (this._block.type === ExternalVideoSupportedTypes.VkVideo) {
972
+ return;
932
973
  }
933
- let tr = header.children.item(0);
934
- let headerColumns = [];
935
- for (let j = 0; j < tr.children.length; j++) {
936
- const jElement = tr.children.item(j);
937
- headerColumns.push(jElement.innerHTML);
974
+ const youtubeIframeApiUrl = 'https://www.youtube.com/iframe_api';
975
+ if (!document.querySelector(`script[src="${youtubeIframeApiUrl}"]`)) {
976
+ // This code loads the IFrame Player API code asynchronously, according to the instructions at
977
+ // https://developers.google.com/youtube/iframe_api_reference#Getting_Started
978
+ const tag = document.createElement('script');
979
+ tag.setAttribute('src', youtubeIframeApiUrl);
980
+ document.body.appendChild(tag);
938
981
  }
939
- return {
940
- type: "table-header",
941
- columns: headerColumns
942
- };
943
- }
944
- static getTableRows(tableTag, options) {
945
- let tBody = tableTag.tBodies.item(0);
946
- let rows = [];
947
- for (let i = 0; i < tBody.children.length; i++) {
948
- const iElement = tBody.children.item(i);
949
- let rowColumns = [];
950
- for (let j = 0; j < iElement.children.length; j++) {
951
- const jElement = iElement.children.item(j);
952
- let children = HtmlExtractionMethods.transformHtmlElementToBlocks(jElement, options);
953
- if (children.length === 0) {
954
- var textTag = document.createElement("p");
955
- textTag.innerHTML = jElement.innerHTML;
956
- var textElem = TextSimpleMethods.ExtractTextTag(textTag);
957
- children.push(textElem);
958
- }
959
- var result = {
960
- type: TableTypes.TableRowColumnData,
961
- data: {
962
- text: jElement.innerHTML,
963
- children
964
- }
965
- };
966
- rowColumns.push(result);
967
- }
968
- rows.push({
969
- type: TableTypes.TableRowColumn,
970
- columns: rowColumns
982
+ if (this.playerContainerRef) {
983
+ resizeObservable(this.playerContainerRef.nativeElement)
984
+ .pipe(map(({ contentRect: { height, width } }) => ({ height, width })), distinctUntilChanged((a, b) => a.height === b.height && a.width === b.width), takeUntilDestroyed(this.destroyRef))
985
+ .subscribe(({ height, width }) => {
986
+ this.playerHeight.set(height);
987
+ this.playerWidth.set(width);
971
988
  });
972
989
  }
973
- return rows;
974
990
  }
991
+ getYouTubeId(youtubeLink) {
992
+ //https://www.youtube.com/watch?v=l3KfbfkxJOU
993
+ const url = new URL(youtubeLink);
994
+ if (url.pathname.endsWith('watch')) {
995
+ return url.searchParams.get("v");
996
+ }
997
+ //https://youtu.be/jzBneaWSswY
998
+ const bits = url.pathname.split('/');
999
+ return bits[bits.length - 1];
1000
+ }
1001
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagExternalVideoComponent, deps: [{ token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Component }); }
1002
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: XmlTagExternalVideoComponent, selector: "croco-html-xml-tag-external-video", inputs: { data: "data", tagData: "tagData" }, viewQueries: [{ propertyName: "playerContainerRef", first: true, predicate: ["playerContainer"], descendants: true, static: true }], ngImport: i0, template: "@switch (_block.type) {\n @case (ExternalVideoSupportedTypes.VkVideo) {\n <vk-video-player [link]=\"_block.link\"></vk-video-player>\n }\n @case (ExternalVideoSupportedTypes.Youtube) {\n <div #playerContainer class=\"d-flex justify-content-center y-video\">\n @if (videoId) {\n <youtube-player [height]=\"playerHeight()\" [width]=\"playerWidth()\" [videoId]=\"videoId\"></youtube-player>\n }\n </div>\n }\n}\n", styles: ["@media only screen and (min-width: 769px){.y-video{display:block;width:640px;height:360px;margin:0 auto}}@media only screen and (max-width: 827px){.y-video{display:block;width:100%;height:315px}}\n"], dependencies: [{ kind: "component", type: i1$3.YouTubePlayer, selector: "youtube-player", inputs: ["videoId", "height", "width", "startSeconds", "endSeconds", "suggestedQuality", "playerVars", "disableCookies", "loadApi", "disablePlaceholder", "showBeforeIframeApiLoads", "placeholderButtonLabel", "placeholderImageQuality"], outputs: ["ready", "stateChange", "error", "apiChange", "playbackQualityChange", "playbackRateChange"] }, { kind: "component", type: VkVideoPlayerComponent, selector: "vk-video-player", inputs: ["link"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
975
1003
  }
1004
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagExternalVideoComponent, decorators: [{
1005
+ type: Component,
1006
+ args: [{ selector: 'croco-html-xml-tag-external-video', changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (_block.type) {\n @case (ExternalVideoSupportedTypes.VkVideo) {\n <vk-video-player [link]=\"_block.link\"></vk-video-player>\n }\n @case (ExternalVideoSupportedTypes.Youtube) {\n <div #playerContainer class=\"d-flex justify-content-center y-video\">\n @if (videoId) {\n <youtube-player [height]=\"playerHeight()\" [width]=\"playerWidth()\" [videoId]=\"videoId\"></youtube-player>\n }\n </div>\n }\n}\n", styles: ["@media only screen and (min-width: 769px){.y-video{display:block;width:640px;height:360px;margin:0 auto}}@media only screen and (max-width: 827px){.y-video{display:block;width:100%;height:315px}}\n"] }]
1007
+ }], ctorParameters: () => [{ type: i0.DestroyRef }], propDecorators: { data: [{
1008
+ type: Input
1009
+ }], tagData: [{
1010
+ type: Input
1011
+ }], playerContainerRef: [{
1012
+ type: ViewChild,
1013
+ args: ['playerContainer', { static: true }]
1014
+ }] } });
976
1015
 
977
- class TextMethods {
978
- static { this.textTags = ["text", "h1", "h2", "h3", "h4", "h5", "h6"]; }
979
- static ExtractRichTextData(elem) {
980
- let children = [];
981
- for (let i = 0; i < elem.children.length; i++) {
982
- const child = elem.children.item(i);
983
- if (child.tagName === "text-block".toUpperCase()) {
984
- children.push({
985
- type: "text-block",
986
- data: {
987
- text: child.innerHTML
988
- }
989
- });
990
- }
991
- else if (child.tagName === "line-break".toUpperCase()) {
992
- children.push({
993
- type: "line-break"
994
- });
995
- }
996
- }
997
- return {
998
- type: "rich-text",
999
- data: {
1000
- children
1001
- }
1016
+ class ExternalVideoBlockComponent {
1017
+ constructor() {
1018
+ this.onTagUpdated = new EventEmitter();
1019
+ this.defaultYoutubeLink = "https://youtu.be/jzBneaWSswY";
1020
+ this.defaultVkLink = "https://vk.com/video_ext.php?oid=-22822305&id=456241864&hd=2";
1021
+ this.ExternalVideoSupportedTypes = ExternalVideoSupportedTypes;
1022
+ this.tagData = {
1023
+ link: this.defaultYoutubeLink,
1024
+ type: ExternalVideoSupportedTypes.Youtube
1002
1025
  };
1003
1026
  }
1027
+ ngOnInit() {
1028
+ this.tagData.link = this.tag.attributes.type === ExternalVideoSupportedTypes.VkVideo ? this.defaultVkLink : this.defaultYoutubeLink;
1029
+ this.tagData.type = this.tag.attributes.type;
1030
+ }
1031
+ linkChanged() {
1032
+ this.tag.attributes = this.tagData;
1033
+ }
1034
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: ExternalVideoBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1035
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: ExternalVideoBlockComponent, selector: "croco-html-external-video-block", inputs: { tag: "tag" }, outputs: { onTagUpdated: "onTagUpdated" }, ngImport: i0, template: "@if (tag.presentOrEdit) {\n <div>\n <div>\n @switch (tagData.type) {\n @case (ExternalVideoSupportedTypes.VkVideo) {\n \u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 Vk Video: {{tagData.link}}\n }\n @case (ExternalVideoSupportedTypes.Youtube) {\n \u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 YouTube: {{tagData.link}}\n }\n }\n </div>\n <div style=\"height: 10px;\"></div>\n <croco-html-xml-tag-external-video [tagData]=\"tagData\"></croco-html-xml-tag-external-video>\n </div>\n}\n\n@if (!tag.presentOrEdit) {\n <div>\n <div>\n <div>\n <mat-form-field class=\"w-100\">\n <input matInput placeholder=\"\u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 YouTube\"\n autocomplete=\"off\"\n [(ngModel)]=\"tagData.link\"\n (ngModelChange)=\"linkChanged()\">\n </mat-form-field>\n </div>\n </div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "directive", type: i1$4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: XmlTagExternalVideoComponent, selector: "croco-html-xml-tag-external-video", inputs: ["data", "tagData"] }] }); }
1036
+ }
1037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: ExternalVideoBlockComponent, decorators: [{
1038
+ type: Component,
1039
+ args: [{ selector: 'croco-html-external-video-block', template: "@if (tag.presentOrEdit) {\n <div>\n <div>\n @switch (tagData.type) {\n @case (ExternalVideoSupportedTypes.VkVideo) {\n \u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 Vk Video: {{tagData.link}}\n }\n @case (ExternalVideoSupportedTypes.Youtube) {\n \u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 YouTube: {{tagData.link}}\n }\n }\n </div>\n <div style=\"height: 10px;\"></div>\n <croco-html-xml-tag-external-video [tagData]=\"tagData\"></croco-html-xml-tag-external-video>\n </div>\n}\n\n@if (!tag.presentOrEdit) {\n <div>\n <div>\n <div>\n <mat-form-field class=\"w-100\">\n <input matInput placeholder=\"\u0421\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 YouTube\"\n autocomplete=\"off\"\n [(ngModel)]=\"tagData.link\"\n (ngModelChange)=\"linkChanged()\">\n </mat-form-field>\n </div>\n </div>\n </div>\n}\n" }]
1040
+ }], propDecorators: { tag: [{
1041
+ type: Input
1042
+ }], onTagUpdated: [{
1043
+ type: Output
1044
+ }] } });
1045
+
1046
+ class HtmlRawEditorComponent {
1047
+ constructor() {
1048
+ this.onTagUpdated = new EventEmitter();
1049
+ }
1050
+ ngOnInit() {
1051
+ }
1052
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: HtmlRawEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1053
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: HtmlRawEditorComponent, selector: "croco-html-html-raw-editor", inputs: { tag: "tag" }, outputs: { onTagUpdated: "onTagUpdated" }, ngImport: i0, template: "@if (tag.presentOrEdit) {\n <div>\n <div [innerHTML]=\"tag.innerHtml\"></div>\n </div>\n}\n\n@if (!tag.presentOrEdit) {\n <div>\n <div style=\"height: 10px;\">\n </div>\n <div>\n <mat-form-field class=\"w-100\">\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u0433\u0430\"\n [(ngModel)]=\"tag.innerHtml\"></textarea>\n </mat-form-field>\n </div>\n </div>\n}\n\n", styles: [""], dependencies: [{ kind: "directive", type: i1$4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i4.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }] }); }
1004
1054
  }
1055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: HtmlRawEditorComponent, decorators: [{
1056
+ type: Component,
1057
+ args: [{ selector: 'croco-html-html-raw-editor', template: "@if (tag.presentOrEdit) {\n <div>\n <div [innerHTML]=\"tag.innerHtml\"></div>\n </div>\n}\n\n@if (!tag.presentOrEdit) {\n <div>\n <div style=\"height: 10px;\">\n </div>\n <div>\n <mat-form-field class=\"w-100\">\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u0433\u0430\"\n [(ngModel)]=\"tag.innerHtml\"></textarea>\n </mat-form-field>\n </div>\n </div>\n}\n\n" }]
1058
+ }], ctorParameters: () => [], propDecorators: { tag: [{
1059
+ type: Input
1060
+ }], onTagUpdated: [{
1061
+ type: Output
1062
+ }] } });
1005
1063
 
1006
- class HtmlExtractionMethods {
1007
- static ExtractHeaderTag(elem, tagName) {
1008
- var data = TextSimpleMethods.ExtractTextTag(elem);
1009
- data.type = tagName;
1010
- return data;
1064
+ const CrocoHtmlOptionsToken = "croco-html-options";
1065
+
1066
+ var FileType;
1067
+ (function (FileType) {
1068
+ FileType["Undefined"] = "Undefined";
1069
+ FileType["Unknown"] = "Unknown";
1070
+ FileType["Image"] = "Image";
1071
+ FileType["Audio"] = "Audio";
1072
+ FileType["Video"] = "Video";
1073
+ FileType["Document"] = "Document";
1074
+ FileType["Archive"] = "Archive";
1075
+ })(FileType || (FileType = {}));
1076
+ class FilesQueryService {
1077
+ constructor(_httpClient, baseUrl) {
1078
+ this._httpClient = _httpClient;
1079
+ this._baseControllerUrl = `${baseUrl}Api/Files`;
1011
1080
  }
1012
- static { this.Extractors = {
1013
- ["TEXT"]: (elem, options) => TextSimpleMethods.ExtractTextTag(elem),
1014
- ["FILE-IMAGE"]: (elem, options) => ImageMethods.ExtractImage(elem, options),
1015
- ["TABLE"]: (elem, options) => TableMethods.getTableFromHtmlTag(elem, options),
1016
- ["RICH-TEXT"]: (elem, options) => TextMethods.ExtractRichTextData(elem),
1017
- ["HTML-RAW"]: (elem, options) => ({
1018
- type: "html-raw",
1019
- data: {
1020
- innerHTML: elem.innerHTML
1021
- }
1022
- }),
1023
- ["H1"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h1"),
1024
- ["H2"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h2"),
1025
- ["H3"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h3"),
1026
- ["H4"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h4"),
1027
- ["H5"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h5"),
1028
- ["H6"]: (elem, options) => HtmlExtractionMethods.ExtractHeaderTag(elem, "h6"),
1029
- [ExternalVideoTagDataConsts.TagName.toUpperCase()]: (elem, options) => VideoMethods.ExtractExternalVideoTag(elem)
1030
- }; }
1031
- static transformHtmlElementToBlocks(element, options) {
1032
- var data = [];
1033
- for (let i = 0; i < element.children.length; i++) {
1034
- var elem = element.children.item(i);
1035
- if (!HtmlExtractionMethods.Extractors.hasOwnProperty(elem.tagName)) {
1036
- data.push({
1037
- type: "unsupported-tag",
1038
- data: {
1039
- tagString: elem.outerHTML
1040
- }
1041
- });
1042
- }
1043
- else {
1044
- var extractor = HtmlExtractionMethods.Extractors[elem.tagName];
1045
- var result = extractor(elem, options);
1046
- data.push(result);
1047
- }
1048
- }
1049
- return data;
1081
+ getFilesWithRelations(model) {
1082
+ return this._httpClient.post(this._baseControllerUrl + `/GetFiles/WithRelations`, model);
1050
1083
  }
1051
- static transformHtmlStringToBlocks(value, options) {
1052
- if (value === undefined || value === null) {
1053
- return [];
1054
- }
1055
- value = value
1056
- .replace('\n', '')
1057
- .replace('\t', '');
1058
- var div = document.createElement("div");
1059
- div.innerHTML = value;
1060
- return this.transformHtmlElementToBlocks(div, options);
1084
+ getFiles(model) {
1085
+ return this._httpClient.post(this._baseControllerUrl + `/GetFiles`, model);
1086
+ }
1087
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FilesQueryService, deps: [{ token: i1.HttpClient }, { token: 'BASE_URL' }], target: i0.ɵɵFactoryTarget.Injectable }); }
1088
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FilesQueryService, providedIn: 'root' }); }
1089
+ }
1090
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FilesQueryService, decorators: [{
1091
+ type: Injectable,
1092
+ args: [{
1093
+ providedIn: 'root'
1094
+ }]
1095
+ }], ctorParameters: () => [{ type: i1.HttpClient }, { type: undefined, decorators: [{
1096
+ type: Inject,
1097
+ args: ['BASE_URL']
1098
+ }] }] });
1099
+
1100
+ class FileIdSelectComponent {
1101
+ constructor(_fileService, _options) {
1102
+ this._fileService = _fileService;
1103
+ this._options = _options;
1104
+ this.labelText = "Поиск файлов";
1105
+ this.loading = false;
1106
+ this.files = [];
1107
+ this.onFileIdChanged = new EventEmitter();
1108
+ }
1109
+ onModelChanged(fileId) {
1110
+ this.onFileIdChanged.emit(fileId);
1111
+ }
1112
+ getSrc(fileId) {
1113
+ return ImageMethods.buildSmallUrl(fileId, this._options);
1114
+ }
1115
+ ngOnInit() {
1116
+ this.loadFiles();
1117
+ }
1118
+ loadFiles() {
1119
+ this.loading = true;
1120
+ this._fileService.getFiles({
1121
+ count: 10,
1122
+ offSet: 0,
1123
+ fileName: null,
1124
+ fileTypes: [FileType.Image],
1125
+ applicationId: null,
1126
+ q: this.q
1127
+ }).subscribe(data => {
1128
+ this.files = [...data.list];
1129
+ this.loading = false;
1130
+ });
1131
+ }
1132
+ onSearchChanged(q) {
1133
+ this.q = q.term;
1134
+ this.loadFiles();
1135
+ }
1136
+ ngOnChanges(changes) {
1137
+ this.loadFiles();
1138
+ }
1139
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FileIdSelectComponent, deps: [{ token: FilesQueryService }, { token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
1140
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: FileIdSelectComponent, selector: "croco-html-file-id-select", inputs: { labelText: "labelText", fileId: "fileId" }, outputs: { fileId: "fileId", onFileIdChanged: "onFileIdChanged" }, usesOnChanges: true, ngImport: i0, template: "<div>\n <div class=\"form-group\">\n <label for=\"fileName\">{{labelText}}</label>\n <ng-select [(ngModel)]=\"fileId\" (ngModelChange)=\"onModelChanged($event)\"\n [items]=\"files\"\n #select\n bindLabel=\"fileName\"\n (search)=\"onSearchChanged($event)\"\n [loading]=\"loading\"\n [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\n dropdownPosition=\"auto\"\n bindValue=\"fileId\"\n labelForId=\"fileName\"\n placeholder=\"\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B\"\n [virtualScroll]=\"true\">\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\n <div>\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc(item.fileId)\"/>\n </div>\n <div>\n <span class=\"h5\">\u0424\u0430\u0439\u043B: </span>\n <span class=\"h5\" [ngOptionHighlight]=\"search\"><b>{{item.fileName}}</b></span>\n </div>\n <div>\n <small>\n <span>\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: <b>{{item.fileId}}</b>\n </span>\n </small>\n </div>\n </ng-template>\n </ng-select>\n </div>\n</div>\n\n<div>\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: {{fileId}}\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: i3$1.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }] }); }
1141
+ }
1142
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FileIdSelectComponent, decorators: [{
1143
+ type: Component,
1144
+ args: [{ selector: 'croco-html-file-id-select', template: "<div>\n <div class=\"form-group\">\n <label for=\"fileName\">{{labelText}}</label>\n <ng-select [(ngModel)]=\"fileId\" (ngModelChange)=\"onModelChanged($event)\"\n [items]=\"files\"\n #select\n bindLabel=\"fileName\"\n (search)=\"onSearchChanged($event)\"\n [loading]=\"loading\"\n [loadingText]=\"'\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u0444\u0430\u0439\u043B\u044B'\"\n dropdownPosition=\"auto\"\n bindValue=\"fileId\"\n labelForId=\"fileName\"\n placeholder=\"\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B\"\n [virtualScroll]=\"true\">\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\n <div>\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc(item.fileId)\"/>\n </div>\n <div>\n <span class=\"h5\">\u0424\u0430\u0439\u043B: </span>\n <span class=\"h5\" [ngOptionHighlight]=\"search\"><b>{{item.fileName}}</b></span>\n </div>\n <div>\n <small>\n <span>\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: <b>{{item.fileId}}</b>\n </span>\n </small>\n </div>\n </ng-template>\n </ng-select>\n </div>\n</div>\n\n<div>\n \u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430: {{fileId}}\n</div>\n" }]
1145
+ }], ctorParameters: () => [{ type: FilesQueryService }, { type: undefined, decorators: [{
1146
+ type: Inject,
1147
+ args: [CrocoHtmlOptionsToken]
1148
+ }] }], propDecorators: { labelText: [{
1149
+ type: Input
1150
+ }], fileId: [{
1151
+ type: Input
1152
+ }, {
1153
+ type: Output
1154
+ }], onFileIdChanged: [{
1155
+ type: Output
1156
+ }] } });
1157
+
1158
+ class ImageEditorComponent {
1159
+ onErrorHandler() {
1160
+ this.hasImageError = true;
1161
+ }
1162
+ constructor(_options) {
1163
+ this._options = _options;
1164
+ this.hasImageError = false;
1165
+ this.searchOrEdit = "search";
1166
+ this.onTagUpdated = new EventEmitter();
1167
+ }
1168
+ getSrc() {
1169
+ return ImageMethods.buildUrl(this.tag.attributes[FileImageTagDataConsts.FileIdAttrName], "Medium", this._options);
1170
+ }
1171
+ hasFileId() {
1172
+ return this.tag.attributes.hasOwnProperty(FileImageTagDataConsts.FileIdAttrName) && !isNaN(this.tag.attributes[FileImageTagDataConsts.FileIdAttrName]);
1173
+ }
1174
+ onFileIdChanged(fileId) {
1175
+ this.tag.attributes[FileImageTagDataConsts.FileIdAttrName] = fileId;
1176
+ this.removeImageError();
1177
+ }
1178
+ removeImageError() {
1179
+ this.hasImageError = false;
1180
+ }
1181
+ ngOnInit() {
1061
1182
  }
1183
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: ImageEditorComponent, deps: [{ token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
1184
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: ImageEditorComponent, selector: "croco-html-image-editor", inputs: { tag: "tag" }, outputs: { onTagUpdated: "onTagUpdated" }, ngImport: i0, template: "<div>\n <div style=\"height: 10px;\">\n </div>\n\n @if (hasImageError) {\n <div class=\"error-block\">\n \u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0444\u0430\u0439\u043B \u043D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043B\u0438 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.\n </div>\n }\n\n @if (hasFileId() && !hasImageError) {\n <div>\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc()\" (error)=\"onErrorHandler()\"/>\n </div>\n }\n\n @if (!hasFileId()) {\n <div>\n <h5>[\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043E]</h5>\n </div>\n }\n</div>\n\n@if (!tag.presentOrEdit) {\n <div>\n <div style=\"height: 10px;\"></div>\n <div style=\"overflow-x:auto;\">\n <mat-button-toggle-group [(ngModel)]=\"searchOrEdit\">\n <mat-button-toggle value=\"search\">\n \u0418\u0441\u043A\u0430\u0442\u044C \u0444\u0430\u0439\u043B <mat-icon>search</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"edit\">\n \u0423\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443 <mat-icon>settings</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"height: 10px;\"></div>\n <div [hidden]=\"searchOrEdit !== 'search'\">\n <croco-html-file-id-select\n [labelText]=\"'\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B'\"\n [(fileId)]=\"tag.attributes['file-id']\"\n (onFileIdChanged)=\"onFileIdChanged($event)\">\n </croco-html-file-id-select>\n </div>\n <div [hidden]=\"searchOrEdit !== 'edit'\">\n <div>\n <mat-form-field class=\"w-100\">\n <input matInput placeholder=\"\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430\" new-autocomplete=\"off\" autocomplete=\"off\"\n type=\"number\"\n [(ngModel)]=\"tag.attributes['file-id']\"\n (ngModelChange)=\"removeImageError()\">\n </mat-form-field>\n </div>\n </div>\n </div>\n}", styles: [".error-block{background-color:#f32323;color:#fff;text-align:center;border-radius:10px;padding:10px}\n"], dependencies: [{ kind: "directive", type: i1$4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$4.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i5.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i5.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: FileIdSelectComponent, selector: "croco-html-file-id-select", inputs: ["labelText", "fileId"], outputs: ["fileId", "onFileIdChanged"] }] }); }
1062
1185
  }
1186
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: ImageEditorComponent, decorators: [{
1187
+ type: Component,
1188
+ args: [{ selector: 'croco-html-image-editor', template: "<div>\n <div style=\"height: 10px;\">\n </div>\n\n @if (hasImageError) {\n <div class=\"error-block\">\n \u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0443\u043A\u0430\u0437\u0430\u043D\u043D\u043E\u043C\u0443 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0444\u0430\u0439\u043B \u043D\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043B\u0438 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.\n </div>\n }\n\n @if (hasFileId() && !hasImageError) {\n <div>\n <img class=\"mx-auto d-block img-fluid\" [src]=\"getSrc()\" (error)=\"onErrorHandler()\"/>\n </div>\n }\n\n @if (!hasFileId()) {\n <div>\n <h5>[\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043E]</h5>\n </div>\n }\n</div>\n\n@if (!tag.presentOrEdit) {\n <div>\n <div style=\"height: 10px;\"></div>\n <div style=\"overflow-x:auto;\">\n <mat-button-toggle-group [(ngModel)]=\"searchOrEdit\">\n <mat-button-toggle value=\"search\">\n \u0418\u0441\u043A\u0430\u0442\u044C \u0444\u0430\u0439\u043B <mat-icon>search</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"edit\">\n \u0423\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440\u0443 <mat-icon>settings</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"height: 10px;\"></div>\n <div [hidden]=\"searchOrEdit !== 'search'\">\n <croco-html-file-id-select\n [labelText]=\"'\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B'\"\n [(fileId)]=\"tag.attributes['file-id']\"\n (onFileIdChanged)=\"onFileIdChanged($event)\">\n </croco-html-file-id-select>\n </div>\n <div [hidden]=\"searchOrEdit !== 'edit'\">\n <div>\n <mat-form-field class=\"w-100\">\n <input matInput placeholder=\"\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0444\u0430\u0439\u043B\u0430\" new-autocomplete=\"off\" autocomplete=\"off\"\n type=\"number\"\n [(ngModel)]=\"tag.attributes['file-id']\"\n (ngModelChange)=\"removeImageError()\">\n </mat-form-field>\n </div>\n </div>\n </div>\n}", styles: [".error-block{background-color:#f32323;color:#fff;text-align:center;border-radius:10px;padding:10px}\n"] }]
1189
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
1190
+ type: Inject,
1191
+ args: [CrocoHtmlOptionsToken]
1192
+ }] }], propDecorators: { tag: [{
1193
+ type: Input
1194
+ }], onTagUpdated: [{
1195
+ type: Output
1196
+ }] } });
1063
1197
 
1064
- class HtmlRawTagDataConsts {
1065
- static { this.TagName = "html-raw"; }
1198
+ class XmlTagHtmlViewComponent {
1199
+ constructor() {
1200
+ this.html = "";
1201
+ }
1202
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHtmlViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1203
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagHtmlViewComponent, selector: "croco-html-xml-tag-html-view", inputs: { html: "html" }, ngImport: i0, template: "<div class=\"col\" [innerHTML]=\"html\">\n</div>", styles: [""] }); }
1066
1204
  }
1205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHtmlViewComponent, decorators: [{
1206
+ type: Component,
1207
+ args: [{ selector: 'croco-html-xml-tag-html-view', template: "<div class=\"col\" [innerHTML]=\"html\">\n</div>" }]
1208
+ }], ctorParameters: () => [], propDecorators: { html: [{
1209
+ type: Input
1210
+ }] } });
1067
1211
 
1068
- class BodyTagsExtensions {
1069
- static getDescription(tagName) {
1070
- var descriptions = {
1071
- "text": "Текст",
1072
- "h1": "Заголовок 1 уровня",
1073
- "h2": "Заголовок 2 уровня",
1074
- "h3": "Заголовок 3 уровня",
1075
- "h4": "Заголовок 4 уровня",
1076
- "h5": "Заголовок 5 уровня",
1077
- "h6": "Заголовок 6 уровня",
1078
- [FileImageTagDataConsts.TagName]: "Изображение",
1079
- [ExternalVideoTagDataConsts.TagName]: "Внешнее видео YouTube",
1080
- [HtmlRawTagDataConsts.TagName]: "Html разметка"
1081
- };
1082
- return descriptions[tagName];
1083
- }
1084
- static toHtml(bodyTags) {
1085
- let htmls = bodyTags.map(x => {
1086
- if (TextMethods.textTags.includes(x.tagDescription.tag)) {
1087
- return `<${x.tagDescription.tag} h-align="${x.attributes['h-align']}">${x.innerHtml}</${x.tagDescription.tag}>`;
1088
- }
1089
- if (x.tagDescription.tag === ExternalVideoTagDataConsts.TagName) {
1090
- return `<${x.tagDescription.tag} type="${x.attributes['type']}" link="${x.attributes['link']}">${x.innerHtml}</${x.tagDescription.tag}>`;
1091
- }
1092
- if (x.tagDescription.tag === "html-raw") {
1093
- return `<${x.tagDescription.tag}>${x.innerHtml}</${x.tagDescription.tag}>`;
1094
- }
1095
- return BodyTagsExtensions.imageTagToHtml(x);
1096
- });
1097
- let result = "";
1098
- for (let index = 0; index < htmls.length; index++) {
1099
- const element = htmls[index];
1100
- result += element;
1101
- }
1102
- return result;
1212
+ class XmlTagTextViewComponent {
1213
+ constructor() { }
1214
+ ngOnInit() {
1103
1215
  }
1104
- static imageTagToHtml(imageTag) {
1105
- var attrStr = "";
1106
- var attrValue = imageTag.attributes[FileImageTagDataConsts.FileIdAttrName];
1107
- if (imageTag.attributes.hasOwnProperty(FileImageTagDataConsts.FileIdAttrName) && attrValue) {
1108
- attrStr = `${FileImageTagDataConsts.FileIdAttrName}="${attrValue}"`;
1109
- }
1110
- return `<${FileImageTagDataConsts.TagName} ${attrStr}></${FileImageTagDataConsts.TagName}>`;
1216
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagTextViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1217
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: XmlTagTextViewComponent, selector: "croco-html-xml-tag-text-view", inputs: { item: "item" }, ngImport: i0, template: "@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'left') {\n <div style=\"text-align: left;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <span [innerHtml]=\"item.data.html\"></span>\n }\n </div>\n}\n\n@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'right') {\n <div style=\"text-align: right;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <span [innerHtml]=\"item.data.html\"></span>\n }\n </div>\n}\n\n@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'center') {\n <div style=\"text-align: center;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <span [innerHtml]=\"item.data.html\"></span>\n }\n </div>\n}\n\n@if (!item.data.validationResult.isSucceeded) {\n <div class=\"red\" style=\"margin-top: 10px;\" >\n <h4>\u0414\u043E\u043F\u0443\u0449\u0435\u043D\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0442\u0435\u0433\u0435 &lt;text&gt;</h4>\n <span>\n {{item.data.validationResult.message}}\n </span>\n </div>\n}", styles: [""] }); }
1218
+ }
1219
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagTextViewComponent, decorators: [{
1220
+ type: Component,
1221
+ args: [{ selector: 'croco-html-xml-tag-text-view', template: "@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'left') {\n <div style=\"text-align: left;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <span [innerHtml]=\"item.data.html\"></span>\n }\n </div>\n}\n\n@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'right') {\n <div style=\"text-align: right;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <span [innerHtml]=\"item.data.html\"></span>\n }\n </div>\n}\n\n@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'center') {\n <div style=\"text-align: center;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <span [innerHtml]=\"item.data.html\"></span>\n }\n </div>\n}\n\n@if (!item.data.validationResult.isSucceeded) {\n <div class=\"red\" style=\"margin-top: 10px;\" >\n <h4>\u0414\u043E\u043F\u0443\u0449\u0435\u043D\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0442\u0435\u0433\u0435 &lt;text&gt;</h4>\n <span>\n {{item.data.validationResult.message}}\n </span>\n </div>\n}" }]
1222
+ }], ctorParameters: () => [], propDecorators: { item: [{
1223
+ type: Input
1224
+ }] } });
1225
+
1226
+ class XmlTagHeaderInnerTextViewComponent {
1227
+ constructor() { }
1228
+ ngOnInit() {
1111
1229
  }
1112
- static getBodyTags(html, options) {
1113
- let result = HtmlExtractionMethods.transformHtmlStringToBlocks(html, options);
1114
- return result.map(x => BodyTagsExtensions.toBodyTag(x));
1230
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHeaderInnerTextViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1231
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: XmlTagHeaderInnerTextViewComponent, selector: "croco-html-xml-tag-header-inner-text-view", inputs: { item: "item" }, ngImport: i0, template: "@if (item.type === 'h1') {\n <h1\n [innerHtml]=\"item.data.html\">\n </h1>\n}\n@if (item.type === 'h2') {\n <h2\n [innerHtml]=\"item.data.html\">\n </h2>\n}\n@if (item.type === 'h3') {\n <h3\n [innerHtml]=\"item.data.html\">\n </h3>\n}\n@if (item.type === 'h4') {\n <h4\n [innerHtml]=\"item.data.html\">\n </h4>\n}\n@if (item.type === 'h5') {\n <h5\n [innerHtml]=\"item.data.html\">\n </h5>\n}\n@if (item.type === 'h6') {\n <h6\n [innerHtml]=\"item.data.html\">\n </h6>\n}", styles: [""] }); }
1232
+ }
1233
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHeaderInnerTextViewComponent, decorators: [{
1234
+ type: Component,
1235
+ args: [{ selector: 'croco-html-xml-tag-header-inner-text-view', template: "@if (item.type === 'h1') {\n <h1\n [innerHtml]=\"item.data.html\">\n </h1>\n}\n@if (item.type === 'h2') {\n <h2\n [innerHtml]=\"item.data.html\">\n </h2>\n}\n@if (item.type === 'h3') {\n <h3\n [innerHtml]=\"item.data.html\">\n </h3>\n}\n@if (item.type === 'h4') {\n <h4\n [innerHtml]=\"item.data.html\">\n </h4>\n}\n@if (item.type === 'h5') {\n <h5\n [innerHtml]=\"item.data.html\">\n </h5>\n}\n@if (item.type === 'h6') {\n <h6\n [innerHtml]=\"item.data.html\">\n </h6>\n}" }]
1236
+ }], ctorParameters: () => [], propDecorators: { item: [{
1237
+ type: Input
1238
+ }] } });
1239
+
1240
+ class XmlTagHeaderTextViewComponent {
1241
+ constructor() { }
1242
+ ngOnInit() {
1115
1243
  }
1116
- static sanitizeInnerHtml(html) {
1117
- return html.trim().replace('\n\t', '');
1244
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHeaderTextViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1245
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: XmlTagHeaderTextViewComponent, selector: "croco-html-xml-tag-header-text-view", inputs: { item: "item" }, ngImport: i0, template: "@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'left') {\n <div style=\"text-align: left;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <croco-html-xml-tag-header-inner-text-view [item]=\"item\">\n </croco-html-xml-tag-header-inner-text-view>\n }\n </div>\n}\n\n@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'right') {\n <div style=\"text-align: right;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <croco-html-xml-tag-header-inner-text-view [item]=\"item\">\n </croco-html-xml-tag-header-inner-text-view>\n }\n </div>\n}\n\n@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'center') {\n <div style=\"text-align: center;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <croco-html-xml-tag-header-inner-text-view [item]=\"item\">\n </croco-html-xml-tag-header-inner-text-view>\n }\n </div>\n}\n\n@if (!item.data.validationResult.isSucceeded) {\n <div class=\"red\" style=\"margin-top: 10px;\" >\n <h4>\u0414\u043E\u043F\u0443\u0449\u0435\u043D\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0442\u0435\u0433\u0435 &lt;text&gt;</h4>\n <span>\n {{item.data.validationResult.message}}\n </span>\n </div>\n}", styles: [""], dependencies: [{ kind: "component", type: XmlTagHeaderInnerTextViewComponent, selector: "croco-html-xml-tag-header-inner-text-view", inputs: ["item"] }] }); }
1246
+ }
1247
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagHeaderTextViewComponent, decorators: [{
1248
+ type: Component,
1249
+ args: [{ selector: 'croco-html-xml-tag-header-text-view', template: "@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'left') {\n <div style=\"text-align: left;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <croco-html-xml-tag-header-inner-text-view [item]=\"item\">\n </croco-html-xml-tag-header-inner-text-view>\n }\n </div>\n}\n\n@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'right') {\n <div style=\"text-align: right;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <croco-html-xml-tag-header-inner-text-view [item]=\"item\">\n </croco-html-xml-tag-header-inner-text-view>\n }\n </div>\n}\n\n@if (item.data.validationResult.isSucceeded && item.data.horizontalAlignment === 'center') {\n <div style=\"text-align: center;\">\n @if (item.data.html.length === 0 || !item.data.html) {\n <span>&nbsp;</span>\n }\n @if (item.data.html.length > 0) {\n <croco-html-xml-tag-header-inner-text-view [item]=\"item\">\n </croco-html-xml-tag-header-inner-text-view>\n }\n </div>\n}\n\n@if (!item.data.validationResult.isSucceeded) {\n <div class=\"red\" style=\"margin-top: 10px;\" >\n <h4>\u0414\u043E\u043F\u0443\u0449\u0435\u043D\u0430 \u043E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0442\u0435\u0433\u0435 &lt;text&gt;</h4>\n <span>\n {{item.data.validationResult.message}}\n </span>\n </div>\n}" }]
1250
+ }], ctorParameters: () => [], propDecorators: { item: [{
1251
+ type: Input
1252
+ }] } });
1253
+
1254
+ class HtmlRawViewComponent {
1255
+ constructor(_sanitizer) {
1256
+ this._sanitizer = _sanitizer;
1257
+ this.rawHtml = "";
1258
+ this.isInitialized = false;
1118
1259
  }
1119
- static toBodyTag(data) {
1120
- if (TextMethods.textTags.includes(data.type)) {
1121
- let textTagData = data.data;
1122
- return {
1123
- presentOrEdit: true,
1124
- tagDescription: {
1125
- tag: textTagData.textTagName,
1126
- displayValue: BodyTagsExtensions.getDescription(data.type)
1127
- },
1128
- attributes: { "h-align": textTagData.horizontalAlignment },
1129
- innerHtml: BodyTagsExtensions.sanitizeInnerHtml(textTagData.html)
1130
- };
1131
- }
1132
- if (data.type === FileImageTagDataConsts.TagName) {
1133
- let fileData = data.data;
1134
- let attrs = {};
1135
- if (fileData.fileId) {
1136
- attrs[FileImageTagDataConsts.FileIdAttrName] = fileData.fileId;
1137
- }
1138
- return {
1139
- presentOrEdit: true,
1140
- tagDescription: {
1141
- tag: FileImageTagDataConsts.TagName,
1142
- displayValue: BodyTagsExtensions.getDescription(data.type)
1143
- },
1144
- attributes: attrs,
1145
- innerHtml: ""
1146
- };
1147
- }
1148
- if (data.type === ExternalVideoTagDataConsts.TagName) {
1149
- let fileData = data.data;
1150
- return {
1151
- presentOrEdit: true,
1152
- tagDescription: {
1153
- tag: ExternalVideoTagDataConsts.TagName,
1154
- displayValue: BodyTagsExtensions.getDescription(data.type)
1155
- },
1156
- attributes: fileData,
1157
- innerHtml: ""
1158
- };
1159
- }
1160
- if (data.type === HtmlRawTagDataConsts.TagName) {
1161
- return {
1162
- presentOrEdit: true,
1163
- tagDescription: {
1164
- tag: HtmlRawTagDataConsts.TagName,
1165
- displayValue: BodyTagsExtensions.getDescription(data.type)
1166
- },
1167
- attributes: {},
1168
- innerHtml: BodyTagsExtensions.sanitizeInnerHtml(data.data["innerHTML"])
1169
- };
1170
- }
1171
- return {
1172
- presentOrEdit: true,
1173
- tagDescription: {
1174
- tag: "unsupported-tag",
1175
- displayValue: "Неподдерживаемый тег"
1176
- },
1177
- attributes: {},
1178
- innerHtml: JSON.stringify(data)
1179
- };
1260
+ ngOnInit() {
1261
+ this.safeHtml = this._sanitizer.bypassSecurityTrustHtml(this.rawHtml);
1180
1262
  }
1263
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: HtmlRawViewComponent, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
1264
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: HtmlRawViewComponent, selector: "croco-html-raw-view", inputs: { rawHtml: "rawHtml" }, ngImport: i0, template: "<div [innerHTML]=\"safeHtml\">\n</div>", styles: [""] }); }
1181
1265
  }
1266
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: HtmlRawViewComponent, decorators: [{
1267
+ type: Component,
1268
+ args: [{ selector: 'croco-html-raw-view', template: "<div [innerHTML]=\"safeHtml\">\n</div>" }]
1269
+ }], ctorParameters: () => [{ type: i1$2.DomSanitizer }], propDecorators: { rawHtml: [{
1270
+ type: Input
1271
+ }] } });
1182
1272
 
1183
- class XmlExtensions {
1184
- static formatXml(xml, tab = '\t') {
1185
- var formatted = '', indent = '';
1186
- tab = tab || '\t';
1187
- xml.split(/>\s*</).forEach(function (node) {
1188
- if (node.match(/^\/\w/))
1189
- indent = indent.substring(tab.length); // decrease indent by one 'tab'
1190
- formatted += indent + '<' + node + '>\r\n';
1191
- if (node.match(/^<?\w[^>]*[^\/]$/))
1192
- indent += tab; // increase indent
1193
- });
1194
- return formatted.substring(1, formatted.length - 3);
1273
+ class FileImageTagViewComponent {
1274
+ constructor() {
1275
+ this.imageSrc = "";
1195
1276
  }
1196
- static tagsToLower(xml) {
1197
- xml = this.replaceTagToLower(xml, "Body");
1198
- xml = this.replaceTagToLower(xml, "Image");
1199
- xml = this.replaceTagToLower(xml, "Text");
1200
- return xml;
1277
+ ngOnInit() {
1278
+ let data = this.item.data;
1279
+ this.imageSrc = data.src;
1201
1280
  }
1202
- static replaceTagToLower(xml, tag) {
1203
- return xml
1204
- .replace(new RegExp(`<${tag}`, 'g'), `<${tag.toLowerCase()}`)
1205
- .replace(new RegExp(`</${tag}>`, 'g'), `</${tag.toLowerCase()}>`);
1281
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FileImageTagViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1282
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: FileImageTagViewComponent, selector: "croco-html-file-image-tag-view", inputs: { item: "item" }, ngImport: i0, template: "\n<img class=\"mx-auto d-block img-fluid\" [src]=\"imageSrc\" alt=\"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E\"/>", styles: [""] }); }
1283
+ }
1284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: FileImageTagViewComponent, decorators: [{
1285
+ type: Component,
1286
+ args: [{ selector: 'croco-html-file-image-tag-view', template: "\n<img class=\"mx-auto d-block img-fluid\" [src]=\"imageSrc\" alt=\"\u0418\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E\"/>" }]
1287
+ }], propDecorators: { item: [{
1288
+ type: Input
1289
+ }] } });
1290
+
1291
+ class XmlTagViewComponent {
1292
+ constructor() {
1293
+ this.data = [];
1294
+ this.textTags = TextTags.allTextTags;
1206
1295
  }
1296
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1297
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: XmlTagViewComponent, selector: "croco-html-xml-tag-view", inputs: { data: "data" }, ngImport: i0, template: "<div>\n @for (item of data; track $index) {\n <div class=\"row\">\n @if (item.type === 'html-raw') {\n <div>\n <croco-html-raw-view [rawHtml]=\"item.data.innerHTML\">\n </croco-html-raw-view>\n </div>\n }\n\n @if (textTags.includes(item.type)) {\n <div>\n <croco-html-xml-tag-header-text-view [item]=\"item\"></croco-html-xml-tag-header-text-view>\n </div>\n }\n\n @if (item.type === 'file-image') {\n <div>\n <croco-html-file-image-tag-view [item]=\"item\"></croco-html-file-image-tag-view>\n </div>\n }\n\n @if (item.type === 'table') {\n <div>\n @if (item.data) {\n <croco-html-xml-tag-html-view [html]=\"item.data\">\n </croco-html-xml-tag-html-view>\n }\n </div>\n }\n\n @if (item.type === 'rich-text') {\n <div>\n <croco-html-xml-tag-text-view></croco-html-xml-tag-text-view>\n </div>\n }\n\n @if (item.type === 'external-video') {\n <div>\n <croco-html-xml-tag-external-video [data]=\"item\"></croco-html-xml-tag-external-video>\n </div>\n }\n\n @if (item.type === 'unsupported-tag') {\n <div class=\"red\" style=\"margin-top: 10px;\">\n <h4>\u0414\u0430\u043D\u043D\u044B\u0439 \u0442\u0435\u0433 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F</h4>\n <span>\n {{item.data.tagString}}\n </span>\n </div>\n }\n </div>\n }\n</div>", styles: [".red{background-color:#c94444;color:#fff}\n"], dependencies: [{ kind: "component", type: XmlTagHtmlViewComponent, selector: "croco-html-xml-tag-html-view", inputs: ["html"] }, { kind: "component", type: XmlTagTextViewComponent, selector: "croco-html-xml-tag-text-view", inputs: ["item"] }, { kind: "component", type: XmlTagHeaderTextViewComponent, selector: "croco-html-xml-tag-header-text-view", inputs: ["item"] }, { kind: "component", type: XmlTagExternalVideoComponent, selector: "croco-html-xml-tag-external-video", inputs: ["data", "tagData"] }, { kind: "component", type: HtmlRawViewComponent, selector: "croco-html-raw-view", inputs: ["rawHtml"] }, { kind: "component", type: FileImageTagViewComponent, selector: "croco-html-file-image-tag-view", inputs: ["item"] }], encapsulation: i0.ViewEncapsulation.None }); }
1207
1298
  }
1299
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagViewComponent, decorators: [{
1300
+ type: Component,
1301
+ args: [{ selector: 'croco-html-xml-tag-view', encapsulation: ViewEncapsulation.None, template: "<div>\n @for (item of data; track $index) {\n <div class=\"row\">\n @if (item.type === 'html-raw') {\n <div>\n <croco-html-raw-view [rawHtml]=\"item.data.innerHTML\">\n </croco-html-raw-view>\n </div>\n }\n\n @if (textTags.includes(item.type)) {\n <div>\n <croco-html-xml-tag-header-text-view [item]=\"item\"></croco-html-xml-tag-header-text-view>\n </div>\n }\n\n @if (item.type === 'file-image') {\n <div>\n <croco-html-file-image-tag-view [item]=\"item\"></croco-html-file-image-tag-view>\n </div>\n }\n\n @if (item.type === 'table') {\n <div>\n @if (item.data) {\n <croco-html-xml-tag-html-view [html]=\"item.data\">\n </croco-html-xml-tag-html-view>\n }\n </div>\n }\n\n @if (item.type === 'rich-text') {\n <div>\n <croco-html-xml-tag-text-view></croco-html-xml-tag-text-view>\n </div>\n }\n\n @if (item.type === 'external-video') {\n <div>\n <croco-html-xml-tag-external-video [data]=\"item\"></croco-html-xml-tag-external-video>\n </div>\n }\n\n @if (item.type === 'unsupported-tag') {\n <div class=\"red\" style=\"margin-top: 10px;\">\n <h4>\u0414\u0430\u043D\u043D\u044B\u0439 \u0442\u0435\u0433 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F</h4>\n <span>\n {{item.data.tagString}}\n </span>\n </div>\n }\n </div>\n }\n</div>", styles: [".red{background-color:#c94444;color:#fff}\n"] }]
1302
+ }], propDecorators: { data: [{
1303
+ type: Input
1304
+ }] } });
1208
1305
 
1209
1306
  class DefaultTags {
1210
1307
  static { this.textTags = [
@@ -1218,7 +1315,7 @@ class DefaultTags {
1218
1315
  ]; }
1219
1316
  static { this.tags = [
1220
1317
  { tag: FileImageTagDataConsts.TagName, displayValue: 'Изображение' },
1221
- { tag: ExternalVideoTagDataConsts.TagName, displayValue: 'Внешнее видео Youtube' },
1318
+ { tag: ExternalVideoTagDataConsts.TagName, displayValue: 'Внешнее видео' },
1222
1319
  ...DefaultTags.textTags
1223
1320
  ]; }
1224
1321
  static { this.htmlRawTag = {
@@ -1243,11 +1340,11 @@ class TextEditorComponent {
1243
1340
  return `<${this.tag.tagDescription.tag}>${this.tag.innerHtml}<${this.tag.tagDescription.tag}/>`;
1244
1341
  }
1245
1342
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: TextEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1246
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: TextEditorComponent, selector: "croco-html-text-editor", inputs: { tag: "tag" }, outputs: { onTagUpdated: "onTagUpdated" }, ngImport: i0, template: "<div *ngIf=\"tag.presentOrEdit\">\r\n <div style=\"height: 10px;\">\r\n </div>\r\n\r\n <div style=\"text-align: left;\" *ngIf=\"tag.attributes['h-align'] === 'left'\" [innerHtml]=\"getInnerHtml()\">\r\n </div>\r\n <div style=\"text-align: right;\" *ngIf=\"tag.attributes['h-align'] === 'right'\" [innerHtml]=\"getInnerHtml()\">\r\n </div>\r\n <div style=\"text-align: center;\" *ngIf=\"tag.attributes['h-align'] === 'center'\" [innerHtml]=\"getInnerHtml()\">\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"!tag.presentOrEdit\">\r\n <div style=\"overflow-x: auto;\">\r\n <mat-button-toggle-group [(ngModel)]=\"tag.attributes['h-align']\">\r\n <mat-button-toggle value=\"center\">\r\n \u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 <mat-icon>format_align_center</mat-icon>\r\n </mat-button-toggle>\r\n <mat-button-toggle value=\"left\">\r\n \u0421\u043B\u0435\u0432\u0430 <mat-icon>format_align_left</mat-icon>\r\n </mat-button-toggle>\r\n <mat-button-toggle value=\"right\">\r\n \u0421\u043F\u0440\u0430\u0432\u0430 <mat-icon> format_align_right</mat-icon>\r\n </mat-button-toggle>\r\n </mat-button-toggle-group>\r\n </div>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n <div>\r\n <mat-form-field class=\"w-100\">\r\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\r\n cdkAutosizeMinRows=\"1\"\r\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430\"\r\n [(ngModel)]=\"tag.innerHtml\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n</div>", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i5.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i6.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i6.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }] }); }
1343
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: TextEditorComponent, selector: "croco-html-text-editor", inputs: { tag: "tag" }, outputs: { onTagUpdated: "onTagUpdated" }, ngImport: i0, template: "@if (tag.presentOrEdit) {\n <div>\n <div style=\"height: 10px;\">\n </div>\n @if (tag.attributes['h-align'] === 'left') {\n <div style=\"text-align: left;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n @if (tag.attributes['h-align'] === 'right') {\n <div style=\"text-align: right;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n @if (tag.attributes['h-align'] === 'center') {\n <div style=\"text-align: center;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n </div>\n}\n\n@if (!tag.presentOrEdit) {\n <div>\n <div style=\"overflow-x: auto;\">\n <mat-button-toggle-group [(ngModel)]=\"tag.attributes['h-align']\">\n <mat-button-toggle value=\"center\">\n \u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 <mat-icon>format_align_center</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n \u0421\u043B\u0435\u0432\u0430 <mat-icon>format_align_left</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"right\">\n \u0421\u043F\u0440\u0430\u0432\u0430 <mat-icon> format_align_right</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"height: 10px;\">\n </div>\n <div>\n <mat-form-field class=\"w-100\">\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430\"\n [(ngModel)]=\"tag.innerHtml\"></textarea>\n </mat-form-field>\n </div>\n </div>\n}", styles: [""], dependencies: [{ kind: "directive", type: i1$4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i4.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i5.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i5.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }] }); }
1247
1344
  }
1248
1345
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: TextEditorComponent, decorators: [{
1249
1346
  type: Component,
1250
- args: [{ selector: 'croco-html-text-editor', template: "<div *ngIf=\"tag.presentOrEdit\">\r\n <div style=\"height: 10px;\">\r\n </div>\r\n\r\n <div style=\"text-align: left;\" *ngIf=\"tag.attributes['h-align'] === 'left'\" [innerHtml]=\"getInnerHtml()\">\r\n </div>\r\n <div style=\"text-align: right;\" *ngIf=\"tag.attributes['h-align'] === 'right'\" [innerHtml]=\"getInnerHtml()\">\r\n </div>\r\n <div style=\"text-align: center;\" *ngIf=\"tag.attributes['h-align'] === 'center'\" [innerHtml]=\"getInnerHtml()\">\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"!tag.presentOrEdit\">\r\n <div style=\"overflow-x: auto;\">\r\n <mat-button-toggle-group [(ngModel)]=\"tag.attributes['h-align']\">\r\n <mat-button-toggle value=\"center\">\r\n \u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 <mat-icon>format_align_center</mat-icon>\r\n </mat-button-toggle>\r\n <mat-button-toggle value=\"left\">\r\n \u0421\u043B\u0435\u0432\u0430 <mat-icon>format_align_left</mat-icon>\r\n </mat-button-toggle>\r\n <mat-button-toggle value=\"right\">\r\n \u0421\u043F\u0440\u0430\u0432\u0430 <mat-icon> format_align_right</mat-icon>\r\n </mat-button-toggle>\r\n </mat-button-toggle-group>\r\n </div>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n <div>\r\n <mat-form-field class=\"w-100\">\r\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\r\n cdkAutosizeMinRows=\"1\"\r\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430\"\r\n [(ngModel)]=\"tag.innerHtml\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n</div>" }]
1347
+ args: [{ selector: 'croco-html-text-editor', template: "@if (tag.presentOrEdit) {\n <div>\n <div style=\"height: 10px;\">\n </div>\n @if (tag.attributes['h-align'] === 'left') {\n <div style=\"text-align: left;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n @if (tag.attributes['h-align'] === 'right') {\n <div style=\"text-align: right;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n @if (tag.attributes['h-align'] === 'center') {\n <div style=\"text-align: center;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n </div>\n}\n\n@if (!tag.presentOrEdit) {\n <div>\n <div style=\"overflow-x: auto;\">\n <mat-button-toggle-group [(ngModel)]=\"tag.attributes['h-align']\">\n <mat-button-toggle value=\"center\">\n \u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 <mat-icon>format_align_center</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n \u0421\u043B\u0435\u0432\u0430 <mat-icon>format_align_left</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"right\">\n \u0421\u043F\u0440\u0430\u0432\u0430 <mat-icon> format_align_right</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"height: 10px;\">\n </div>\n <div>\n <mat-form-field class=\"w-100\">\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430\"\n [(ngModel)]=\"tag.innerHtml\"></textarea>\n </mat-form-field>\n </div>\n </div>\n}" }]
1251
1348
  }], ctorParameters: () => [], propDecorators: { tag: [{
1252
1349
  type: Input
1253
1350
  }], onTagUpdated: [{
@@ -1256,7 +1353,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
1256
1353
 
1257
1354
  class MainEditorBlockComponent {
1258
1355
  constructor() {
1259
- this.textTags = TextMethods.textTags;
1356
+ this.textTags = TextTags.allTextTags;
1260
1357
  this.onTagSaved = new EventEmitter();
1261
1358
  this.onTagRemoved = new EventEmitter();
1262
1359
  }
@@ -1272,12 +1369,12 @@ class MainEditorBlockComponent {
1272
1369
  ngOnInit() {
1273
1370
  }
1274
1371
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MainEditorBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1275
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: MainEditorBlockComponent, selector: "croco-html-main-editor-block", inputs: { tag: "tag" }, outputs: { onTagSaved: "onTagSaved", onTagRemoved: "onTagRemoved" }, ngImport: i0, template: "<div>\r\n <div>\r\n <div *ngIf=\"textTags.includes(tag.tagDescription.tag)\">\r\n <croco-html-text-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\r\n </croco-html-text-editor>\r\n </div>\r\n\r\n <div *ngIf=\"tag.tagDescription.tag === 'file-image'\"> \r\n <croco-html-image-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\r\n </croco-html-image-editor>\r\n </div>\r\n\r\n <div *ngIf=\"tag.tagDescription.tag === 'external-video'\">\r\n <croco-html-external-video-block (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\r\n </croco-html-external-video-block>\r\n </div>\r\n\r\n <div *ngIf=\"tag.tagDescription.tag === 'html-raw'\">\r\n <croco-html-html-raw-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\r\n </croco-html-html-raw-editor>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-between\">\r\n <div class=\"d-flex justify-content-end align-self-center\">\r\n <div>\r\n <button *ngIf=\"tag.presentOrEdit\" (click)=\"tag.presentOrEdit = false\" mat-icon-button>\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button *ngIf=\"!tag.presentOrEdit\" (click)=\"save()\" mat-icon-button>\r\n <mat-icon>save</mat-icon>\r\n </button>\r\n <button (click)=\"deleteItem()\" mat-icon-button color=\"warn\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n</div>", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TextEditorComponent, selector: "croco-html-text-editor", inputs: ["tag"], outputs: ["onTagUpdated"] }, { kind: "component", type: ExternalVideoBlockComponent, selector: "croco-html-external-video-block", inputs: ["tag"], outputs: ["onTagUpdated"] }, { kind: "component", type: ImageEditorComponent, selector: "croco-html-image-editor", inputs: ["tag"], outputs: ["onTagUpdated"] }, { kind: "component", type: HtmlRawEditorComponent, selector: "croco-html-html-raw-editor", inputs: ["tag"], outputs: ["onTagUpdated"] }] }); }
1372
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: MainEditorBlockComponent, selector: "croco-html-main-editor-block", inputs: { tag: "tag" }, outputs: { onTagSaved: "onTagSaved", onTagRemoved: "onTagRemoved" }, ngImport: i0, template: "<div>\n <div>\n @if (textTags.includes(tag.tagDescription.tag)) {\n <div>\n <croco-html-text-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\n </croco-html-text-editor>\n </div>\n }\n\n @if (tag.tagDescription.tag === 'file-image') {\n <div>\n <croco-html-image-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\n </croco-html-image-editor>\n </div>\n }\n\n @if (tag.tagDescription.tag === 'external-video') {\n <div>\n <croco-html-external-video-block (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\n </croco-html-external-video-block>\n </div>\n }\n\n @if (tag.tagDescription.tag === 'html-raw') {\n <div>\n <croco-html-html-raw-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\n </croco-html-html-raw-editor>\n </div>\n }\n\n </div>\n\n <div class=\"d-flex justify-content-between\">\n <div class=\"d-flex justify-content-end align-self-center\">\n <div>\n @if (tag.presentOrEdit) {\n <button (click)=\"tag.presentOrEdit = false\" mat-icon-button>\n <mat-icon>edit</mat-icon>\n </button>\n }\n @if (!tag.presentOrEdit) {\n <button (click)=\"save()\" mat-icon-button>\n <mat-icon>save</mat-icon>\n </button>\n }\n <button (click)=\"deleteItem()\" mat-icon-button color=\"warn\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: i1$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TextEditorComponent, selector: "croco-html-text-editor", inputs: ["tag"], outputs: ["onTagUpdated"] }, { kind: "component", type: ExternalVideoBlockComponent, selector: "croco-html-external-video-block", inputs: ["tag"], outputs: ["onTagUpdated"] }, { kind: "component", type: ImageEditorComponent, selector: "croco-html-image-editor", inputs: ["tag"], outputs: ["onTagUpdated"] }, { kind: "component", type: HtmlRawEditorComponent, selector: "croco-html-html-raw-editor", inputs: ["tag"], outputs: ["onTagUpdated"] }] }); }
1276
1373
  }
1277
1374
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MainEditorBlockComponent, decorators: [{
1278
1375
  type: Component,
1279
- args: [{ selector: 'croco-html-main-editor-block', template: "<div>\r\n <div>\r\n <div *ngIf=\"textTags.includes(tag.tagDescription.tag)\">\r\n <croco-html-text-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\r\n </croco-html-text-editor>\r\n </div>\r\n\r\n <div *ngIf=\"tag.tagDescription.tag === 'file-image'\"> \r\n <croco-html-image-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\r\n </croco-html-image-editor>\r\n </div>\r\n\r\n <div *ngIf=\"tag.tagDescription.tag === 'external-video'\">\r\n <croco-html-external-video-block (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\r\n </croco-html-external-video-block>\r\n </div>\r\n\r\n <div *ngIf=\"tag.tagDescription.tag === 'html-raw'\">\r\n <croco-html-html-raw-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\r\n </croco-html-html-raw-editor>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-between\">\r\n <div class=\"d-flex justify-content-end align-self-center\">\r\n <div>\r\n <button *ngIf=\"tag.presentOrEdit\" (click)=\"tag.presentOrEdit = false\" mat-icon-button>\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button *ngIf=\"!tag.presentOrEdit\" (click)=\"save()\" mat-icon-button>\r\n <mat-icon>save</mat-icon>\r\n </button>\r\n <button (click)=\"deleteItem()\" mat-icon-button color=\"warn\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n</div>" }]
1280
- }], ctorParameters: () => [], propDecorators: { tag: [{
1376
+ args: [{ selector: 'croco-html-main-editor-block', template: "<div>\n <div>\n @if (textTags.includes(tag.tagDescription.tag)) {\n <div>\n <croco-html-text-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\n </croco-html-text-editor>\n </div>\n }\n\n @if (tag.tagDescription.tag === 'file-image') {\n <div>\n <croco-html-image-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\n </croco-html-image-editor>\n </div>\n }\n\n @if (tag.tagDescription.tag === 'external-video') {\n <div>\n <croco-html-external-video-block (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\n </croco-html-external-video-block>\n </div>\n }\n\n @if (tag.tagDescription.tag === 'html-raw') {\n <div>\n <croco-html-html-raw-editor (onTagUpdated)=\"tagUpdatedHandler($event)\" [tag]=\"tag\">\n </croco-html-html-raw-editor>\n </div>\n }\n\n </div>\n\n <div class=\"d-flex justify-content-between\">\n <div class=\"d-flex justify-content-end align-self-center\">\n <div>\n @if (tag.presentOrEdit) {\n <button (click)=\"tag.presentOrEdit = false\" mat-icon-button>\n <mat-icon>edit</mat-icon>\n </button>\n }\n @if (!tag.presentOrEdit) {\n <button (click)=\"save()\" mat-icon-button>\n <mat-icon>save</mat-icon>\n </button>\n }\n <button (click)=\"deleteItem()\" mat-icon-button color=\"warn\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n\n </div>\n</div>\n" }]
1377
+ }], propDecorators: { tag: [{
1281
1378
  type: Input
1282
1379
  }], onTagSaved: [{
1283
1380
  type: Output
@@ -1285,6 +1382,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
1285
1382
  type: Output
1286
1383
  }] } });
1287
1384
 
1385
+ const defaultLinkYouTube = "https://youtu.be/jzBneaWSswY";
1386
+ const defaultLinkVk = "https://vk.com/video_ext.php?oid=-22822305&id=456241864&hd=2";
1288
1387
  class VisualEditorComponent {
1289
1388
  isHtmlSet() {
1290
1389
  return this.html.startsWith("<body>");
@@ -1310,6 +1409,8 @@ class VisualEditorComponent {
1310
1409
  this.alignmentOptions = AlignmentsData;
1311
1410
  this.showMarkUp = true;
1312
1411
  this.tags = [];
1412
+ this.videoPlayers = ExternalVideoPlayers;
1413
+ this.ExternalVideoTagDataConsts = ExternalVideoTagDataConsts;
1313
1414
  this.useHtmlRaw = false;
1314
1415
  this.html = "";
1315
1416
  this.onHtmlChanged = new EventEmitter();
@@ -1328,13 +1429,13 @@ class VisualEditorComponent {
1328
1429
  .find(x => x.tag === this.selectedValue);
1329
1430
  let attrs = {};
1330
1431
  let innerHtml = "";
1331
- if (TextMethods.textTags.includes(tagDescription.tag)) {
1432
+ if (TextTags.allTextTags.includes(tagDescription.tag)) {
1332
1433
  attrs["h-align"] = EAlignments.Left;
1333
1434
  innerHtml = "Введите ваш текст";
1334
1435
  }
1335
1436
  else if (tagDescription.tag == ExternalVideoTagDataConsts.TagName) {
1336
- attrs[ExternalVideoTagDataConsts.VideoTypeAttrName] = ExternalVideoSupportedTypes.Youtube;
1337
- attrs[ExternalVideoTagDataConsts.LinkAttrName] = null;
1437
+ attrs[ExternalVideoTagDataConsts.VideoTypeAttrName] = this.selectedVideoPlayer;
1438
+ attrs[ExternalVideoTagDataConsts.LinkAttrName] = this.selectedVideoPlayer === ExternalVideoSupportedTypes.VkVideo ? defaultLinkVk : defaultLinkYouTube;
1338
1439
  }
1339
1440
  else {
1340
1441
  attrs[FileImageTagDataConsts.FileIdAttrName] = null;
@@ -1424,13 +1525,14 @@ class VisualEditorComponent {
1424
1525
  this.recalculateBodyTags();
1425
1526
  this.tags = DefaultTags.getTags(this.useHtmlRaw);
1426
1527
  this.selectedValue = this.tags[0].tag;
1528
+ this.selectedVideoPlayer = this.videoPlayers[0].type;
1427
1529
  }
1428
1530
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: VisualEditorComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: CrocoHtmlOptionsToken }], target: i0.ɵɵFactoryTarget.Component }); }
1429
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: VisualEditorComponent, selector: "croco-visual-editor", inputs: { showMarkUp: "showMarkUp", useHtmlRaw: "useHtmlRaw", html: "html" }, outputs: { html: "html", onHtmlChanged: "onHtmlChanged", rendered: "rendered" }, viewQueries: [{ propertyName: "textArea", first: true, predicate: ["textArea"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"isLoading\">\r\n <div>\r\n <mat-spinner style=\"margin:0 auto;\"></mat-spinner>\r\n <div style=\"text-align: center;\">{{loadingText}}</div>\r\n </div>\r\n <div style=\"height: 10px;\"></div>\r\n</div>\r\n<div [hidden]=\"isLoading\">\r\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <div class=\"row d-flex align-items-center\">\r\n <div class=\"col-12\">\r\n <button (click)=\"addText()\" class=\"w-100\" mat-stroked-button *ngIf=\"!isActiveAddText\">\r\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u043A\u0441\u0442\r\n </button>\r\n <ng-container *ngIf=\"isActiveAddText\">\r\n <mat-form-field class=\"w-100\" >\r\n <textarea\r\n #autosize=\"cdkTextareaAutosize\"\r\n matInput\r\n cdkTextareaAutosize\r\n cdkAutosizeMinRows=\"1\"\r\n cdkAutosizeMaxRows=\"5\"\r\n placeholder=\"\u0422\u0435\u043A\u0441\u0442\"\r\n #textArea\r\n [(ngModel)]=\"text\"\r\n (ngModelChange)=\"modelChanged()\"\r\n ></textarea>\r\n </mat-form-field>\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>\u0422\u0435\u0433 \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u0430</mat-label>\r\n <mat-select [(ngModel)]=\"textTag\" (ngModelChange)=\"modelChanged()\">\r\n <mat-option *ngFor=\"let option of textTagOptions\" value=\"{{ option.tag }}\">\r\n {{ option.displayValue }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>\u0413\u043E\u0440\u0438\u0437\u043E\u043D\u0442\u0430\u043B\u044C\u043D\u043E\u0435 \u0432\u044B\u0440\u0430\u0432\u043D\u0438\u0432\u0430\u043D\u0438\u0435</mat-label>\r\n <mat-select [(ngModel)]=\"alignment\" (ngModelChange)=\"modelChanged()\">\r\n <mat-option *ngFor=\"let option of alignmentOptions\" value=\"{{ option.value }}\">\r\n {{ option.text }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </ng-container>\r\n <div class=\"d-flex flex-nowrap justify-content-end w-100\">\r\n <button (click)=\"addText()\" class=\"w-20\" style=\"margin-right: 10px\" mat-flat-button color=\"primary\" *ngIf=\"isActiveAddText\">\r\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C\r\n </button>\r\n <button (click)=\"closeText()\" class=\"w-20\" mat-flat-button color=\"warn\" *ngIf=\"isActiveAddText\">\r\n \u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C\r\n </button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n</div>\r\n<div [hidden]=\"isLoading\">\r\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <div class=\"row d-flex align-items-center\">\r\n <div class=\"col-12\">\r\n <mat-form-field class=\"w-100\" appearance=\"outline\">\r\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u0433</mat-label>\r\n <mat-select [(ngModel)]=\"selectedValue\">\r\n <mat-option *ngFor=\"let tag of tags\" [value]=\"tag.tag\">\r\n {{tag.displayValue}}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n <div class=\"col-12\">\r\n <button (click)=\"addTag()\" class=\"w-100\" mat-stroked-button>\r\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u0433\r\n </button>\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n</div>\r\n<div [hidden]=\"isLoading\">\r\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <div class=\"row d-flex align-items-center\">\r\n <div class=\"col-12\">\r\n <croco-html-add-files-btn (filesTagsReady)=\"filesTagsReadyHandler($event)\"\r\n (postFilesStarted)=\"postFilesStartedEventHandler($event)\" class=\"w-100\">\r\n </croco-html-add-files-btn>\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n</div>\r\n<div [hidden]=\"isLoading\">\r\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\">\r\n <div *ngFor=\"let tag of bodyTags; let i = index\" cdkDrag>\r\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <div class=\"d-flex justify-content-between\">\r\n <div class=\"example-handle\" cdkDragHandle>\r\n <svg width=\"24px\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path\r\n d=\"M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z\">\r\n </path>\r\n <path d=\"M0 0h24v24H0z\" fill=\"none\"></path>\r\n </svg>\r\n </div>\r\n <div>\r\n <div class=\"badge\">\r\n {{tag.tagDescription.displayValue}}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div style=\"height: 15px;\"></div>\r\n\r\n <croco-html-main-editor-block [tag]=\"tag\" (onTagSaved)=\"onTagSavedHandler($event)\"\r\n (onTagRemoved)=\"onTagRemovedHandler(i)\">\r\n </croco-html-main-editor-block>\r\n </mat-card-content>\r\n </mat-card>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n\r\n\r\n\r\n", styles: [".example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.badge{background-color:#50a450;color:#fff;min-width:55px;height:25px;border-radius:15px;display:flex;align-items:center;justify-content:center;font-weight:400}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "component", type: i4$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i5$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i5$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i7.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i5.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: i11.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i11.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i11.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: MainEditorBlockComponent, selector: "croco-html-main-editor-block", inputs: ["tag"], outputs: ["onTagSaved", "onTagRemoved"] }, { kind: "component", type: AddFilesBtnComponent, selector: "croco-html-add-files-btn", outputs: ["postFilesStarted", "filesTagsReady"] }] }); }
1531
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: VisualEditorComponent, selector: "croco-visual-editor", inputs: { showMarkUp: "showMarkUp", useHtmlRaw: "useHtmlRaw", html: "html" }, outputs: { html: "html", onHtmlChanged: "onHtmlChanged", rendered: "rendered" }, viewQueries: [{ propertyName: "textArea", first: true, predicate: ["textArea"], descendants: true }], ngImport: i0, template: "@if (isLoading) {\n <div>\n <div>\n <mat-spinner style=\"margin:0 auto;\"></mat-spinner>\n <div style=\"text-align: center;\">{{loadingText}}</div>\n </div>\n <div style=\"height: 10px;\"></div>\n </div>\n}\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n @if (!isActiveAddText) {\n <button (click)=\"addText()\" class=\"w-100\" mat-stroked-button>\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u043A\u0441\u0442\n </button>\n }\n @if (isActiveAddText) {\n <mat-form-field class=\"w-100\" >\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0422\u0435\u043A\u0441\u0442\"\n #textArea\n [(ngModel)]=\"text\"\n (ngModelChange)=\"modelChanged()\"\n ></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>\u0422\u0435\u0433 \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u0430</mat-label>\n <mat-select [(ngModel)]=\"textTag\" (ngModelChange)=\"modelChanged()\">\n @for (option of textTagOptions; track option) {\n <mat-option value=\"{{ option.tag }}\">\n {{ option.displayValue }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>\u0413\u043E\u0440\u0438\u0437\u043E\u043D\u0442\u0430\u043B\u044C\u043D\u043E\u0435 \u0432\u044B\u0440\u0430\u0432\u043D\u0438\u0432\u0430\u043D\u0438\u0435</mat-label>\n <mat-select [(ngModel)]=\"alignment\" (ngModelChange)=\"modelChanged()\">\n @for (option of alignmentOptions; track option) {\n <mat-option value=\"{{ option.value }}\">\n {{ option.text }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <div class=\"d-flex flex-nowrap justify-content-end w-100\">\n @if (isActiveAddText) {\n <button (click)=\"addText()\" class=\"w-20\" style=\"margin-right: 10px\" mat-flat-button color=\"primary\">\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C\n </button>\n }\n @if (isActiveAddText) {\n <button (click)=\"closeText()\" class=\"w-20\" mat-flat-button color=\"warn\" >\n \u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C\n </button>\n }\n </div>\n\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u0433</mat-label>\n <mat-select [(ngModel)]=\"selectedValue\">\n @for (tag of tags; track tag) {\n <mat-option [value]=\"tag.tag\">\n {{tag.displayValue}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (selectedValue === ExternalVideoTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0438\u0434\u0435\u043E\u043F\u043B\u0435\u0435\u0440</mat-label>\n <mat-select [(ngModel)]=\"selectedVideoPlayer\">\n @for (videoPlayer of videoPlayers; track videoPlayer.type) {\n <mat-option [value]=\"videoPlayer.type\">\n {{videoPlayer.displayValue}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n <div class=\"col-12\">\n <button (click)=\"addTag()\" class=\"w-100\" mat-stroked-button>\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u0433\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <croco-html-add-files-btn (filesTagsReady)=\"filesTagsReadyHandler($event)\"\n (postFilesStarted)=\"postFilesStartedEventHandler($event)\" class=\"w-100\">\n </croco-html-add-files-btn>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\">\n @for (tag of bodyTags; track tag; let i = $index) {\n <div cdkDrag>\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"d-flex justify-content-between\">\n <div class=\"example-handle\" cdkDragHandle>\n <svg width=\"24px\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n d=\"M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z\">\n </path>\n <path d=\"M0 0h24v24H0z\" fill=\"none\"></path>\n </svg>\n </div>\n <div>\n <div class=\"badge\">\n {{tag.tagDescription.displayValue}}\n </div>\n </div>\n </div>\n <div style=\"height: 15px;\"></div>\n <croco-html-main-editor-block [tag]=\"tag\" (onTagSaved)=\"onTagSavedHandler($event)\"\n (onTagRemoved)=\"onTagRemovedHandler(i)\">\n </croco-html-main-editor-block>\n </mat-card-content>\n </mat-card>\n <div style=\"height: 10px;\">\n </div>\n </div>\n }\n </div>\n</div>\n\n\n\n\n\n", styles: [".example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.badge{background-color:#50a450;color:#fff;min-width:55px;height:25px;border-radius:15px;display:flex;align-items:center;justify-content:center;font-weight:400}\n"], dependencies: [{ kind: "directive", type: i1$4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "component", type: i3$2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i4$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i5$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i1$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i4.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: i10.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i10.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i10.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: MainEditorBlockComponent, selector: "croco-html-main-editor-block", inputs: ["tag"], outputs: ["onTagSaved", "onTagRemoved"] }, { kind: "component", type: AddFilesBtnComponent, selector: "croco-html-add-files-btn", outputs: ["postFilesStarted", "filesTagsReady"] }] }); }
1430
1532
  }
1431
1533
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: VisualEditorComponent, decorators: [{
1432
1534
  type: Component,
1433
- args: [{ selector: 'croco-visual-editor', template: "<div *ngIf=\"isLoading\">\r\n <div>\r\n <mat-spinner style=\"margin:0 auto;\"></mat-spinner>\r\n <div style=\"text-align: center;\">{{loadingText}}</div>\r\n </div>\r\n <div style=\"height: 10px;\"></div>\r\n</div>\r\n<div [hidden]=\"isLoading\">\r\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <div class=\"row d-flex align-items-center\">\r\n <div class=\"col-12\">\r\n <button (click)=\"addText()\" class=\"w-100\" mat-stroked-button *ngIf=\"!isActiveAddText\">\r\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u043A\u0441\u0442\r\n </button>\r\n <ng-container *ngIf=\"isActiveAddText\">\r\n <mat-form-field class=\"w-100\" >\r\n <textarea\r\n #autosize=\"cdkTextareaAutosize\"\r\n matInput\r\n cdkTextareaAutosize\r\n cdkAutosizeMinRows=\"1\"\r\n cdkAutosizeMaxRows=\"5\"\r\n placeholder=\"\u0422\u0435\u043A\u0441\u0442\"\r\n #textArea\r\n [(ngModel)]=\"text\"\r\n (ngModelChange)=\"modelChanged()\"\r\n ></textarea>\r\n </mat-form-field>\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>\u0422\u0435\u0433 \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u0430</mat-label>\r\n <mat-select [(ngModel)]=\"textTag\" (ngModelChange)=\"modelChanged()\">\r\n <mat-option *ngFor=\"let option of textTagOptions\" value=\"{{ option.tag }}\">\r\n {{ option.displayValue }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>\u0413\u043E\u0440\u0438\u0437\u043E\u043D\u0442\u0430\u043B\u044C\u043D\u043E\u0435 \u0432\u044B\u0440\u0430\u0432\u043D\u0438\u0432\u0430\u043D\u0438\u0435</mat-label>\r\n <mat-select [(ngModel)]=\"alignment\" (ngModelChange)=\"modelChanged()\">\r\n <mat-option *ngFor=\"let option of alignmentOptions\" value=\"{{ option.value }}\">\r\n {{ option.text }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </ng-container>\r\n <div class=\"d-flex flex-nowrap justify-content-end w-100\">\r\n <button (click)=\"addText()\" class=\"w-20\" style=\"margin-right: 10px\" mat-flat-button color=\"primary\" *ngIf=\"isActiveAddText\">\r\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C\r\n </button>\r\n <button (click)=\"closeText()\" class=\"w-20\" mat-flat-button color=\"warn\" *ngIf=\"isActiveAddText\">\r\n \u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C\r\n </button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n</div>\r\n<div [hidden]=\"isLoading\">\r\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <div class=\"row d-flex align-items-center\">\r\n <div class=\"col-12\">\r\n <mat-form-field class=\"w-100\" appearance=\"outline\">\r\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u0433</mat-label>\r\n <mat-select [(ngModel)]=\"selectedValue\">\r\n <mat-option *ngFor=\"let tag of tags\" [value]=\"tag.tag\">\r\n {{tag.displayValue}}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n <div class=\"col-12\">\r\n <button (click)=\"addTag()\" class=\"w-100\" mat-stroked-button>\r\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u0433\r\n </button>\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n</div>\r\n<div [hidden]=\"isLoading\">\r\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <div class=\"row d-flex align-items-center\">\r\n <div class=\"col-12\">\r\n <croco-html-add-files-btn (filesTagsReady)=\"filesTagsReadyHandler($event)\"\r\n (postFilesStarted)=\"postFilesStartedEventHandler($event)\" class=\"w-100\">\r\n </croco-html-add-files-btn>\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n</div>\r\n<div [hidden]=\"isLoading\">\r\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\">\r\n <div *ngFor=\"let tag of bodyTags; let i = index\" cdkDrag>\r\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <div class=\"d-flex justify-content-between\">\r\n <div class=\"example-handle\" cdkDragHandle>\r\n <svg width=\"24px\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path\r\n d=\"M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z\">\r\n </path>\r\n <path d=\"M0 0h24v24H0z\" fill=\"none\"></path>\r\n </svg>\r\n </div>\r\n <div>\r\n <div class=\"badge\">\r\n {{tag.tagDescription.displayValue}}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div style=\"height: 15px;\"></div>\r\n\r\n <croco-html-main-editor-block [tag]=\"tag\" (onTagSaved)=\"onTagSavedHandler($event)\"\r\n (onTagRemoved)=\"onTagRemovedHandler(i)\">\r\n </croco-html-main-editor-block>\r\n </mat-card-content>\r\n </mat-card>\r\n\r\n <div style=\"height: 10px;\">\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n\r\n\r\n\r\n", styles: [".example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.badge{background-color:#50a450;color:#fff;min-width:55px;height:25px;border-radius:15px;display:flex;align-items:center;justify-content:center;font-weight:400}\n"] }]
1535
+ args: [{ selector: 'croco-visual-editor', template: "@if (isLoading) {\n <div>\n <div>\n <mat-spinner style=\"margin:0 auto;\"></mat-spinner>\n <div style=\"text-align: center;\">{{loadingText}}</div>\n </div>\n <div style=\"height: 10px;\"></div>\n </div>\n}\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n @if (!isActiveAddText) {\n <button (click)=\"addText()\" class=\"w-100\" mat-stroked-button>\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u043A\u0441\u0442\n </button>\n }\n @if (isActiveAddText) {\n <mat-form-field class=\"w-100\" >\n <textarea\n #autosize=\"cdkTextareaAutosize\"\n matInput\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"1\"\n cdkAutosizeMaxRows=\"5\"\n placeholder=\"\u0422\u0435\u043A\u0441\u0442\"\n #textArea\n [(ngModel)]=\"text\"\n (ngModelChange)=\"modelChanged()\"\n ></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>\u0422\u0435\u0433 \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u0430</mat-label>\n <mat-select [(ngModel)]=\"textTag\" (ngModelChange)=\"modelChanged()\">\n @for (option of textTagOptions; track option) {\n <mat-option value=\"{{ option.tag }}\">\n {{ option.displayValue }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>\u0413\u043E\u0440\u0438\u0437\u043E\u043D\u0442\u0430\u043B\u044C\u043D\u043E\u0435 \u0432\u044B\u0440\u0430\u0432\u043D\u0438\u0432\u0430\u043D\u0438\u0435</mat-label>\n <mat-select [(ngModel)]=\"alignment\" (ngModelChange)=\"modelChanged()\">\n @for (option of alignmentOptions; track option) {\n <mat-option value=\"{{ option.value }}\">\n {{ option.text }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <div class=\"d-flex flex-nowrap justify-content-end w-100\">\n @if (isActiveAddText) {\n <button (click)=\"addText()\" class=\"w-20\" style=\"margin-right: 10px\" mat-flat-button color=\"primary\">\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C\n </button>\n }\n @if (isActiveAddText) {\n <button (click)=\"closeText()\" class=\"w-20\" mat-flat-button color=\"warn\" >\n \u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C\n </button>\n }\n </div>\n\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u0433</mat-label>\n <mat-select [(ngModel)]=\"selectedValue\">\n @for (tag of tags; track tag) {\n <mat-option [value]=\"tag.tag\">\n {{tag.displayValue}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n @if (selectedValue === ExternalVideoTagDataConsts.TagName) {\n <div class=\"col-12\">\n <mat-form-field class=\"w-100\" appearance=\"outline\">\n <mat-label>\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0438\u0434\u0435\u043E\u043F\u043B\u0435\u0435\u0440</mat-label>\n <mat-select [(ngModel)]=\"selectedVideoPlayer\">\n @for (videoPlayer of videoPlayers; track videoPlayer.type) {\n <mat-option [value]=\"videoPlayer.type\">\n {{videoPlayer.displayValue}}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n <div class=\"col-12\">\n <button (click)=\"addTag()\" class=\"w-100\" mat-stroked-button>\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u0433\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"row d-flex align-items-center\">\n <div class=\"col-12\">\n <croco-html-add-files-btn (filesTagsReady)=\"filesTagsReadyHandler($event)\"\n (postFilesStarted)=\"postFilesStartedEventHandler($event)\" class=\"w-100\">\n </croco-html-add-files-btn>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n\n <div style=\"height: 10px;\">\n </div>\n</div>\n<div [hidden]=\"isLoading\">\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\">\n @for (tag of bodyTags; track tag; let i = $index) {\n <div cdkDrag>\n <mat-card style=\"margin: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <div class=\"d-flex justify-content-between\">\n <div class=\"example-handle\" cdkDragHandle>\n <svg width=\"24px\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n d=\"M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z\">\n </path>\n <path d=\"M0 0h24v24H0z\" fill=\"none\"></path>\n </svg>\n </div>\n <div>\n <div class=\"badge\">\n {{tag.tagDescription.displayValue}}\n </div>\n </div>\n </div>\n <div style=\"height: 15px;\"></div>\n <croco-html-main-editor-block [tag]=\"tag\" (onTagSaved)=\"onTagSavedHandler($event)\"\n (onTagRemoved)=\"onTagRemovedHandler(i)\">\n </croco-html-main-editor-block>\n </mat-card-content>\n </mat-card>\n <div style=\"height: 10px;\">\n </div>\n </div>\n }\n </div>\n</div>\n\n\n\n\n\n", styles: [".example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.badge{background-color:#50a450;color:#fff;min-width:55px;height:25px;border-radius:15px;display:flex;align-items:center;justify-content:center;font-weight:400}\n"] }]
1434
1536
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
1435
1537
  type: Inject,
1436
1538
  args: [CrocoHtmlOptionsToken]
@@ -1511,13 +1613,13 @@ class MainEditorComponent {
1511
1613
  ngOnInit() {
1512
1614
  this.visualEditor.recalculateBodyTags();
1513
1615
  }
1514
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MainEditorComponent, deps: [{ token: i1$3.ClipboardService }, { token: i2$3.MatSnackBar }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
1515
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: MainEditorComponent, selector: "croco-html-main-editor", inputs: { showMarkUp: "showMarkUp", useHtmlRaw: "useHtmlRaw", html: "html" }, outputs: { html: "html", onHtmlChanged: "onHtmlChanged" }, viewQueries: [{ propertyName: "visualEditor", first: true, predicate: ["visualEditor"], descendants: true, static: true }], ngImport: i0, template: "<mat-tab-group>\r\n <mat-tab label=\"\u0412\u0438\u0437\u0443\u0430\u043B\u044C\u043D\u044B\u0439 \u0440\u0435\u0434\u0430\u043A\u0442\u043E\u0440\">\r\n\r\n <div style=\"height: 20px;\"></div>\r\n\r\n <croco-visual-editor #visualEditor\r\n [useHtmlRaw]=\"useHtmlRaw\"\r\n [html]=\"html\"\r\n (onHtmlChanged)=\"onHtmlChangedHandler($event)\"\r\n (rendered)=\"visualEditorRenderedHandler()\">\r\n </croco-visual-editor>\r\n\r\n <div style=\"height: 20px;\"></div>\r\n\r\n </mat-tab>\r\n\r\n <mat-tab label=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\">\r\n <div style=\"height: 10px;\"></div>\r\n <div *ngIf=\"visualEditorRendered\">\r\n <mat-form-field class=\"w-100\">\r\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\r\n cdkAutosizeMinRows=\"1\"\r\n placeholder=\"\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434\" [(ngModel)]=\"html\"\r\n (ngModelChange)=\"textAreaModelChangedHandler()\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n\r\n <button (click)=\"copyMarkUp()\"\r\n mat-raised-button color=\"primary\">\r\n \u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0443\r\n </button>\r\n </mat-tab>\r\n <mat-tab label=\"\u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\">\r\n <mat-card style=\"padding: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <croco-html-xml-tag-view [data]=\"html | topreview\">\r\n </croco-html-xml-tag-view>\r\n </mat-card-content>\r\n </mat-card>\r\n </mat-tab>\r\n</mat-tab-group>\r\n", styles: [".example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "component", type: i6$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i6$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i5$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i5$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i5.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "component", type: XmlTagViewComponent, selector: "croco-html-xml-tag-view", inputs: ["data"] }, { kind: "component", type: VisualEditorComponent, selector: "croco-visual-editor", inputs: ["showMarkUp", "useHtmlRaw", "html"], outputs: ["html", "onHtmlChanged", "rendered"] }, { kind: "pipe", type: ToPreviewPipe, name: "topreview" }] }); }
1616
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MainEditorComponent, deps: [{ token: i1$5.ClipboardService }, { token: i2$1.MatSnackBar }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
1617
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: MainEditorComponent, selector: "croco-html-main-editor", inputs: { showMarkUp: "showMarkUp", useHtmlRaw: "useHtmlRaw", html: "html" }, outputs: { html: "html", onHtmlChanged: "onHtmlChanged" }, viewQueries: [{ propertyName: "visualEditor", first: true, predicate: ["visualEditor"], descendants: true, static: true }], ngImport: i0, template: "<mat-tab-group>\n <mat-tab label=\"\u0412\u0438\u0437\u0443\u0430\u043B\u044C\u043D\u044B\u0439 \u0440\u0435\u0434\u0430\u043A\u0442\u043E\u0440\">\n\n <div style=\"height: 20px;\"></div>\n\n <croco-visual-editor #visualEditor\n [useHtmlRaw]=\"useHtmlRaw\"\n [html]=\"html\"\n (onHtmlChanged)=\"onHtmlChangedHandler($event)\"\n (rendered)=\"visualEditorRenderedHandler()\">\n </croco-visual-editor>\n\n <div style=\"height: 20px;\"></div>\n\n </mat-tab>\n\n <mat-tab label=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\">\n <div style=\"height: 10px;\"></div>\n @if (visualEditorRendered) {\n <div>\n <mat-form-field class=\"w-100\">\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434\" [(ngModel)]=\"html\"\n (ngModelChange)=\"textAreaModelChangedHandler()\"></textarea>\n </mat-form-field>\n </div>\n }\n\n <button (click)=\"copyMarkUp()\"\n mat-raised-button color=\"primary\">\n \u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0443\n </button>\n </mat-tab>\n <mat-tab label=\"\u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\">\n <mat-card style=\"padding: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <croco-html-xml-tag-view [data]=\"html | topreview\">\n </croco-html-xml-tag-view>\n </mat-card-content>\n </mat-card>\n </mat-tab>\n</mat-tab-group>\n", styles: [".example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "directive", type: i1$4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "component", type: i5$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i5$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i4$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i1$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i4.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "component", type: XmlTagViewComponent, selector: "croco-html-xml-tag-view", inputs: ["data"] }, { kind: "component", type: VisualEditorComponent, selector: "croco-visual-editor", inputs: ["showMarkUp", "useHtmlRaw", "html"], outputs: ["html", "onHtmlChanged", "rendered"] }, { kind: "pipe", type: ToPreviewPipe, name: "topreview" }] }); }
1516
1618
  }
1517
1619
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: MainEditorComponent, decorators: [{
1518
1620
  type: Component,
1519
- args: [{ selector: 'croco-html-main-editor', template: "<mat-tab-group>\r\n <mat-tab label=\"\u0412\u0438\u0437\u0443\u0430\u043B\u044C\u043D\u044B\u0439 \u0440\u0435\u0434\u0430\u043A\u0442\u043E\u0440\">\r\n\r\n <div style=\"height: 20px;\"></div>\r\n\r\n <croco-visual-editor #visualEditor\r\n [useHtmlRaw]=\"useHtmlRaw\"\r\n [html]=\"html\"\r\n (onHtmlChanged)=\"onHtmlChangedHandler($event)\"\r\n (rendered)=\"visualEditorRenderedHandler()\">\r\n </croco-visual-editor>\r\n\r\n <div style=\"height: 20px;\"></div>\r\n\r\n </mat-tab>\r\n\r\n <mat-tab label=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\">\r\n <div style=\"height: 10px;\"></div>\r\n <div *ngIf=\"visualEditorRendered\">\r\n <mat-form-field class=\"w-100\">\r\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\r\n cdkAutosizeMinRows=\"1\"\r\n placeholder=\"\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434\" [(ngModel)]=\"html\"\r\n (ngModelChange)=\"textAreaModelChangedHandler()\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n\r\n <button (click)=\"copyMarkUp()\"\r\n mat-raised-button color=\"primary\">\r\n \u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0443\r\n </button>\r\n </mat-tab>\r\n <mat-tab label=\"\u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\">\r\n <mat-card style=\"padding: 2px;\" class=\"mat-card\">\r\n <mat-card-content>\r\n <croco-html-xml-tag-view [data]=\"html | topreview\">\r\n </croco-html-xml-tag-view>\r\n </mat-card-content>\r\n </mat-card>\r\n </mat-tab>\r\n</mat-tab-group>\r\n", styles: [".example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"] }]
1520
- }], ctorParameters: () => [{ type: i1$3.ClipboardService }, { type: i2$3.MatSnackBar }, { type: i0.ChangeDetectorRef }], propDecorators: { visualEditor: [{
1621
+ args: [{ selector: 'croco-html-main-editor', template: "<mat-tab-group>\n <mat-tab label=\"\u0412\u0438\u0437\u0443\u0430\u043B\u044C\u043D\u044B\u0439 \u0440\u0435\u0434\u0430\u043A\u0442\u043E\u0440\">\n\n <div style=\"height: 20px;\"></div>\n\n <croco-visual-editor #visualEditor\n [useHtmlRaw]=\"useHtmlRaw\"\n [html]=\"html\"\n (onHtmlChanged)=\"onHtmlChangedHandler($event)\"\n (rendered)=\"visualEditorRenderedHandler()\">\n </croco-visual-editor>\n\n <div style=\"height: 20px;\"></div>\n\n </mat-tab>\n\n <mat-tab label=\"\u0420\u0430\u0437\u043C\u0435\u0442\u043A\u0430\">\n <div style=\"height: 10px;\"></div>\n @if (visualEditorRendered) {\n <div>\n <mat-form-field class=\"w-100\">\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u043A\u043E\u0434\" [(ngModel)]=\"html\"\n (ngModelChange)=\"textAreaModelChangedHandler()\"></textarea>\n </mat-form-field>\n </div>\n }\n\n <button (click)=\"copyMarkUp()\"\n mat-raised-button color=\"primary\">\n \u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0443\n </button>\n </mat-tab>\n <mat-tab label=\"\u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\">\n <mat-card style=\"padding: 2px;\" class=\"mat-card\">\n <mat-card-content>\n <croco-html-xml-tag-view [data]=\"html | topreview\">\n </croco-html-xml-tag-view>\n </mat-card-content>\n </mat-card>\n </mat-tab>\n</mat-tab-group>\n", styles: [".example-list{width:500px;max-width:100%;border:solid 1px #ccc;min-height:60px;display:block;background:#fff;border-radius:4px;overflow:hidden}.example-box{padding:20px 10px;border-bottom:solid 1px #ccc;color:#000000de;display:flex;flex-direction:row;align-items:center;justify-content:space-between;box-sizing:border-box;cursor:move;background:#fff;font-size:14px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.example-box:last-child{border:none}.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"] }]
1622
+ }], ctorParameters: () => [{ type: i1$5.ClipboardService }, { type: i2$1.MatSnackBar }, { type: i0.ChangeDetectorRef }], propDecorators: { visualEditor: [{
1521
1623
  type: ViewChild,
1522
1624
  args: ["visualEditor", { static: true }]
1523
1625
  }], showMarkUp: [{
@@ -1563,11 +1665,11 @@ class XmlTagRichTextViewComponent {
1563
1665
  ngOnInit() {
1564
1666
  }
1565
1667
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagRichTextViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1566
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagRichTextViewComponent, selector: "croco-html-xml-tag-rich-text-view", inputs: { richTextData: "richTextData" }, ngImport: i0, template: "<div *ngIf=\"richTextData\" [innerHtml]=\"richTextData | richTextToHtml\">\r\n</div>", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: RichTextToHtmlPipe, name: "richTextToHtml" }] }); }
1668
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: XmlTagRichTextViewComponent, selector: "croco-html-xml-tag-rich-text-view", inputs: { richTextData: "richTextData" }, ngImport: i0, template: "@if (richTextData) {\n <div [innerHtml]=\"richTextData | richTextToHtml\">\n </div>\n}", styles: [""], dependencies: [{ kind: "pipe", type: RichTextToHtmlPipe, name: "richTextToHtml" }] }); }
1567
1669
  }
1568
1670
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagRichTextViewComponent, decorators: [{
1569
1671
  type: Component,
1570
- args: [{ selector: 'croco-html-xml-tag-rich-text-view', template: "<div *ngIf=\"richTextData\" [innerHtml]=\"richTextData | richTextToHtml\">\r\n</div>" }]
1672
+ args: [{ selector: 'croco-html-xml-tag-rich-text-view', template: "@if (richTextData) {\n <div [innerHtml]=\"richTextData | richTextToHtml\">\n </div>\n}" }]
1571
1673
  }], ctorParameters: () => [], propDecorators: { richTextData: [{
1572
1674
  type: Input
1573
1675
  }] } });
@@ -1577,11 +1679,11 @@ class XmlTagTableViewComponent {
1577
1679
  this.displayedColumns = [];
1578
1680
  }
1579
1681
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagTableViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1580
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: XmlTagTableViewComponent, selector: "croco-html-xml-tag-table-view", inputs: { displayedColumns: "displayedColumns", data: "data" }, ngImport: i0, template: "<table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8 w-100 example-container\">\r\n <ng-container [matColumnDef]=\"column\" *ngFor=\"let column of displayedColumns\">\r\n <th mat-header-cell *matHeaderCellDef> {{column}} </th>\r\n <td mat-cell *matCellDef=\"let element\"> {{element[column]}} </td>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\r\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\r\n</table>", styles: [""], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i2$4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i2$4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i2$4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i2$4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i2$4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i2$4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i2$4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i2$4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i2$4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i2$4.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }] }); }
1682
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.4", type: XmlTagTableViewComponent, selector: "croco-html-xml-tag-table-view", inputs: { displayedColumns: "displayedColumns", data: "data" }, ngImport: i0, template: "<table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8 w-100 example-container\">\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{column}} </th>\n <td mat-cell *matCellDef=\"let element\"> {{element[column]}} </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n</table>", styles: [""], dependencies: [{ kind: "component", type: i1$6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }] }); }
1581
1683
  }
1582
1684
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: XmlTagTableViewComponent, decorators: [{
1583
1685
  type: Component,
1584
- args: [{ selector: 'croco-html-xml-tag-table-view', template: "<table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8 w-100 example-container\">\r\n <ng-container [matColumnDef]=\"column\" *ngFor=\"let column of displayedColumns\">\r\n <th mat-header-cell *matHeaderCellDef> {{column}} </th>\r\n <td mat-cell *matCellDef=\"let element\"> {{element[column]}} </td>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\r\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\r\n</table>" }]
1686
+ args: [{ selector: 'croco-html-xml-tag-table-view', template: "<table mat-table [dataSource]=\"data\" class=\"mat-elevation-z8 w-100 example-container\">\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th mat-header-cell *matHeaderCellDef> {{column}} </th>\n <td mat-cell *matCellDef=\"let element\"> {{element[column]}} </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n</table>" }]
1585
1687
  }], propDecorators: { displayedColumns: [{
1586
1688
  type: Input
1587
1689
  }], data: [{
@@ -1656,40 +1758,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
1656
1758
  args: [CrocoHtmlOptionsToken]
1657
1759
  }] }] });
1658
1760
 
1659
- class TableBuilder {
1660
- static getTableMarkUp(rows, cols, generateHeaders) {
1661
- rows = +rows;
1662
- cols = +cols;
1663
- let result = "<table>";
1664
- if (generateHeaders) {
1665
- result += TableBuilder.getTableHeaderMarkUp(cols);
1666
- }
1667
- result += TableBuilder.getTableBodyMarkUp(cols, rows);
1668
- result += "</table>";
1669
- return XmlExtensions.formatXml(result);
1670
- }
1671
- static getTableHeaderMarkUp(cols) {
1672
- let result = "<thead><tr>";
1673
- for (let i = 0; i < cols; i++) {
1674
- result += `<th>Колонка #${i + 1}</th>`;
1675
- }
1676
- result += "</tr></thead>";
1677
- return result;
1678
- }
1679
- static getTableBodyMarkUp(cols, rows) {
1680
- let result = "<tbody>";
1681
- for (let row = 0; row < rows; row++) {
1682
- result += "<tr>";
1683
- for (let i = 0; i < cols; i++) {
1684
- result += `<td>Ряд№${row + 1} Колонка #${i + 1}</td>`;
1685
- }
1686
- result += "</tr>";
1687
- }
1688
- result += "</tbody>";
1689
- return result;
1690
- }
1691
- }
1692
-
1693
1761
  const EditorComponents = [
1694
1762
  MainEditorComponent,
1695
1763
  FileIdSelectComponent,
@@ -1765,7 +1833,8 @@ class CrocoHtmlModule {
1765
1833
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.4", ngImport: i0, type: CrocoHtmlModule, declarations: [UploadFilesBtnComponent, HtmlViewComponent, XmlTagTableViewComponent, XmlTagViewComponent, XmlTagRichTextViewComponent, XmlTagHtmlViewComponent, XmlTagTextViewComponent, XmlTagHeaderTextViewComponent, XmlTagHeaderInnerTextViewComponent, XmlTagExternalVideoComponent, HtmlRawViewComponent, FileImageTagViewComponent, HtmlViewComponent, MainEditorComponent, FileIdSelectComponent, TextEditorComponent, ExternalVideoBlockComponent, ImageEditorComponent, MainEditorBlockComponent, VisualEditorComponent, AddFilesBtnComponent, HtmlRawEditorComponent, RichTextToHtmlPipe, TagToSpanPipe, ToPreviewPipe, ToHtmlBodyTagsPipe, ToPreviewHtmlPipe], imports: [CommonModule,
1766
1834
  FormsModule,
1767
1835
  ReactiveFormsModule,
1768
- NgSelectModule, i27.MatBadgeModule, i2$4.MatTableModule, i29.MatExpansionModule, i3.MatFormFieldModule, i2$3.MatSnackBarModule, i32.MatProgressBarModule, i4$1.MatProgressSpinnerModule, i6$2.MatTabsModule, i35.MatMenuModule, i5$2.MatCardModule, i6$1.MatSelectModule, i38.MatTooltipModule, i39.MatCheckboxModule, i40.MatChipsModule, i41.MatListModule, i2.MatButtonModule, i4.MatInputModule, i44.MatDialogModule, i45.MatPaginatorModule, i46.MatDatepickerModule, i47.MatGridListModule, i48.MatSlideToggleModule, i49.MatTreeModule, i7.MatNativeDateModule, i51.MatAutocompleteModule, i52.MatSidenavModule, i5$1.MatIconModule, i11.DragDropModule, i6.MatButtonToggleModule, YouTubePlayerModule], exports: [UploadFilesBtnComponent, HtmlViewComponent, XmlTagTableViewComponent, XmlTagViewComponent, XmlTagRichTextViewComponent, XmlTagHtmlViewComponent, XmlTagTextViewComponent, XmlTagHeaderTextViewComponent, XmlTagHeaderInnerTextViewComponent, XmlTagExternalVideoComponent, HtmlRawViewComponent, FileImageTagViewComponent, HtmlViewComponent, MainEditorComponent, FileIdSelectComponent, TextEditorComponent, ExternalVideoBlockComponent, ImageEditorComponent, MainEditorBlockComponent, VisualEditorComponent, AddFilesBtnComponent, HtmlRawEditorComponent, RichTextToHtmlPipe, TagToSpanPipe, ToPreviewPipe, ToHtmlBodyTagsPipe, ToPreviewHtmlPipe] }); }
1836
+ NgSelectModule, i27.MatBadgeModule, i1$6.MatTableModule, i29.MatExpansionModule, i2.MatFormFieldModule, i2$1.MatSnackBarModule, i32.MatProgressBarModule, i3$2.MatProgressSpinnerModule, i5$2.MatTabsModule, i35.MatMenuModule, i4$2.MatCardModule, i5$1.MatSelectModule, i38.MatTooltipModule, i39.MatCheckboxModule, i40.MatChipsModule, i41.MatListModule, i1$1.MatButtonModule, i3.MatInputModule, i44.MatDialogModule, i45.MatPaginatorModule, i46.MatDatepickerModule, i47.MatGridListModule, i48.MatSlideToggleModule, i49.MatTreeModule, i6.MatNativeDateModule, i51.MatAutocompleteModule, i52.MatSidenavModule, i4$1.MatIconModule, i10.DragDropModule, i5.MatButtonToggleModule, YouTubePlayerModule,
1837
+ VkVideoPlayerComponent], exports: [UploadFilesBtnComponent, HtmlViewComponent, XmlTagTableViewComponent, XmlTagViewComponent, XmlTagRichTextViewComponent, XmlTagHtmlViewComponent, XmlTagTextViewComponent, XmlTagHeaderTextViewComponent, XmlTagHeaderInnerTextViewComponent, XmlTagExternalVideoComponent, HtmlRawViewComponent, FileImageTagViewComponent, HtmlViewComponent, MainEditorComponent, FileIdSelectComponent, TextEditorComponent, ExternalVideoBlockComponent, ImageEditorComponent, MainEditorBlockComponent, VisualEditorComponent, AddFilesBtnComponent, HtmlRawEditorComponent, RichTextToHtmlPipe, TagToSpanPipe, ToPreviewPipe, ToHtmlBodyTagsPipe, ToPreviewHtmlPipe] }); }
1769
1838
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: CrocoHtmlModule, imports: [CommonModule,
1770
1839
  FormsModule,
1771
1840
  ReactiveFormsModule,
@@ -1786,7 +1855,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
1786
1855
  ReactiveFormsModule,
1787
1856
  NgSelectModule,
1788
1857
  ...MaterialModules,
1789
- YouTubePlayerModule
1858
+ YouTubePlayerModule,
1859
+ VkVideoPlayerComponent
1790
1860
  ]
1791
1861
  }]
1792
1862
  }] });
@@ -1799,5 +1869,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImpor
1799
1869
  * Generated bundle index. Do not edit.
1800
1870
  */
1801
1871
 
1802
- export { AddFilesBtnComponent, AngularMaterialTableMethods, BodyTagsExtensions, BootstrapTableMethods, CrocoHtmlModule, CrocoHtmlOptionsToken, ExternalVideoBlockComponent, ExternalVideoSupportedTypes, ExternalVideoTagDataConsts, FileIdSelectComponent, FileImageTagDataConsts, FileImageTagViewComponent, HtmlRawEditorComponent, HtmlRawViewComponent, HtmlViewComponent, ImageEditorComponent, ImageMethods, MainEditorBlockComponent, MainEditorComponent, RichTextToHtmlPipe, TableBuilder, TableMethods, TableTypes, TagToSpanPipe, TextEditorComponent, TextMethods, TextSimpleMethods, TextTag, ToHtmlBodyTagsPipe, ToPreviewHtmlPipe, ToPreviewPipe, UploadFilesBtnComponent, VideoMethods, VisualEditorComponent, XmlExtensions, XmlTagExternalVideoComponent, XmlTagHeaderInnerTextViewComponent, XmlTagHeaderTextViewComponent, XmlTagHtmlViewComponent, XmlTagRichTextViewComponent, XmlTagTableViewComponent, XmlTagTextViewComponent, XmlTagViewComponent };
1872
+ export { AddFilesBtnComponent, AngularMaterialTableMethods, BodyTagsExtensions, BootstrapTableMethods, CrocoHtmlModule, CrocoHtmlOptionsToken, ExternalVideoBlockComponent, ExternalVideoPlayers, ExternalVideoSupportedTypes, ExternalVideoTagDataConsts, FileIdSelectComponent, FileImageTagDataConsts, FileImageTagViewComponent, HtmlRawEditorComponent, HtmlRawViewComponent, HtmlViewComponent, ImageEditorComponent, ImageMethods, MainEditorBlockComponent, MainEditorComponent, RichTextToHtmlPipe, TableBuilder, TableMethods, TableTypes, TagToSpanPipe, TextEditorComponent, TextMethods, TextSimpleMethods, TextTag, TextTags, ToHtmlBodyTagsPipe, ToPreviewHtmlPipe, ToPreviewPipe, UploadFilesBtnComponent, VideoMethods, VisualEditorComponent, XmlExtensions, XmlTagExternalVideoComponent, XmlTagHeaderInnerTextViewComponent, XmlTagHeaderTextViewComponent, XmlTagHtmlViewComponent, XmlTagRichTextViewComponent, XmlTagTableViewComponent, XmlTagTextViewComponent, XmlTagViewComponent, defaultLinkVk, defaultLinkYouTube };
1803
1873
  //# sourceMappingURL=croco-html.mjs.map