@talrace/ngx-noder 19.0.52 → 19.0.53

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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Directive, Injectable, signal, inject, ChangeDetectorRef, HostBinding, Input, InjectionToken, Component, ChangeDetectionStrategy, Inject, ViewChild, EventEmitter, Output, HostListener, createComponent, ApplicationRef, Injector, input, computed, effect, NgModule, output } from '@angular/core';
3
- import { Subject, BehaviorSubject, distinctUntilChanged, debounceTime, filter, fromEvent, take, throttleTime, startWith, takeUntil, tap, map, catchError } from 'rxjs';
3
+ import { Subject, BehaviorSubject, distinctUntilChanged, debounceTime, filter, fromEvent, take, throttleTime, startWith, takeUntil, switchMap, from, tap, map, catchError } from 'rxjs';
4
4
  import * as i1$2 from '@angular/common/http';
5
5
  import { HttpHeaders } from '@angular/common/http';
6
6
  import { ComponentPortal } from '@angular/cdk/portal';
@@ -626,6 +626,7 @@ class PageFormatModel {
626
626
  class EditorService {
627
627
  constructor() {
628
628
  this._styles$ = new BehaviorSubject({});
629
+ this._revisionId$ = new BehaviorSubject(0);
629
630
  this._receiveTextStyle$ = new Subject();
630
631
  this._isViewOnly$ = new BehaviorSubject(false);
631
632
  this._isViewOnly = false;
@@ -719,6 +720,8 @@ class EditorService {
719
720
  this._setCommentsVisibility$ = new Subject();
720
721
  this._getCommentText$ = new Subject();
721
722
  this._replaceCommentText$ = new Subject();
723
+ this._requestContentsInsertion$ = new Subject();
724
+ this._insertContents$ = new Subject();
722
725
  this._startNewList$ = new Subject();
723
726
  this._continueNumbering$ = new Subject();
724
727
  this._setNumberingValue$ = new Subject();
@@ -732,6 +735,9 @@ class EditorService {
732
735
  get styles$() {
733
736
  return this._styles$.asObservable();
734
737
  }
738
+ get revisionId() {
739
+ return this._revisionId$.value;
740
+ }
735
741
  get receiveTextStyle$() {
736
742
  return this._receiveTextStyle$.asObservable();
737
743
  }
@@ -1024,6 +1030,12 @@ class EditorService {
1024
1030
  get replaceCommentText$() {
1025
1031
  return this._replaceCommentText$.asObservable();
1026
1032
  }
1033
+ get requestContentsInsertion$() {
1034
+ return this._requestContentsInsertion$.asObservable();
1035
+ }
1036
+ get insertContents$() {
1037
+ return this._insertContents$.asObservable();
1038
+ }
1027
1039
  get startNewList$() {
1028
1040
  return this._startNewList$.asObservable();
1029
1041
  }
@@ -1033,6 +1045,12 @@ class EditorService {
1033
1045
  get setNumberingValue$() {
1034
1046
  return this._setNumberingValue$.asObservable();
1035
1047
  }
1048
+ requestContentsInsertion(contents, from) {
1049
+ this._requestContentsInsertion$.next({ contents, from });
1050
+ }
1051
+ insertContents(contents) {
1052
+ this._insertContents$.next(contents);
1053
+ }
1036
1054
  startNewList() {
1037
1055
  this._startNewList$.next();
1038
1056
  }
@@ -1090,6 +1108,9 @@ class EditorService {
1090
1108
  }
1091
1109
  this._currentPage$.next(value);
1092
1110
  }
1111
+ setRevisionId(id) {
1112
+ this._revisionId$.next(id);
1113
+ }
1093
1114
  receiveTextStyle(component) {
1094
1115
  this._receiveTextStyle$.next(component);
1095
1116
  }
@@ -1666,6 +1687,8 @@ var CommandType;
1666
1687
  CommandType[CommandType["RemoveComment"] = 39] = "RemoveComment";
1667
1688
  CommandType[CommandType["ApplyNumberingLevels"] = 40] = "ApplyNumberingLevels";
1668
1689
  CommandType[CommandType["ApplyNewNumberingForParagraphs"] = 41] = "ApplyNewNumberingForParagraphs";
1690
+ CommandType[CommandType["InsertContents"] = 42] = "InsertContents";
1691
+ CommandType[CommandType["ReplaceByContents"] = 43] = "ReplaceByContents";
1669
1692
  })(CommandType || (CommandType = {}));
1670
1693
 
1671
1694
  class PageNumbersModel {
@@ -1824,6 +1847,112 @@ class BreakHelper {
1824
1847
  }
1825
1848
  }
1826
1849
 
1850
+ class ClipboardHandler {
1851
+ constructor(cdkClipboard) {
1852
+ this.cdkClipboard = cdkClipboard;
1853
+ this.sliceMime = 'application/x-noder-slice+json';
1854
+ this.webSliceMime = `web ${this.sliceMime}`;
1855
+ this.internalState = null;
1856
+ }
1857
+ copyEvent(event, text, slice, revisionId) {
1858
+ if (!event.clipboardData) {
1859
+ this.copyAsync(text, slice, revisionId).catch(() => { });
1860
+ return;
1861
+ }
1862
+ event.preventDefault();
1863
+ const sliceData = this.createSliceData(slice, revisionId);
1864
+ event.clipboardData.setData('text/plain', text);
1865
+ event.clipboardData.setData(this.webSliceMime, JSON.stringify(sliceData));
1866
+ this.internalState = { text, sliceData };
1867
+ this.copyAsync(text, slice, revisionId, false).catch(() => { }); // event not update navigation clipboard! Need update both!
1868
+ }
1869
+ readEvent(event) {
1870
+ if (!event.clipboardData) {
1871
+ return { text: null, sliceData: null };
1872
+ }
1873
+ event.preventDefault();
1874
+ const text = event.clipboardData.getData('text/plain');
1875
+ const sliceJson = event.clipboardData.getData(this.webSliceMime);
1876
+ const sliceData = this.getClipboardSlice(text, sliceJson);
1877
+ return { text: text || null, sliceData };
1878
+ }
1879
+ async copyAsync(text, slice, revisionId, useFallback = true) {
1880
+ const sliceData = this.createSliceData(slice, revisionId);
1881
+ try {
1882
+ const textBlob = new Blob([text], { type: 'text/plain' });
1883
+ const sliceBlob = new Blob([JSON.stringify(sliceData)], { type: this.webSliceMime });
1884
+ const clipboardItem = new ClipboardItem({
1885
+ // eslint-disable-next-line @typescript-eslint/naming-convention
1886
+ 'text/plain': Promise.resolve(textBlob), // Promise for Safari
1887
+ [this.webSliceMime]: Promise.resolve(sliceBlob)
1888
+ });
1889
+ await navigator.clipboard.write([clipboardItem]);
1890
+ }
1891
+ catch {
1892
+ if (useFallback) {
1893
+ this.cdkClipboard.copy(text);
1894
+ }
1895
+ }
1896
+ this.internalState = { text, sliceData };
1897
+ }
1898
+ async readAsync() {
1899
+ try {
1900
+ const items = await navigator.clipboard.read();
1901
+ const item = items[0];
1902
+ if (!item) {
1903
+ return { text: null, sliceData: null };
1904
+ }
1905
+ let text = null;
1906
+ let jsonSliceData = null;
1907
+ if (item.types.includes(this.webSliceMime)) {
1908
+ const sliceBlob = await item.getType(this.webSliceMime);
1909
+ jsonSliceData = await sliceBlob.text();
1910
+ }
1911
+ if (item.types.includes('text/plain')) {
1912
+ const textBlob = await item.getType('text/plain');
1913
+ text = await textBlob.text();
1914
+ }
1915
+ const sliceData = this.getClipboardSlice(text || '', jsonSliceData || '');
1916
+ return { text, sliceData };
1917
+ }
1918
+ catch {
1919
+ return await this.readFallback();
1920
+ }
1921
+ }
1922
+ getClipboardSlice(clipboardText, clipboardSliceData) {
1923
+ if (this.internalState && this.internalState.text === clipboardText) {
1924
+ return this.internalState.sliceData;
1925
+ }
1926
+ if (!clipboardSliceData) {
1927
+ return null;
1928
+ }
1929
+ try {
1930
+ return JSON.parse(clipboardSliceData);
1931
+ }
1932
+ catch {
1933
+ return null;
1934
+ }
1935
+ }
1936
+ async readFallback() {
1937
+ try {
1938
+ const text = await navigator.clipboard.readText();
1939
+ const sliceData = this.getClipboardSlice(text, '');
1940
+ return { text, sliceData };
1941
+ }
1942
+ catch {
1943
+ return { text: null, sliceData: null };
1944
+ }
1945
+ }
1946
+ createSliceData(slice, revisionId) {
1947
+ return {
1948
+ type: 'NODER_SLICE',
1949
+ version: 1,
1950
+ source: { revisionId },
1951
+ data: slice
1952
+ };
1953
+ }
1954
+ }
1955
+
1827
1956
  const COMMENT_TYPES = new InjectionToken('COMMENT_TYPES');
1828
1957
 
1829
1958
  class OverlayService {
@@ -1957,77 +2086,7 @@ class ContentHelper {
1957
2086
  }
1958
2087
  }
1959
2088
 
1960
- const CONTEXT_MENU_HEIGHT = 210;
1961
- const CONTEXT_MENU_WIDTH = 320;
1962
- class ContextMenuComponent {
1963
- constructor(editorService, overlayService) {
1964
- this.editorService = editorService;
1965
- this.overlayService = overlayService;
1966
- }
1967
- ngOnDestroy() {
1968
- this.overlayService.close();
1969
- }
1970
- onCopy() {
1971
- this.editorService.copySelected();
1972
- this.overlayService.close();
1973
- }
1974
- onPaste() {
1975
- this.editorService.pasteFromClipboard();
1976
- this.overlayService.close();
1977
- }
1978
- onCut() {
1979
- this.editorService.cutSelected();
1980
- this.overlayService.close();
1981
- }
1982
- onStartNewList() {
1983
- this.editorService.startNewList();
1984
- this.overlayService.close();
1985
- }
1986
- onContinueNumbering() {
1987
- this.editorService.continueNumbering();
1988
- this.overlayService.close();
1989
- }
1990
- onSetNumberingValue() {
1991
- this.overlayService.close(AfterCloseOverlayActions.OpenSetNumberingValue);
1992
- }
1993
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ContextMenuComponent, deps: [{ token: EditorService }, { token: OverlayService }], target: i0.ɵɵFactoryTarget.Component }); }
1994
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: ContextMenuComponent, isStandalone: true, selector: "app-nod-context-menu", inputs: { hasNumbering: "hasNumbering", hasSelection: "hasSelection", disableContinueNumber: "disableContinueNumber" }, host: { properties: { "style.height.px": "210", "style.width.px": "320" } }, ngImport: i0, template: "<button\n mat-button\n (click)=\"onCopy()\"\n [disabled]=\"!hasSelection\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-copy\" />\n {{ 'NODER.LABEL.COPY' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onPaste()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-paste\" />\n {{ 'NODER.LABEL.PASTE' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onCut()\"\n [disabled]=\"!hasSelection\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cut\" />\n {{ 'NODER.LABEL.CUT' | translate }}\n</button>\n<div class=\"separator\"></div>\n<button\n mat-button\n (click)=\"onStartNewList()\"\n [disabled]=\"!hasNumbering\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-restart-numbering\" />\n {{ 'NODER.LABEL.START_NEW_LIST' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onContinueNumbering()\"\n [disabled]=\"!hasNumbering || disableContinueNumber\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-continue-numbering\" />\n {{ 'NODER.LABEL.CONTINUE_NUMBERING' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onSetNumberingValue()\"\n [disabled]=\"!hasNumbering\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-starting-value\" />\n {{ 'NODER.LABEL.SET_NUMBERING_VALUE' | translate }}\n</button>\n", styles: [":host{display:flex;padding:8px 16px;flex-direction:column;align-items:flex-start;gap:4px;border-radius:8px;box-shadow:2px 2px 8px #21212129}.separator{width:288px;height:1px}button{width:100%;justify-content:start;min-height:28px;height:28px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1995
- }
1996
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ContextMenuComponent, decorators: [{
1997
- type: Component,
1998
- args: [{ selector: 'app-nod-context-menu', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatButtonModule, TranslateModule, MatIconModule], host: {
1999
- '[style.height.px]': `${CONTEXT_MENU_HEIGHT}`,
2000
- '[style.width.px]': `${CONTEXT_MENU_WIDTH}`
2001
- }, template: "<button\n mat-button\n (click)=\"onCopy()\"\n [disabled]=\"!hasSelection\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-copy\" />\n {{ 'NODER.LABEL.COPY' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onPaste()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-paste\" />\n {{ 'NODER.LABEL.PASTE' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onCut()\"\n [disabled]=\"!hasSelection\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cut\" />\n {{ 'NODER.LABEL.CUT' | translate }}\n</button>\n<div class=\"separator\"></div>\n<button\n mat-button\n (click)=\"onStartNewList()\"\n [disabled]=\"!hasNumbering\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-restart-numbering\" />\n {{ 'NODER.LABEL.START_NEW_LIST' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onContinueNumbering()\"\n [disabled]=\"!hasNumbering || disableContinueNumber\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-continue-numbering\" />\n {{ 'NODER.LABEL.CONTINUE_NUMBERING' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onSetNumberingValue()\"\n [disabled]=\"!hasNumbering\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-starting-value\" />\n {{ 'NODER.LABEL.SET_NUMBERING_VALUE' | translate }}\n</button>\n", styles: [":host{display:flex;padding:8px 16px;flex-direction:column;align-items:flex-start;gap:4px;border-radius:8px;box-shadow:2px 2px 8px #21212129}.separator{width:288px;height:1px}button{width:100%;justify-content:start;min-height:28px;height:28px}\n"] }]
2002
- }], ctorParameters: () => [{ type: EditorService }, { type: OverlayService }], propDecorators: { hasNumbering: [{
2003
- type: Input
2004
- }], hasSelection: [{
2005
- type: Input
2006
- }], disableContinueNumber: [{
2007
- type: Input
2008
- }] } });
2009
-
2010
- class CreateEdgesModel {
2011
- constructor(fields) {
2012
- if (fields) {
2013
- Object.assign(this, fields);
2014
- }
2015
- }
2016
- }
2017
-
2018
- const PARENT_TAG = 'APP-NOD-EDITOR';
2019
- const TABLE_CELL_TAG = 'APP-NOD-TABLE-CELL';
2020
- const EDGE_TAG = 'APP-NOD-EDGE';
2021
- const IMAGE_TAG = 'APP-NOD-IMAGE';
2022
- const CUSTOM_TAG = 'app-nod-custom-element';
2023
-
2024
- class CustomElementSearchResult {
2025
- constructor(init) {
2026
- Object.assign(this, init);
2027
- }
2028
- }
2029
-
2030
- class DeleteModel {
2089
+ class BreakModel {
2031
2090
  constructor(fields) {
2032
2091
  if (fields) {
2033
2092
  Object.assign(this, fields);
@@ -2035,98 +2094,24 @@ class DeleteModel {
2035
2094
  }
2036
2095
  }
2037
2096
 
2038
- class BaseHandler {
2039
- constructor() {
2040
- this.actions = {};
2041
- }
2042
- getKeyCombination(event) {
2043
- let result = event.metaKey ? 'Command-' : '';
2044
- if (event.ctrlKey) {
2045
- result = `${result}Ctrl-`;
2046
- }
2047
- if (event.altKey) {
2048
- result = `${result}Alt-`;
2049
- }
2050
- if (event.shiftKey) {
2051
- result = `${result}Shift-`;
2052
- }
2053
- return `${result}${event.code}`;
2054
- }
2055
- }
2056
-
2057
- class DocumentHandler extends BaseHandler {
2058
- constructor(editor) {
2059
- super();
2060
- this.documentKeyDown$ = fromEvent(document, 'keydown').subscribe((event) => this.onKeyDown(event));
2061
- this.contextMenu$ = fromEvent(document, 'contextmenu').subscribe(event => event.preventDefault());
2062
- this.fillActions(editor);
2063
- }
2064
- destroy() {
2065
- this.documentKeyDown$?.unsubscribe();
2066
- this.contextMenu$.unsubscribe();
2067
- }
2068
- onKeyDown(event) {
2069
- const keyCombination = this.getKeyCombination(event);
2070
- if (this.actions[keyCombination]) {
2071
- this.actions[keyCombination](event);
2072
- }
2073
- else {
2074
- return;
2075
- }
2076
- event.preventDefault();
2077
- }
2078
- fillActions(editor) {
2079
- this.actions['Ctrl-KeyP'] = () => editor.onPrint();
2080
- this.actions['Ctrl-KeyO'] = (event) => editor.onHotKeyDown(event);
2081
- }
2082
- }
2083
-
2084
- class DragAndDrop {
2085
- constructor(editorContainer) {
2086
- this.editorContainer = editorContainer;
2087
- this.onMove$ = new Subject();
2088
- this.onDrop$ = new Subject();
2089
- }
2090
- onStart(session, range) {
2091
- if (this.isDragging) {
2092
- return;
2093
- }
2094
- this.isDragging = true;
2095
- this.editorContainer.classList.add('drag-and-drop-progress');
2096
- this.sourceSession = session;
2097
- this.sourceRange = range;
2098
- this.initListeners();
2097
+ class ContentOperationsHelper {
2098
+ static removeContent(content, startIndex, count) {
2099
+ return `${content.slice(0, startIndex)}${content.slice(startIndex + count, content.length)}`;
2099
2100
  }
2100
- destroyListeners() {
2101
- this.mouseMove$?.unsubscribe();
2102
- this.mouseUp$?.unsubscribe();
2101
+ static sliceContent(content, startIndex, count) {
2102
+ return content.slice(startIndex, startIndex + count);
2103
2103
  }
2104
- onEnd() {
2105
- this.destroyListeners();
2106
- if (!this.isDragging) {
2107
- return;
2108
- }
2109
- this.isDragging = false;
2110
- this.editorContainer.classList.remove('drag-and-drop-progress');
2111
- this.onDrop$.next({ sourceSession: this.sourceSession, sourceRange: this.sourceRange });
2104
+ static insertContent(content, text, index) {
2105
+ const before = content.slice(0, index);
2106
+ const after = content.slice(index, content.length);
2107
+ return `${before}${text}${after}`;
2112
2108
  }
2113
- initListeners() {
2114
- this.destroyListeners();
2115
- this.mouseMove$ = fromEvent(document, 'mousemove')
2116
- .pipe(throttleTime(20))
2117
- .subscribe(event => this.onMove$.next(event));
2118
- this.mouseUp$ = fromEvent(document, 'mouseup')
2119
- .pipe(take(1))
2120
- .subscribe(() => this.onEnd());
2109
+ static replaceContent(content, startIndex, endIndex, text) {
2110
+ const reduced = this.removeContent(content, startIndex, endIndex - startIndex + 1);
2111
+ return this.insertContent(reduced, text, startIndex);
2121
2112
  }
2122
2113
  }
2123
2114
 
2124
- var EdgeType;
2125
- (function (EdgeType) {
2126
- EdgeType[EdgeType["Header"] = 0] = "Header";
2127
- EdgeType[EdgeType["Footer"] = 1] = "Footer";
2128
- })(EdgeType || (EdgeType = {}));
2129
-
2130
2115
  class ElementModel {
2131
2116
  constructor(fields) {
2132
2117
  if (fields) {
@@ -2162,58 +2147,504 @@ class FormatHelper {
2162
2147
  }
2163
2148
  }
2164
2149
 
2165
- class GrammarPopupComponent {
2166
- constructor(editorService, overlayService) {
2167
- this.editorService = editorService;
2168
- this.overlayService = overlayService;
2169
- }
2170
- onSuggestionClick(index) {
2171
- this.editorService.applyGrammarSuggestion(this.error, index, this.paragraphIndex);
2172
- this.overlayService.close();
2173
- }
2174
- onIgnoreClick() {
2175
- this.editorService.ignoreGrammarSuggestion(this.error);
2176
- this.overlayService.close();
2150
+ class BordersStyleModel {
2151
+ constructor(fields) {
2152
+ if (fields) {
2153
+ Object.assign(this, fields);
2154
+ }
2177
2155
  }
2178
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: GrammarPopupComponent, deps: [{ token: EditorService }, { token: OverlayService }], target: i0.ɵɵFactoryTarget.Component }); }
2179
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: GrammarPopupComponent, isStandalone: true, selector: "app-nod-grammar-popup", inputs: { error: "error", paragraphIndex: "paragraphIndex" }, ngImport: i0, template: "<span class=\"message\">{{ error.message }}</span>\n<div class=\"options\">\n @for (suggestion of error.replacements; track i; let i = $index) {\n <span\n class=\"suggestion\"\n (click)=\"onSuggestionClick(i)\">\n {{ suggestion }}\n </span>\n }\n</div>\n<button\n mat-button\n class=\"ignore\"\n (click)=\"onIgnoreClick()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-ignore\"></mat-icon>\n <span>\n {{ 'NODER.LABEL.IGNORE' | translate }}\n </span>\n</button>\n", styles: [":host{border-radius:8px;display:flex;flex-direction:column;padding:8px;max-width:500px;gap:5px}.message{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;font-size:12px}.options{display:flex;flex-flow:column wrap;justify-content:center;gap:5px;padding:10px 0;border-bottom-width:1px;border-bottom-style:solid}.suggestion{font-weight:600;font-size:14px;cursor:pointer;text-decoration:underline;padding:3px 8px}.ignore{margin-left:auto;font-size:12px;letter-spacing:0;cursor:pointer;height:32px}.ignore mat-icon{margin-right:4px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2180
2156
  }
2181
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: GrammarPopupComponent, decorators: [{
2182
- type: Component,
2183
- args: [{ selector: 'app-nod-grammar-popup', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatButtonModule, MatIconModule, TranslateModule], standalone: true, template: "<span class=\"message\">{{ error.message }}</span>\n<div class=\"options\">\n @for (suggestion of error.replacements; track i; let i = $index) {\n <span\n class=\"suggestion\"\n (click)=\"onSuggestionClick(i)\">\n {{ suggestion }}\n </span>\n }\n</div>\n<button\n mat-button\n class=\"ignore\"\n (click)=\"onIgnoreClick()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-ignore\"></mat-icon>\n <span>\n {{ 'NODER.LABEL.IGNORE' | translate }}\n </span>\n</button>\n", styles: [":host{border-radius:8px;display:flex;flex-direction:column;padding:8px;max-width:500px;gap:5px}.message{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;font-size:12px}.options{display:flex;flex-flow:column wrap;justify-content:center;gap:5px;padding:10px 0;border-bottom-width:1px;border-bottom-style:solid}.suggestion{font-weight:600;font-size:14px;cursor:pointer;text-decoration:underline;padding:3px 8px}.ignore{margin-left:auto;font-size:12px;letter-spacing:0;cursor:pointer;height:32px}.ignore mat-icon{margin-right:4px}\n"] }]
2184
- }], ctorParameters: () => [{ type: EditorService }, { type: OverlayService }], propDecorators: { error: [{
2185
- type: Input
2186
- }], paragraphIndex: [{
2187
- type: Input
2188
- }] } });
2189
2157
 
2190
- class ImageDataModel {
2158
+ class ImageModel {
2191
2159
  constructor(fields) {
2192
2160
  if (fields) {
2161
+ if (fields.border) {
2162
+ fields.border = new BordersStyleModel(fields.border);
2163
+ }
2193
2164
  Object.assign(this, fields);
2194
2165
  }
2195
2166
  }
2196
2167
  }
2197
2168
 
2198
- class ImageHelper {
2199
- static getImageWithAllowedSize(imageData, maxWidth) {
2200
- if (imageData.width <= maxWidth) {
2201
- return imageData;
2202
- }
2203
- const aspectRatio = imageData.width / imageData.height;
2204
- const height = maxWidth / aspectRatio;
2205
- return new ImageDataModel({ width: Math.round(maxWidth), height: Math.round(height), content: imageData.content });
2169
+ class IndexedElementHelper {
2170
+ static sliceSection(elements, startIndex, endIndex) {
2171
+ return elements.filter(x => x.insertIndex >= startIndex && x.insertIndex <= endIndex);
2172
+ }
2173
+ static shiftIndexes(elements, offset) {
2174
+ for (const element of elements) {
2175
+ element.insertIndex += offset;
2176
+ }
2177
+ }
2178
+ }
2179
+
2180
+ class LinkModel {
2181
+ constructor(fields) {
2182
+ if (fields) {
2183
+ Object.assign(this, fields);
2184
+ }
2185
+ }
2186
+ }
2187
+
2188
+ class LinkHelper {
2189
+ static sliceSection(links, start, end) {
2190
+ return links.map(link => LinkHelper.getPartialLink(link, start, end)).filter(x => x !== null);
2191
+ }
2192
+ static shiftIndexes(links, offset) {
2193
+ for (const link of links) {
2194
+ link.startIndex += offset;
2195
+ link.endIndex += offset;
2196
+ }
2197
+ }
2198
+ static sliceFormats(links, startIndex, endIndex) {
2199
+ const result = [];
2200
+ for (const link of links) {
2201
+ const absoluteFormats = link.formats.map(x => new FormatModel({ ...x, startIndex: x.startIndex + link.startIndex, endIndex: x.endIndex + link.startIndex }));
2202
+ const slicedLinkFormats = FormatHelper.sliceSection(absoluteFormats, startIndex, endIndex);
2203
+ result.push(...slicedLinkFormats);
2204
+ }
2205
+ return result;
2206
+ }
2207
+ static getPartialLink(link, selectionStart, selectionEnd) {
2208
+ if (link.endIndex < selectionStart || link.startIndex > selectionEnd) {
2209
+ return null;
2210
+ }
2211
+ const newStart = Math.max(link.startIndex, selectionStart);
2212
+ const newEnd = Math.min(link.endIndex, selectionEnd);
2213
+ const formats = link.formats
2214
+ .map(format => {
2215
+ const formatStart = link.startIndex + format.startIndex;
2216
+ const formatEnd = link.startIndex + format.endIndex;
2217
+ if (formatEnd < newStart || formatStart > newEnd) {
2218
+ return null;
2219
+ }
2220
+ const newFormatStart = Math.max(formatStart, newStart) - newStart;
2221
+ const newFormatEnd = Math.min(formatEnd, newEnd) - newStart;
2222
+ const textStyle = new TextStyleModel(format.textStyle);
2223
+ return new FormatModel({ startIndex: newFormatStart, endIndex: newFormatEnd, textStyle });
2224
+ })
2225
+ .filter(x => x !== null);
2226
+ return new LinkModel({ ...link, startIndex: newStart, endIndex: newEnd, formats });
2227
+ }
2228
+ }
2229
+
2230
+ class PageFormatHelper {
2231
+ static sliceSection(content, start, end) {
2232
+ if (content instanceof DocxModel) {
2233
+ return content.pageFormats.filter(x => x.insertIndex !== 0 && x.insertIndex >= start && x.insertIndex <= end);
2234
+ }
2235
+ return [];
2236
+ }
2237
+ static shiftIndexes(pagesFormats, offset) {
2238
+ for (const pageFormat of pagesFormats) {
2239
+ if (pageFormat.insertIndex === 0) {
2240
+ return;
2241
+ }
2242
+ pageFormat.insertIndex += offset;
2243
+ }
2244
+ }
2245
+ }
2246
+
2247
+ class ParagraphModel {
2248
+ constructor(fields) {
2249
+ if (fields) {
2250
+ if (fields.paragraphStyle) {
2251
+ fields.paragraphStyle = new ParagraphStyleModel(fields.paragraphStyle);
2252
+ }
2253
+ Object.assign(this, fields);
2254
+ }
2255
+ }
2256
+ }
2257
+
2258
+ class RangeElementHelper {
2259
+ static removeContent(elements, startIndex, endIndex) {
2260
+ const length = endIndex - startIndex + 1;
2261
+ for (let i = elements.length - 1; i >= 0; i--) {
2262
+ const element = elements[i];
2263
+ if (element.endIndex < startIndex) {
2264
+ continue;
2265
+ }
2266
+ if (element.startIndex < startIndex) {
2267
+ if (element.endIndex > endIndex) {
2268
+ element.endIndex -= length;
2269
+ }
2270
+ else {
2271
+ element.endIndex = startIndex - 1;
2272
+ }
2273
+ continue;
2274
+ }
2275
+ if (element.startIndex >= startIndex && element.startIndex <= endIndex) {
2276
+ if (element.endIndex <= endIndex) {
2277
+ elements.splice(i, 1);
2278
+ continue;
2279
+ }
2280
+ element.startIndex -= element.startIndex - startIndex;
2281
+ element.endIndex -= endIndex - element.startIndex;
2282
+ continue;
2283
+ }
2284
+ element.startIndex -= length;
2285
+ element.endIndex -= length;
2286
+ }
2287
+ }
2288
+ static insertContent(elements, index, length) {
2289
+ for (const element of elements) {
2290
+ if (element.startIndex >= index) {
2291
+ element.startIndex += length;
2292
+ element.endIndex += length;
2293
+ }
2294
+ else if (element.endIndex > index) {
2295
+ element.endIndex += length;
2296
+ }
2297
+ }
2298
+ }
2299
+ static insertRelative(elements, insertIndex, insertLength, insertElements) {
2300
+ this.insertContent(elements, insertIndex, insertLength);
2301
+ if (insertElements.length === 0) {
2302
+ return;
2303
+ }
2304
+ for (const element of insertElements) {
2305
+ element.startIndex += insertIndex;
2306
+ element.endIndex += insertIndex;
2307
+ }
2308
+ const targetIndex = elements.findIndex(x => x.startIndex === insertIndex);
2309
+ if (targetIndex < 0) {
2310
+ elements.push(...insertElements);
2311
+ }
2312
+ else {
2313
+ elements.splice(targetIndex, 0, ...insertElements);
2314
+ }
2315
+ }
2316
+ static restore(elements, index, contentLength, newElements) {
2317
+ RangeElementHelper.insertContent(elements, index, contentLength);
2318
+ const nextElement = elements.find(x => x.startIndex >= index);
2319
+ const indexInElements = nextElement !== undefined ? elements.indexOf(nextElement) : elements.length;
2320
+ elements.splice(indexInElements, 0, ...newElements);
2321
+ }
2322
+ static replaceContent(elements, startIndex, endIndex, length) {
2323
+ RangeElementHelper.removeContent(elements, startIndex, endIndex);
2324
+ RangeElementHelper.insertContent(elements, startIndex, length);
2325
+ }
2326
+ static shiftIndexes(elements, offset) {
2327
+ for (const element of elements) {
2328
+ element.startIndex += offset;
2329
+ element.endIndex += offset;
2330
+ }
2331
+ }
2332
+ static sliceSection(elements, startIndex, endIndex) {
2333
+ return elements.filter(x => x.startIndex >= startIndex && x.endIndex <= endIndex);
2334
+ }
2335
+ }
2336
+
2337
+ class RestoreModel {
2338
+ constructor(fields) {
2339
+ if (fields) {
2340
+ Object.assign(this, fields);
2341
+ }
2342
+ }
2343
+ }
2344
+
2345
+ class ContentsModel {
2346
+ constructor(fields) {
2347
+ if (fields) {
2348
+ Object.assign(this, fields);
2349
+ }
2350
+ }
2351
+ }
2352
+
2353
+ class TableModel {
2354
+ constructor(fields) {
2355
+ if (fields) {
2356
+ if (fields.margins) {
2357
+ fields.margins = new MarginsModel(fields.margins);
2358
+ }
2359
+ Object.assign(this, fields);
2360
+ }
2361
+ }
2362
+ }
2363
+
2364
+ class TabModel {
2365
+ constructor(fields) {
2366
+ if (fields) {
2367
+ Object.assign(this, fields);
2368
+ }
2369
+ }
2370
+ }
2371
+
2372
+ class ContentsOperationsHelper {
2373
+ static GetRestoreFromSlice(contents, startIndex, count) {
2374
+ const text = ContentOperationsHelper.sliceContent(contents.content, startIndex, count);
2375
+ const endIndex = startIndex + count - 1;
2376
+ const formats = FormatHelper.sliceSection(contents.formats, startIndex, endIndex);
2377
+ const paragraphs = IndexedElementHelper.sliceSection(contents.paragraphs, startIndex, endIndex).map(x => new ParagraphModel(x));
2378
+ const images = IndexedElementHelper.sliceSection(contents.images, startIndex, endIndex).map(x => new ImageModel(x));
2379
+ const tables = IndexedElementHelper.sliceSection(contents.tables, startIndex, endIndex).map(x => new TableModel(x));
2380
+ const elements = IndexedElementHelper.sliceSection(contents.elements, startIndex, endIndex).map(x => new ElementModel(x));
2381
+ const comments = RangeElementHelper.sliceSection(contents.comments, startIndex, endIndex);
2382
+ const breaks = IndexedElementHelper.sliceSection(contents.breaks, startIndex, endIndex).map(x => new BreakModel(x));
2383
+ const tabs = IndexedElementHelper.sliceSection(contents.tabs, startIndex, endIndex).map(x => new TabModel(x));
2384
+ const links = LinkHelper.sliceSection(contents.links, startIndex, endIndex).map(x => new LinkModel(x));
2385
+ const pageFormats = PageFormatHelper.sliceSection(contents, startIndex, endIndex).map(x => new PageFormatModel(x));
2386
+ return new RestoreModel({
2387
+ insertIndex: startIndex,
2388
+ text,
2389
+ formats,
2390
+ paragraphs,
2391
+ images,
2392
+ tables,
2393
+ elements,
2394
+ breaks,
2395
+ tabs,
2396
+ links,
2397
+ pageFormats,
2398
+ comments
2399
+ });
2400
+ }
2401
+ static GetRelativeContentSlice(contents, startIndex, count) {
2402
+ const content = ContentOperationsHelper.sliceContent(contents.content, startIndex, count);
2403
+ const endIndex = startIndex + count - 1;
2404
+ const formats = FormatHelper.sliceSection(contents.formats, startIndex, endIndex).map(x => new FormatModel(x));
2405
+ const paragraphs = IndexedElementHelper.sliceSection(contents.paragraphs, startIndex, endIndex).map(x => new ParagraphModel(x));
2406
+ const images = IndexedElementHelper.sliceSection(contents.images, startIndex, endIndex).map(x => new ImageModel(x));
2407
+ const tables = IndexedElementHelper.sliceSection(contents.tables, startIndex, endIndex).map(x => new TableModel(x));
2408
+ const elements = IndexedElementHelper.sliceSection(contents.elements, startIndex, endIndex).map(x => new ElementModel(x));
2409
+ const comments = RangeElementHelper.sliceSection(contents.comments, startIndex, endIndex).map(x => new CommentModel(x));
2410
+ const breaks = IndexedElementHelper.sliceSection(contents.breaks, startIndex, endIndex).map(x => new BreakModel(x));
2411
+ const tabs = IndexedElementHelper.sliceSection(contents.tabs, startIndex, endIndex).map(x => new TabModel(x));
2412
+ const links = LinkHelper.sliceSection(contents.links, startIndex, endIndex).map(x => new LinkModel(x));
2413
+ FormatHelper.shiftIndexes(formats, -startIndex);
2414
+ IndexedElementHelper.shiftIndexes(paragraphs, -startIndex);
2415
+ IndexedElementHelper.shiftIndexes(images, -startIndex);
2416
+ IndexedElementHelper.shiftIndexes(tables, -startIndex);
2417
+ IndexedElementHelper.shiftIndexes(elements, -startIndex);
2418
+ IndexedElementHelper.shiftIndexes(breaks, -startIndex);
2419
+ IndexedElementHelper.shiftIndexes(tabs, -startIndex);
2420
+ RangeElementHelper.shiftIndexes(comments, -startIndex);
2421
+ LinkHelper.shiftIndexes(links, -startIndex);
2422
+ return new ContentsModel({
2423
+ content,
2424
+ formats,
2425
+ paragraphs,
2426
+ images,
2427
+ tables,
2428
+ elements,
2429
+ breaks,
2430
+ tabs,
2431
+ links,
2432
+ comments
2433
+ });
2434
+ }
2435
+ }
2436
+
2437
+ const CONTEXT_MENU_HEIGHT = 210;
2438
+ const CONTEXT_MENU_WIDTH = 320;
2439
+ class ContextMenuComponent {
2440
+ constructor(editorService, overlayService) {
2441
+ this.editorService = editorService;
2442
+ this.overlayService = overlayService;
2443
+ }
2444
+ ngOnDestroy() {
2445
+ this.overlayService.close();
2446
+ }
2447
+ onCopy() {
2448
+ this.editorService.copySelected();
2449
+ this.overlayService.close();
2450
+ }
2451
+ onPaste() {
2452
+ this.editorService.pasteFromClipboard();
2453
+ this.overlayService.close();
2454
+ }
2455
+ onCut() {
2456
+ this.editorService.cutSelected();
2457
+ this.overlayService.close();
2458
+ }
2459
+ onStartNewList() {
2460
+ this.editorService.startNewList();
2461
+ this.overlayService.close();
2462
+ }
2463
+ onContinueNumbering() {
2464
+ this.editorService.continueNumbering();
2465
+ this.overlayService.close();
2466
+ }
2467
+ onSetNumberingValue() {
2468
+ this.overlayService.close(AfterCloseOverlayActions.OpenSetNumberingValue);
2469
+ }
2470
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ContextMenuComponent, deps: [{ token: EditorService }, { token: OverlayService }], target: i0.ɵɵFactoryTarget.Component }); }
2471
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: ContextMenuComponent, isStandalone: true, selector: "app-nod-context-menu", inputs: { hasNumbering: "hasNumbering", hasSelection: "hasSelection", disableContinueNumber: "disableContinueNumber" }, host: { properties: { "style.height.px": "210", "style.width.px": "320" } }, ngImport: i0, template: "<button\n mat-button\n (click)=\"onCopy()\"\n [disabled]=\"!hasSelection\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-copy\" />\n {{ 'NODER.LABEL.COPY' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onPaste()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-paste\" />\n {{ 'NODER.LABEL.PASTE' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onCut()\"\n [disabled]=\"!hasSelection\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cut\" />\n {{ 'NODER.LABEL.CUT' | translate }}\n</button>\n<div class=\"separator\"></div>\n<button\n mat-button\n (click)=\"onStartNewList()\"\n [disabled]=\"!hasNumbering\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-restart-numbering\" />\n {{ 'NODER.LABEL.START_NEW_LIST' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onContinueNumbering()\"\n [disabled]=\"!hasNumbering || disableContinueNumber\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-continue-numbering\" />\n {{ 'NODER.LABEL.CONTINUE_NUMBERING' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onSetNumberingValue()\"\n [disabled]=\"!hasNumbering\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-starting-value\" />\n {{ 'NODER.LABEL.SET_NUMBERING_VALUE' | translate }}\n</button>\n", styles: [":host{display:flex;padding:8px 16px;flex-direction:column;align-items:flex-start;gap:4px;border-radius:8px;box-shadow:2px 2px 8px #21212129}.separator{width:288px;height:1px}button{width:100%;justify-content:start;min-height:28px;height:28px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2472
+ }
2473
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ContextMenuComponent, decorators: [{
2474
+ type: Component,
2475
+ args: [{ selector: 'app-nod-context-menu', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatButtonModule, TranslateModule, MatIconModule], host: {
2476
+ '[style.height.px]': `${CONTEXT_MENU_HEIGHT}`,
2477
+ '[style.width.px]': `${CONTEXT_MENU_WIDTH}`
2478
+ }, template: "<button\n mat-button\n (click)=\"onCopy()\"\n [disabled]=\"!hasSelection\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-copy\" />\n {{ 'NODER.LABEL.COPY' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onPaste()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-paste\" />\n {{ 'NODER.LABEL.PASTE' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onCut()\"\n [disabled]=\"!hasSelection\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cut\" />\n {{ 'NODER.LABEL.CUT' | translate }}\n</button>\n<div class=\"separator\"></div>\n<button\n mat-button\n (click)=\"onStartNewList()\"\n [disabled]=\"!hasNumbering\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-restart-numbering\" />\n {{ 'NODER.LABEL.START_NEW_LIST' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onContinueNumbering()\"\n [disabled]=\"!hasNumbering || disableContinueNumber\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-continue-numbering\" />\n {{ 'NODER.LABEL.CONTINUE_NUMBERING' | translate }}\n</button>\n<button\n mat-button\n (click)=\"onSetNumberingValue()\"\n [disabled]=\"!hasNumbering\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-starting-value\" />\n {{ 'NODER.LABEL.SET_NUMBERING_VALUE' | translate }}\n</button>\n", styles: [":host{display:flex;padding:8px 16px;flex-direction:column;align-items:flex-start;gap:4px;border-radius:8px;box-shadow:2px 2px 8px #21212129}.separator{width:288px;height:1px}button{width:100%;justify-content:start;min-height:28px;height:28px}\n"] }]
2479
+ }], ctorParameters: () => [{ type: EditorService }, { type: OverlayService }], propDecorators: { hasNumbering: [{
2480
+ type: Input
2481
+ }], hasSelection: [{
2482
+ type: Input
2483
+ }], disableContinueNumber: [{
2484
+ type: Input
2485
+ }] } });
2486
+
2487
+ class CreateEdgesModel {
2488
+ constructor(fields) {
2489
+ if (fields) {
2490
+ Object.assign(this, fields);
2491
+ }
2492
+ }
2493
+ }
2494
+
2495
+ const PARENT_TAG = 'APP-NOD-EDITOR';
2496
+ const TABLE_CELL_TAG = 'APP-NOD-TABLE-CELL';
2497
+ const EDGE_TAG = 'APP-NOD-EDGE';
2498
+ const IMAGE_TAG = 'APP-NOD-IMAGE';
2499
+ const CUSTOM_TAG = 'app-nod-custom-element';
2500
+
2501
+ class CustomElementSearchResult {
2502
+ constructor(init) {
2503
+ Object.assign(this, init);
2504
+ }
2505
+ }
2506
+
2507
+ class DeleteModel {
2508
+ constructor(fields) {
2509
+ if (fields) {
2510
+ Object.assign(this, fields);
2511
+ }
2512
+ }
2513
+ }
2514
+
2515
+ class BaseHandler {
2516
+ constructor() {
2517
+ this.actions = {};
2518
+ }
2519
+ getKeyCombination(event) {
2520
+ let result = event.metaKey ? 'Command-' : '';
2521
+ if (event.ctrlKey) {
2522
+ result = `${result}Ctrl-`;
2523
+ }
2524
+ if (event.altKey) {
2525
+ result = `${result}Alt-`;
2526
+ }
2527
+ if (event.shiftKey) {
2528
+ result = `${result}Shift-`;
2529
+ }
2530
+ return `${result}${event.code}`;
2531
+ }
2532
+ }
2533
+
2534
+ class DocumentHandler extends BaseHandler {
2535
+ constructor(editor) {
2536
+ super();
2537
+ this.documentKeyDown$ = fromEvent(document, 'keydown').subscribe((event) => this.onKeyDown(event));
2538
+ this.contextMenu$ = fromEvent(document, 'contextmenu').subscribe(event => event.preventDefault());
2539
+ this.fillActions(editor);
2540
+ }
2541
+ destroy() {
2542
+ this.documentKeyDown$?.unsubscribe();
2543
+ this.contextMenu$.unsubscribe();
2544
+ }
2545
+ onKeyDown(event) {
2546
+ const keyCombination = this.getKeyCombination(event);
2547
+ if (this.actions[keyCombination]) {
2548
+ this.actions[keyCombination](event);
2549
+ }
2550
+ else {
2551
+ return;
2552
+ }
2553
+ event.preventDefault();
2554
+ }
2555
+ fillActions(editor) {
2556
+ this.actions['Ctrl-KeyP'] = () => editor.onPrint();
2557
+ this.actions['Ctrl-KeyO'] = (event) => editor.onHotKeyDown(event);
2558
+ }
2559
+ }
2560
+
2561
+ class DragAndDrop {
2562
+ constructor(editorContainer) {
2563
+ this.editorContainer = editorContainer;
2564
+ this.onMove$ = new Subject();
2565
+ this.onDrop$ = new Subject();
2566
+ }
2567
+ onStart(session, range) {
2568
+ if (this.isDragging) {
2569
+ return;
2570
+ }
2571
+ this.isDragging = true;
2572
+ this.editorContainer.classList.add('drag-and-drop-progress');
2573
+ this.sourceSession = session;
2574
+ this.sourceRange = range;
2575
+ this.initListeners();
2576
+ }
2577
+ destroyListeners() {
2578
+ this.mouseMove$?.unsubscribe();
2579
+ this.mouseUp$?.unsubscribe();
2580
+ }
2581
+ onEnd() {
2582
+ this.destroyListeners();
2583
+ if (!this.isDragging) {
2584
+ return;
2585
+ }
2586
+ this.isDragging = false;
2587
+ this.editorContainer.classList.remove('drag-and-drop-progress');
2588
+ this.onDrop$.next({ sourceSession: this.sourceSession, sourceRange: this.sourceRange });
2589
+ }
2590
+ initListeners() {
2591
+ this.destroyListeners();
2592
+ this.mouseMove$ = fromEvent(document, 'mousemove')
2593
+ .pipe(throttleTime(20))
2594
+ .subscribe(event => this.onMove$.next(event));
2595
+ this.mouseUp$ = fromEvent(document, 'mouseup')
2596
+ .pipe(take(1))
2597
+ .subscribe(() => this.onEnd());
2598
+ }
2599
+ }
2600
+
2601
+ var EdgeType;
2602
+ (function (EdgeType) {
2603
+ EdgeType[EdgeType["Header"] = 0] = "Header";
2604
+ EdgeType[EdgeType["Footer"] = 1] = "Footer";
2605
+ })(EdgeType || (EdgeType = {}));
2606
+
2607
+ class GrammarPopupComponent {
2608
+ constructor(editorService, overlayService) {
2609
+ this.editorService = editorService;
2610
+ this.overlayService = overlayService;
2611
+ }
2612
+ onSuggestionClick(index) {
2613
+ this.editorService.applyGrammarSuggestion(this.error, index, this.paragraphIndex);
2614
+ this.overlayService.close();
2615
+ }
2616
+ onIgnoreClick() {
2617
+ this.editorService.ignoreGrammarSuggestion(this.error);
2618
+ this.overlayService.close();
2206
2619
  }
2620
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: GrammarPopupComponent, deps: [{ token: EditorService }, { token: OverlayService }], target: i0.ɵɵFactoryTarget.Component }); }
2621
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: GrammarPopupComponent, isStandalone: true, selector: "app-nod-grammar-popup", inputs: { error: "error", paragraphIndex: "paragraphIndex" }, ngImport: i0, template: "<span class=\"message\">{{ error.message }}</span>\n<div class=\"options\">\n @for (suggestion of error.replacements; track i; let i = $index) {\n <span\n class=\"suggestion\"\n (click)=\"onSuggestionClick(i)\">\n {{ suggestion }}\n </span>\n }\n</div>\n<button\n mat-button\n class=\"ignore\"\n (click)=\"onIgnoreClick()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-ignore\"></mat-icon>\n <span>\n {{ 'NODER.LABEL.IGNORE' | translate }}\n </span>\n</button>\n", styles: [":host{border-radius:8px;display:flex;flex-direction:column;padding:8px;max-width:500px;gap:5px}.message{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;font-size:12px}.options{display:flex;flex-flow:column wrap;justify-content:center;gap:5px;padding:10px 0;border-bottom-width:1px;border-bottom-style:solid}.suggestion{font-weight:600;font-size:14px;cursor:pointer;text-decoration:underline;padding:3px 8px}.ignore{margin-left:auto;font-size:12px;letter-spacing:0;cursor:pointer;height:32px}.ignore mat-icon{margin-right:4px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i6.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2207
2622
  }
2623
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: GrammarPopupComponent, decorators: [{
2624
+ type: Component,
2625
+ args: [{ selector: 'app-nod-grammar-popup', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatButtonModule, MatIconModule, TranslateModule], standalone: true, template: "<span class=\"message\">{{ error.message }}</span>\n<div class=\"options\">\n @for (suggestion of error.replacements; track i; let i = $index) {\n <span\n class=\"suggestion\"\n (click)=\"onSuggestionClick(i)\">\n {{ suggestion }}\n </span>\n }\n</div>\n<button\n mat-button\n class=\"ignore\"\n (click)=\"onIgnoreClick()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-ignore\"></mat-icon>\n <span>\n {{ 'NODER.LABEL.IGNORE' | translate }}\n </span>\n</button>\n", styles: [":host{border-radius:8px;display:flex;flex-direction:column;padding:8px;max-width:500px;gap:5px}.message{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;font-size:12px}.options{display:flex;flex-flow:column wrap;justify-content:center;gap:5px;padding:10px 0;border-bottom-width:1px;border-bottom-style:solid}.suggestion{font-weight:600;font-size:14px;cursor:pointer;text-decoration:underline;padding:3px 8px}.ignore{margin-left:auto;font-size:12px;letter-spacing:0;cursor:pointer;height:32px}.ignore mat-icon{margin-right:4px}\n"] }]
2626
+ }], ctorParameters: () => [{ type: EditorService }, { type: OverlayService }], propDecorators: { error: [{
2627
+ type: Input
2628
+ }], paragraphIndex: [{
2629
+ type: Input
2630
+ }] } });
2208
2631
 
2209
- class IndexedElementHelper {
2210
- static sliceSection(elements, startIndex, endIndex) {
2211
- return elements.filter(x => x.insertIndex >= startIndex && x.insertIndex <= endIndex);
2632
+ class ImageDataModel {
2633
+ constructor(fields) {
2634
+ if (fields) {
2635
+ Object.assign(this, fields);
2636
+ }
2212
2637
  }
2213
- static shiftIndexes(elements, offset) {
2214
- for (const element of elements) {
2215
- element.insertIndex += offset;
2638
+ }
2639
+
2640
+ class ImageHelper {
2641
+ static getImageWithAllowedSize(imageData, maxWidth) {
2642
+ if (imageData.width <= maxWidth) {
2643
+ return imageData;
2216
2644
  }
2645
+ const aspectRatio = imageData.width / imageData.height;
2646
+ const height = maxWidth / aspectRatio;
2647
+ return new ImageDataModel({ width: Math.round(maxWidth), height: Math.round(height), content: imageData.content });
2217
2648
  }
2218
2649
  }
2219
2650
 
@@ -2373,6 +2804,17 @@ class InsertBreakModel {
2373
2804
  }
2374
2805
  }
2375
2806
 
2807
+ class InsertContentsModel {
2808
+ constructor(fields) {
2809
+ if (fields) {
2810
+ if (fields.contents) {
2811
+ fields.contents = new ContentsModel(fields.contents);
2812
+ }
2813
+ Object.assign(this, fields);
2814
+ }
2815
+ }
2816
+ }
2817
+
2376
2818
  class InsertElementModel {
2377
2819
  constructor(fields) {
2378
2820
  if (fields) {
@@ -2476,56 +2918,6 @@ class InsertTextModel {
2476
2918
  }
2477
2919
  }
2478
2920
 
2479
- class LinkModel {
2480
- constructor(fields) {
2481
- if (fields) {
2482
- Object.assign(this, fields);
2483
- }
2484
- }
2485
- }
2486
-
2487
- class LinkHelper {
2488
- static sliceSection(links, start, end) {
2489
- return links.map(link => LinkHelper.getPartialLink(link, start, end)).filter(x => x !== null);
2490
- }
2491
- static shiftIndexes(links, offset) {
2492
- for (const link of links) {
2493
- link.startIndex += offset;
2494
- link.endIndex += offset;
2495
- }
2496
- }
2497
- static sliceFormats(links, startIndex, endIndex) {
2498
- const result = [];
2499
- for (const link of links) {
2500
- const absoluteFormats = link.formats.map(x => new FormatModel({ ...x, startIndex: x.startIndex + link.startIndex, endIndex: x.endIndex + link.startIndex }));
2501
- const slicedLinkFormats = FormatHelper.sliceSection(absoluteFormats, startIndex, endIndex);
2502
- result.push(...slicedLinkFormats);
2503
- }
2504
- return result;
2505
- }
2506
- static getPartialLink(link, selectionStart, selectionEnd) {
2507
- if (link.endIndex < selectionStart || link.startIndex > selectionEnd) {
2508
- return null;
2509
- }
2510
- const newStart = Math.max(link.startIndex, selectionStart);
2511
- const newEnd = Math.min(link.endIndex, selectionEnd);
2512
- const formats = link.formats
2513
- .map(format => {
2514
- const formatStart = link.startIndex + format.startIndex;
2515
- const formatEnd = link.startIndex + format.endIndex;
2516
- if (formatEnd < newStart || formatStart > newEnd) {
2517
- return null;
2518
- }
2519
- const newFormatStart = Math.max(formatStart, newStart) - newStart;
2520
- const newFormatEnd = Math.min(formatEnd, newEnd) - newStart;
2521
- const textStyle = new TextStyleModel(format.textStyle);
2522
- return new FormatModel({ startIndex: newFormatStart, endIndex: newFormatEnd, textStyle });
2523
- })
2524
- .filter(x => x !== null);
2525
- return new LinkModel({ ...link, startIndex: newStart, endIndex: newEnd, formats });
2526
- }
2527
- }
2528
-
2529
2921
  var MouseButton;
2530
2922
  (function (MouseButton) {
2531
2923
  MouseButton[MouseButton["Left"] = 0] = "Left";
@@ -2658,14 +3050,6 @@ class RemoveTableRowsModel {
2658
3050
  }
2659
3051
  }
2660
3052
 
2661
- class RestoreModel {
2662
- constructor(fields) {
2663
- if (fields) {
2664
- Object.assign(this, fields);
2665
- }
2666
- }
2667
- }
2668
-
2669
3053
  class ReplaceByRestoreModel {
2670
3054
  constructor(fields) {
2671
3055
  if (fields) {
@@ -2875,6 +3259,12 @@ class OperationHistory {
2875
3259
  pushMoveRange(restore, replace, selection) {
2876
3260
  this.addToHistory(restore, replace, selection, []);
2877
3261
  }
3262
+ pushInsertContents(undo, redo) {
3263
+ this.addToHistory(undo, redo);
3264
+ }
3265
+ pushReplaceByContents(undo, redo) {
3266
+ this.addToHistory(undo, redo);
3267
+ }
2878
3268
  pushReplace(restore, replace) {
2879
3269
  let count = replace.insertText ? replace.insertText.text.length : 1;
2880
3270
  if (replace.insertTable?.insertParagraphBefore) {
@@ -2904,242 +3294,112 @@ class OperationHistory {
2904
3294
  pushInsertPageFormat(undoStep, redoStep) {
2905
3295
  this.addToHistory(undoStep, redoStep);
2906
3296
  }
2907
- popUndoOperation() {
2908
- if (this.step === -1) {
2909
- return null;
2910
- }
2911
- const operation = this.storage[this.step].undo;
2912
- const targets = this.storage[this.step].targets;
2913
- const cursor = this.storage[this.step].cursor;
2914
- const anchor = this.storage[this.step].anchor;
2915
- this.step--;
2916
- this.editorService.historyInfo = new OperationsHistoryInfoModel(this.step, this.storage.length - 1);
2917
- return { operation, targets, cursor, anchor };
2918
- }
2919
- popRedoOperation() {
2920
- if (this.step >= this.storage.length - 1) {
2921
- return null;
2922
- }
2923
- this.step++;
2924
- const operation = this.storage[this.step].redo;
2925
- const targets = this.storage[this.step].targets;
2926
- const cursor = this.storage[this.step].cursor;
2927
- const anchor = this.storage[this.step].anchor;
2928
- this.editorService.historyInfo = new OperationsHistoryInfoModel(this.step, this.storage.length - 1);
2929
- return { operation, targets, cursor, anchor };
2930
- }
2931
- addToHistory(undoStep, redoStep, selection = null, targets = null) {
2932
- targets ??= this.regulatorService.getCurrentSessionTargets();
2933
- const cursor = selection?.start ?? this.regulatorService.selection.cursor;
2934
- const anchor = selection?.end ?? this.regulatorService.selection.anchor;
2935
- this.step++;
2936
- this.storage.splice(this.step, this.storage.length);
2937
- this.storage.push({ undo: undoStep, redo: redoStep, targets, cursor, anchor });
2938
- if (this.storage.length > this.MAX_HISTORY) {
2939
- this.storage.splice(0, 1);
2940
- this.step--;
2941
- }
2942
- this.editorService.historyInfo = new OperationsHistoryInfoModel(this.step, this.storage.length - 1);
2943
- }
2944
- }
2945
-
2946
- class BreakModel {
2947
- constructor(fields) {
2948
- if (fields) {
2949
- Object.assign(this, fields);
2950
- }
2951
- }
2952
- }
2953
-
2954
- class IndexedElementOperationsHelper {
2955
- static removeContent(elements, startIndex, endIndex) {
2956
- const length = endIndex - startIndex + 1;
2957
- for (let i = elements.length - 1; i >= 0; i--) {
2958
- if (elements[i].insertIndex >= startIndex && elements[i].insertIndex <= endIndex) {
2959
- elements.splice(i, 1);
2960
- }
2961
- }
2962
- elements.forEach(x => {
2963
- if (x.insertIndex > endIndex) {
2964
- x.insertIndex -= length;
2965
- }
2966
- });
2967
- }
2968
- static insert(elements, element, length = 1) {
2969
- this.insertContent(elements, element.insertIndex, length);
2970
- const index = elements.findIndex(x => x.insertIndex > element.insertIndex);
2971
- if (index < 0) {
2972
- elements.push(element);
2973
- }
2974
- else {
2975
- elements.splice(index, 0, element);
2976
- }
2977
- }
2978
- static insertContent(elements, index, length) {
2979
- elements.forEach(x => {
2980
- if (x.insertIndex >= index) {
2981
- x.insertIndex += length;
2982
- }
2983
- });
2984
- }
2985
- static restore(elements, index, contentLength, newElements) {
2986
- this.insertContent(elements, index, contentLength);
2987
- let indexInElements = elements.findIndex(x => x.insertIndex >= index);
2988
- indexInElements = indexInElements === -1 ? elements.length : indexInElements;
2989
- elements.splice(indexInElements, 0, ...newElements);
2990
- }
2991
- static replaceContent(elements, startIndex, endIndex, length) {
2992
- this.removeContent(elements, startIndex, endIndex);
2993
- this.insertContent(elements, startIndex, length);
2994
- }
2995
- }
2996
-
2997
- class BreakOperationsHelper {
2998
- static insertContent(elements, index, breakType, length) {
2999
- const element = new BreakModel({ insertIndex: index, breakType });
3000
- IndexedElementOperationsHelper.insert(elements, element, length);
3001
- }
3002
- }
3003
-
3004
- class CellModel {
3005
- constructor(fields) {
3006
- if (fields) {
3007
- if (fields.margins) {
3008
- fields.margins = new MarginsModel(fields.margins);
3009
- }
3010
- Object.assign(this, fields);
3011
- }
3012
- }
3013
- }
3014
-
3015
- class ContentOperationsHelper {
3016
- static removeContent(content, startIndex, count) {
3017
- return `${content.slice(0, startIndex)}${content.slice(startIndex + count, content.length)}`;
3018
- }
3019
- static sliceContent(content, startIndex, count) {
3020
- return content.slice(startIndex, startIndex + count);
3021
- }
3022
- static insertContent(content, text, index) {
3023
- const before = content.slice(0, index);
3024
- const after = content.slice(index, content.length);
3025
- return `${before}${text}${after}`;
3026
- }
3027
- static replaceContent(content, startIndex, endIndex, text) {
3028
- const reduced = this.removeContent(content, startIndex, endIndex - startIndex + 1);
3029
- return this.insertContent(reduced, text, startIndex);
3030
- }
3031
- }
3032
-
3033
- class BordersStyleModel {
3034
- constructor(fields) {
3035
- if (fields) {
3036
- Object.assign(this, fields);
3037
- }
3038
- }
3039
- }
3040
-
3041
- class ImageModel {
3042
- constructor(fields) {
3043
- if (fields) {
3044
- if (fields.border) {
3045
- fields.border = new BordersStyleModel(fields.border);
3046
- }
3047
- Object.assign(this, fields);
3048
- }
3049
- }
3050
- }
3051
-
3052
- class PageFormatHelper {
3053
- static sliceSection(content, start, end) {
3054
- if (content instanceof DocxModel) {
3055
- return content.pageFormats.filter(x => x.insertIndex !== 0 && x.insertIndex >= start && x.insertIndex <= end);
3297
+ popUndoOperation() {
3298
+ if (this.step === -1) {
3299
+ return null;
3056
3300
  }
3057
- return [];
3301
+ const operation = this.storage[this.step].undo;
3302
+ const targets = this.storage[this.step].targets;
3303
+ const cursor = this.storage[this.step].cursor;
3304
+ const anchor = this.storage[this.step].anchor;
3305
+ this.step--;
3306
+ this.editorService.historyInfo = new OperationsHistoryInfoModel(this.step, this.storage.length - 1);
3307
+ return { operation, targets, cursor, anchor };
3058
3308
  }
3059
- static shiftIndexes(pagesFormats, offset) {
3060
- for (const pageFormat of pagesFormats) {
3061
- if (pageFormat.insertIndex === 0) {
3062
- return;
3063
- }
3064
- pageFormat.insertIndex += offset;
3309
+ popRedoOperation() {
3310
+ if (this.step >= this.storage.length - 1) {
3311
+ return null;
3065
3312
  }
3313
+ this.step++;
3314
+ const operation = this.storage[this.step].redo;
3315
+ const targets = this.storage[this.step].targets;
3316
+ const cursor = this.storage[this.step].cursor;
3317
+ const anchor = this.storage[this.step].anchor;
3318
+ this.editorService.historyInfo = new OperationsHistoryInfoModel(this.step, this.storage.length - 1);
3319
+ return { operation, targets, cursor, anchor };
3066
3320
  }
3067
- }
3068
-
3069
- class ParagraphModel {
3070
- constructor(fields) {
3071
- if (fields) {
3072
- if (fields.paragraphStyle) {
3073
- fields.paragraphStyle = new ParagraphStyleModel(fields.paragraphStyle);
3074
- }
3075
- Object.assign(this, fields);
3321
+ addToHistory(undoStep, redoStep, selection = null, targets = null) {
3322
+ targets ??= this.regulatorService.getCurrentSessionTargets();
3323
+ const cursor = selection?.start ?? this.regulatorService.selection.cursor;
3324
+ const anchor = selection?.end ?? this.regulatorService.selection.anchor;
3325
+ this.step++;
3326
+ this.storage.splice(this.step, this.storage.length);
3327
+ this.storage.push({ undo: undoStep, redo: redoStep, targets, cursor, anchor });
3328
+ if (this.storage.length > this.MAX_HISTORY) {
3329
+ this.storage.splice(0, 1);
3330
+ this.step--;
3076
3331
  }
3332
+ this.editorService.historyInfo = new OperationsHistoryInfoModel(this.step, this.storage.length - 1);
3077
3333
  }
3078
3334
  }
3079
3335
 
3080
- class RangeElementHelper {
3336
+ class IndexedElementOperationsHelper {
3081
3337
  static removeContent(elements, startIndex, endIndex) {
3082
3338
  const length = endIndex - startIndex + 1;
3083
3339
  for (let i = elements.length - 1; i >= 0; i--) {
3084
- const element = elements[i];
3085
- if (element.endIndex < startIndex) {
3086
- continue;
3087
- }
3088
- if (element.startIndex < startIndex) {
3089
- if (element.endIndex > endIndex) {
3090
- element.endIndex -= length;
3091
- }
3092
- else {
3093
- element.endIndex = startIndex - 1;
3094
- }
3095
- continue;
3340
+ if (elements[i].insertIndex >= startIndex && elements[i].insertIndex <= endIndex) {
3341
+ elements.splice(i, 1);
3096
3342
  }
3097
- if (element.startIndex >= startIndex && element.startIndex <= endIndex) {
3098
- if (element.endIndex <= endIndex) {
3099
- elements.splice(i, 1);
3100
- continue;
3101
- }
3102
- element.startIndex -= element.startIndex - startIndex;
3103
- element.endIndex -= endIndex - element.startIndex;
3104
- continue;
3343
+ }
3344
+ elements.forEach(x => {
3345
+ if (x.insertIndex > endIndex) {
3346
+ x.insertIndex -= length;
3105
3347
  }
3106
- element.startIndex -= length;
3107
- element.endIndex -= length;
3348
+ });
3349
+ }
3350
+ static insert(elements, element, length = 1) {
3351
+ this.insertContent(elements, element.insertIndex, length);
3352
+ const index = elements.findIndex(x => x.insertIndex > element.insertIndex);
3353
+ if (index < 0) {
3354
+ elements.push(element);
3355
+ }
3356
+ else {
3357
+ elements.splice(index, 0, element);
3108
3358
  }
3109
3359
  }
3110
3360
  static insertContent(elements, index, length) {
3111
- for (const element of elements) {
3112
- if (element.startIndex >= index) {
3113
- element.startIndex += length;
3114
- element.endIndex += length;
3115
- }
3116
- else if (element.endIndex > index) {
3117
- element.endIndex += length;
3361
+ elements.forEach(x => {
3362
+ if (x.insertIndex >= index) {
3363
+ x.insertIndex += length;
3118
3364
  }
3365
+ });
3366
+ }
3367
+ static insertRelative(elements, insertIndex, insertLength, insertElements) {
3368
+ this.insertContent(elements, insertIndex, insertLength);
3369
+ if (insertElements.length === 0) {
3370
+ return;
3371
+ }
3372
+ for (const element of insertElements) {
3373
+ element.insertIndex += insertIndex;
3374
+ }
3375
+ const targetIndex = elements.findIndex(x => x.insertIndex > insertIndex);
3376
+ if (targetIndex < 0) {
3377
+ elements.push(...insertElements);
3378
+ }
3379
+ else {
3380
+ elements.splice(targetIndex, 0, ...insertElements);
3119
3381
  }
3120
3382
  }
3121
3383
  static restore(elements, index, contentLength, newElements) {
3122
- RangeElementHelper.insertContent(elements, index, contentLength);
3123
- const nextElement = elements.find(x => x.startIndex >= index);
3124
- const indexInElements = nextElement !== undefined ? elements.indexOf(nextElement) : elements.length;
3384
+ this.insertContent(elements, index, contentLength);
3385
+ let indexInElements = elements.findIndex(x => x.insertIndex >= index);
3386
+ indexInElements = indexInElements === -1 ? elements.length : indexInElements;
3125
3387
  elements.splice(indexInElements, 0, ...newElements);
3126
3388
  }
3127
3389
  static replaceContent(elements, startIndex, endIndex, length) {
3128
- RangeElementHelper.removeContent(elements, startIndex, endIndex);
3129
- RangeElementHelper.insertContent(elements, startIndex, length);
3130
- }
3131
- static shiftIndexes(elements, offset) {
3132
- for (const element of elements) {
3133
- element.startIndex += offset;
3134
- element.endIndex += offset;
3135
- }
3390
+ this.removeContent(elements, startIndex, endIndex);
3391
+ this.insertContent(elements, startIndex, length);
3136
3392
  }
3137
- static sliceSection(elements, startIndex, endIndex) {
3138
- return elements.filter(x => x.startIndex >= startIndex && x.endIndex <= endIndex);
3393
+ }
3394
+
3395
+ class BreakOperationsHelper {
3396
+ static insertContent(elements, index, breakType, length) {
3397
+ const element = new BreakModel({ insertIndex: index, breakType });
3398
+ IndexedElementOperationsHelper.insert(elements, element, length);
3139
3399
  }
3140
3400
  }
3141
3401
 
3142
- class TableModel {
3402
+ class CellModel {
3143
3403
  constructor(fields) {
3144
3404
  if (fields) {
3145
3405
  if (fields.margins) {
@@ -3150,45 +3410,6 @@ class TableModel {
3150
3410
  }
3151
3411
  }
3152
3412
 
3153
- class TabModel {
3154
- constructor(fields) {
3155
- if (fields) {
3156
- Object.assign(this, fields);
3157
- }
3158
- }
3159
- }
3160
-
3161
- class ContentsOperationsHelper {
3162
- static GetRestoreFromSlice(contents, startIndex, count) {
3163
- const text = ContentOperationsHelper.sliceContent(contents.content, startIndex, count);
3164
- const endIndex = startIndex + count - 1;
3165
- const formats = FormatHelper.sliceSection(contents.formats, startIndex, endIndex);
3166
- const paragraphs = IndexedElementHelper.sliceSection(contents.paragraphs, startIndex, endIndex).map(x => new ParagraphModel(x));
3167
- const images = IndexedElementHelper.sliceSection(contents.images, startIndex, endIndex).map(x => new ImageModel(x));
3168
- const tables = IndexedElementHelper.sliceSection(contents.tables, startIndex, endIndex).map(x => new TableModel(x));
3169
- const elements = IndexedElementHelper.sliceSection(contents.elements, startIndex, endIndex).map(x => new ElementModel(x));
3170
- const comments = RangeElementHelper.sliceSection(contents.comments, startIndex, endIndex);
3171
- const breaks = IndexedElementHelper.sliceSection(contents.breaks, startIndex, endIndex).map(x => new BreakModel(x));
3172
- const tabs = IndexedElementHelper.sliceSection(contents.tabs, startIndex, endIndex).map(x => new TabModel(x));
3173
- const links = LinkHelper.sliceSection(contents.links, startIndex, endIndex).map(x => new LinkModel(x));
3174
- const pageFormats = PageFormatHelper.sliceSection(contents, startIndex, endIndex).map(x => new PageFormatModel(x));
3175
- return new RestoreModel({
3176
- insertIndex: startIndex,
3177
- text,
3178
- formats,
3179
- paragraphs,
3180
- images,
3181
- tables,
3182
- elements,
3183
- breaks,
3184
- tabs,
3185
- links,
3186
- pageFormats,
3187
- comments
3188
- });
3189
- }
3190
- }
3191
-
3192
3413
  class EdgeModel {
3193
3414
  constructor(fields) {
3194
3415
  if (fields) {
@@ -3252,6 +3473,14 @@ class FormatOperationsHelper {
3252
3473
  }
3253
3474
  });
3254
3475
  }
3476
+ static insertRelative(formats, insertIndex, insertLength, insertFormats) {
3477
+ this.insertContent(formats, insertIndex, insertLength);
3478
+ for (const format of insertFormats) {
3479
+ format.startIndex += insertIndex;
3480
+ format.endIndex += insertIndex;
3481
+ this.apply(formats, format.startIndex, format.endIndex, format.textStyle);
3482
+ }
3483
+ }
3255
3484
  static insertStyledContent(formats, index, textLength, style) {
3256
3485
  this.insertContent(formats, index, textLength);
3257
3486
  this.apply(formats, index, index + textLength - 1, style);
@@ -3354,6 +3583,24 @@ class LinkOperationsHelper {
3354
3583
  }
3355
3584
  }
3356
3585
  }
3586
+ static insertRelative(links, insertIndex, insertLength, insertLinks) {
3587
+ this.insertContent(links, insertIndex, insertLength);
3588
+ if (insertLinks.length === 0) {
3589
+ return;
3590
+ }
3591
+ for (const link of links) {
3592
+ link.startIndex += insertIndex;
3593
+ link.endIndex += insertIndex;
3594
+ }
3595
+ const targetIndex = links.findIndex(x => x.startIndex === insertIndex);
3596
+ if (targetIndex < 0) {
3597
+ links.push(...insertLinks);
3598
+ }
3599
+ else {
3600
+ links.splice(targetIndex, 0, ...insertLinks);
3601
+ }
3602
+ this.merge(links, insertIndex - 1, insertIndex + insertLength);
3603
+ }
3357
3604
  static removeContent(links, startIndex, endIndex) {
3358
3605
  const length = endIndex - startIndex + 1;
3359
3606
  for (let i = links.length - 1; i >= 0; i--) {
@@ -5778,6 +6025,17 @@ class OperationsHelper {
5778
6025
  this.removeComment(document, model.commentId);
5779
6026
  break;
5780
6027
  }
6028
+ case CommandType.InsertContents: {
6029
+ const model = command.insertContents;
6030
+ this.insertContents(contents, model.insertIndex, model.contents);
6031
+ break;
6032
+ }
6033
+ case CommandType.ReplaceByContents: {
6034
+ const model = command.replaceByContents;
6035
+ this.delete(contents, model.startIndex, model.count);
6036
+ this.insertContents(contents, model.startIndex, model.contents);
6037
+ break;
6038
+ }
5781
6039
  }
5782
6040
  });
5783
6041
  }
@@ -6033,6 +6291,22 @@ class OperationsHelper {
6033
6291
  document.comments = document.comments.filter(x => x.commentId !== commentId);
6034
6292
  return comment;
6035
6293
  }
6294
+ static insertContents(contents, insertIndex, insertContents) {
6295
+ const contentLength = insertContents.content.length;
6296
+ contents.content = ContentOperationsHelper.insertContent(contents.content, insertContents.content, insertIndex);
6297
+ IndexedElementOperationsHelper.insertRelative(contents.paragraphs, insertIndex, contentLength, insertContents.paragraphs);
6298
+ IndexedElementOperationsHelper.insertRelative(contents.images, insertIndex, contentLength, insertContents.images);
6299
+ IndexedElementOperationsHelper.insertRelative(contents.tables, insertIndex, contentLength, insertContents.tables);
6300
+ IndexedElementOperationsHelper.insertRelative(contents.elements, insertIndex, contentLength, insertContents.elements);
6301
+ IndexedElementOperationsHelper.insertRelative(contents.breaks, insertIndex, contentLength, insertContents.breaks);
6302
+ IndexedElementOperationsHelper.insertRelative(contents.tabs, insertIndex, contentLength, insertContents.tabs);
6303
+ FormatOperationsHelper.insertRelative(contents.formats, insertIndex, contentLength, insertContents.formats);
6304
+ RangeElementHelper.insertRelative(contents.comments, insertIndex, contentLength, insertContents.comments);
6305
+ LinkOperationsHelper.insertRelative(contents.links, insertIndex, contentLength, insertContents.links);
6306
+ if (contents instanceof DocxModel) {
6307
+ PageFormatOperationsHelper.insertContent(contents, insertIndex, contentLength);
6308
+ }
6309
+ }
6036
6310
  static replace(document, contents, model) {
6037
6311
  this.delete(document, model.delete.startIndex, model.delete.count);
6038
6312
  if (model.insertText) {
@@ -9162,7 +9436,7 @@ class EditSession {
9162
9436
  }
9163
9437
  removeByDocumentIndexes(startIndex, endIndex) {
9164
9438
  const startParagraphPosition = ContentHelper.documentIndexToParagraphIndex(this.displayData.paragraphs, startIndex);
9165
- const endParagraphPosition = ContentHelper.documentIndexToParagraphIndex(this.displayData.paragraphs, endIndex);
9439
+ const endParagraphPosition = ContentHelper.documentIndexToParagraphIndex(this.displayData.paragraphs, endIndex + 1);
9166
9440
  this.remove(new Range(startParagraphPosition, endParagraphPosition));
9167
9441
  }
9168
9442
  insertTextByDocumentIndex(index, text, style) {
@@ -9313,7 +9587,7 @@ class EditSession {
9313
9587
  this.applyToolbarStyles();
9314
9588
  }
9315
9589
  replace(model) {
9316
- this.removeByDocumentIndexes(model.delete.startIndex, model.delete.startIndex + model.delete.count);
9590
+ this.removeByDocumentIndexes(model.delete.startIndex, model.delete.startIndex + model.delete.count - 1);
9317
9591
  let endPoint;
9318
9592
  if (model.insertText) {
9319
9593
  endPoint = this.insertTextByDocumentIndex(model.insertText.insertIndex, model.insertText.text);
@@ -9348,7 +9622,7 @@ class EditSession {
9348
9622
  this.removeNumberings(paragraphIndex, paragraphIndex);
9349
9623
  }
9350
9624
  this.applyParagraphStyle(paragraphIndex, paragraphIndex, model.paragraphStyle);
9351
- this.removeByDocumentIndexes(model.startIndex, model.startIndex + model.count);
9625
+ this.removeByDocumentIndexes(model.startIndex, model.startIndex + model.count - 1);
9352
9626
  }
9353
9627
  restoreWithParagraph(model) {
9354
9628
  this.restore(model.restore);
@@ -9453,6 +9727,23 @@ class EditSession {
9453
9727
  OperationsHelper.applyTableCellsStyles(this.model, model);
9454
9728
  table.instance.updateTable();
9455
9729
  }
9730
+ insertContents(insertIndex, contents) {
9731
+ OperationsHelper.insertContents(this.model, insertIndex, contents);
9732
+ const endIndex = insertIndex + contents.content.length - 1;
9733
+ this.insertComponents(this.model.tables, this.customComponents.tables, NoderTableComponent, insertIndex, endIndex);
9734
+ this.insertComponents(this.model.images, this.customComponents.images, NoderImageComponent, insertIndex, endIndex);
9735
+ this.insertComponents(this.model.tabs, this.customComponents.tabs, NoderTabComponent, insertIndex, endIndex);
9736
+ this.insertElementComponents(this.model.elements, insertIndex, endIndex);
9737
+ const startPosition = ContentHelper.documentIndexToParagraphIndex(this.displayData.paragraphs, insertIndex);
9738
+ const endPosition = this.displayData.insertText(startPosition, contents.content);
9739
+ this.displayData.updateNextLineIndexes(startPosition.row, endPosition.row);
9740
+ this.selection.placeSelection(endPosition, endPosition);
9741
+ this.applyToolbarStyles();
9742
+ }
9743
+ replaceByContents(startIndex, count, contents) {
9744
+ this.removeByDocumentIndexes(startIndex, startIndex + count - 1);
9745
+ this.insertContents(startIndex, contents);
9746
+ }
9456
9747
  removeMoveRange(moveModel) {
9457
9748
  const endIndex = moveModel.sourceStartIndex + moveModel.sourceCount - 1;
9458
9749
  const startPosition = this.displayData.indexToPosition(moveModel.sourceStartIndex, 0);
@@ -9472,10 +9763,10 @@ class EditSession {
9472
9763
  restoreMoveRange(restoreModel, moveModel, _sourceSessionId) {
9473
9764
  const moveIndex = OperationsHelper.restoreMoveRange(this.model, moveModel, restoreModel);
9474
9765
  const endIndex = moveIndex + moveModel.sourceCount;
9475
- this.restoreComponents(this.model.tables, this.customComponents.tables, NoderTableComponent, moveIndex, endIndex);
9476
- this.restoreComponents(this.model.images, this.customComponents.images, NoderImageComponent, moveIndex, endIndex);
9477
- this.restoreComponents(this.model.tabs, this.customComponents.tabs, NoderTabComponent, moveIndex, endIndex);
9478
- this.restoreElementComponents(this.model.elements, moveIndex, endIndex);
9766
+ this.insertComponents(this.model.tables, this.customComponents.tables, NoderTableComponent, moveIndex, endIndex);
9767
+ this.insertComponents(this.model.images, this.customComponents.images, NoderImageComponent, moveIndex, endIndex);
9768
+ this.insertComponents(this.model.tabs, this.customComponents.tabs, NoderTabComponent, moveIndex, endIndex);
9769
+ this.insertElementComponents(this.model.elements, moveIndex, endIndex);
9479
9770
  const startPosition = ContentHelper.documentIndexToParagraphIndex(this.displayData.paragraphs, moveIndex);
9480
9771
  const endPosition = this.displayData.insertText(startPosition, restoreModel.text);
9481
9772
  this.displayData.updateNextLineIndexes(startPosition.row, endPosition.row);
@@ -9491,6 +9782,12 @@ class EditSession {
9491
9782
  const endIndex = this.displayData.positionToIndex(range.end);
9492
9783
  return positionIndex >= startIndex && positionIndex < endIndex;
9493
9784
  }
9785
+ getContentsSlice(start, end) {
9786
+ const startIndex = ContentHelper.paragraphPositionToDocumentIndex(this.displayData.paragraphs, start);
9787
+ const endIndex = ContentHelper.paragraphPositionToDocumentIndex(this.displayData.paragraphs, end) - 1;
9788
+ const count = endIndex - startIndex + 1;
9789
+ return ContentsOperationsHelper.GetRelativeContentSlice(this.model, startIndex, count);
9790
+ }
9494
9791
  createRestoreFromSlice(start, end) {
9495
9792
  const startIndex = ContentHelper.paragraphToDocumentIndex(this.displayData.paragraphs, start.row, start.column);
9496
9793
  const endIndex = ContentHelper.paragraphToDocumentIndex(this.displayData.paragraphs, end.row, end.column) - 1;
@@ -9557,7 +9854,7 @@ class EditSession {
9557
9854
  return [format.textStyle];
9558
9855
  }
9559
9856
  replaceByRestore(model) {
9560
- this.removeByDocumentIndexes(model.delete.startIndex, model.delete.startIndex + model.delete.count);
9857
+ this.removeByDocumentIndexes(model.delete.startIndex, model.delete.startIndex + model.delete.count - 1);
9561
9858
  this.restore(model.restore);
9562
9859
  }
9563
9860
  restore(model) {
@@ -9565,15 +9862,15 @@ class EditSession {
9565
9862
  OperationsHelper.restore(this.model, model);
9566
9863
  const endPoint = this.displayData.insertText(paragraphPosition, model.text);
9567
9864
  const restoreEndIndex = model.insertIndex + model.text.length;
9568
- this.restoreComponents(this.model.tables, this.customComponents.tables, NoderTableComponent, model.insertIndex, restoreEndIndex);
9569
- this.restoreComponents(this.model.images, this.customComponents.images, NoderImageComponent, model.insertIndex, restoreEndIndex);
9570
- this.restoreComponents(this.model.tabs, this.customComponents.tabs, NoderTabComponent, model.insertIndex, restoreEndIndex);
9571
- this.restoreElementComponents(this.model.elements, model.insertIndex, restoreEndIndex);
9865
+ this.insertComponents(this.model.tables, this.customComponents.tables, NoderTableComponent, model.insertIndex, restoreEndIndex);
9866
+ this.insertComponents(this.model.images, this.customComponents.images, NoderImageComponent, model.insertIndex, restoreEndIndex);
9867
+ this.insertComponents(this.model.tabs, this.customComponents.tabs, NoderTabComponent, model.insertIndex, restoreEndIndex);
9868
+ this.insertElementComponents(this.model.elements, model.insertIndex, restoreEndIndex);
9572
9869
  this.displayData.updateNextLineIndexes(paragraphPosition.row, endPoint.row);
9573
9870
  this.selection.placeCursor(endPoint);
9574
9871
  this.applyToolbarStyles();
9575
9872
  }
9576
- restoreComponents(models, components, componentType, restoreIndex, restoreEndIndex) {
9873
+ insertComponents(models, components, componentType, restoreIndex, restoreEndIndex) {
9577
9874
  for (const model of models) {
9578
9875
  if (model.insertIndex < restoreIndex) {
9579
9876
  continue;
@@ -9584,7 +9881,7 @@ class EditSession {
9584
9881
  this.addComponent(components, model, componentType);
9585
9882
  }
9586
9883
  }
9587
- restoreElementComponents(elements, restoreIndex, restoreEndIndex) {
9884
+ insertElementComponents(elements, restoreIndex, restoreEndIndex) {
9588
9885
  for (const model of elements) {
9589
9886
  if (model.insertIndex < restoreIndex) {
9590
9887
  continue;
@@ -13794,6 +14091,17 @@ class RemoveWithParagraphModel {
13794
14091
  }
13795
14092
  }
13796
14093
 
14094
+ class ReplaceByContentsModel {
14095
+ constructor(fields) {
14096
+ if (fields) {
14097
+ if (fields.contents) {
14098
+ fields.contents = new ContentsModel(fields.contents);
14099
+ }
14100
+ Object.assign(this, fields);
14101
+ }
14102
+ }
14103
+ }
14104
+
13797
14105
  class ReplaceModel {
13798
14106
  constructor(fields) {
13799
14107
  if (fields) {
@@ -13893,6 +14201,9 @@ class CommandModel {
13893
14201
  if (fields.insertBreak) {
13894
14202
  fields.insertBreak = new InsertBreakModel(fields.insertBreak);
13895
14203
  }
14204
+ if (fields.insertContents) {
14205
+ fields.insertContents = new InsertContentsModel(fields.insertContents);
14206
+ }
13896
14207
  if (fields.insertElement) {
13897
14208
  fields.insertElement = new InsertElementModel(fields.insertElement);
13898
14209
  }
@@ -13950,6 +14261,9 @@ class CommandModel {
13950
14261
  if (fields.replace) {
13951
14262
  fields.replace = new ReplaceModel(fields.replace);
13952
14263
  }
14264
+ if (fields.replaceByContents) {
14265
+ fields.replaceByContents = new ReplaceByContentsModel(fields.replaceByContents);
14266
+ }
13953
14267
  if (fields.replaceByRestore) {
13954
14268
  fields.replaceByRestore = new ReplaceByRestoreModel(fields.replaceByRestore);
13955
14269
  }
@@ -14078,6 +14392,12 @@ class SaveCommandsHelper {
14078
14392
  static getReplaceByRestoreCommand(replaceByRestore, targets) {
14079
14393
  return new CommandModel({ commandType: CommandType.ReplaceByRestore, replaceByRestore, targets });
14080
14394
  }
14395
+ static getInsertContentsCommand(model, targets) {
14396
+ return new CommandModel({ commandType: CommandType.InsertContents, insertContents: model, targets });
14397
+ }
14398
+ static getReplaceByContentsModel(model, targets) {
14399
+ return new CommandModel({ commandType: CommandType.ReplaceByContents, replaceByContents: model, targets });
14400
+ }
14081
14401
  static getMoveRangeCommand(model, targets) {
14082
14402
  return new CommandModel({ commandType: CommandType.MoveRange, moveRange: model, targets });
14083
14403
  }
@@ -14846,10 +15166,6 @@ class TextInput {
14846
15166
  parentElement.insertBefore(this.input, parentElement.firstChild);
14847
15167
  this.isFocused = document.activeElement === this.input;
14848
15168
  }
14849
- getClipboardData(event) {
14850
- const mime = 'text/plain';
14851
- return event.clipboardData.getData(mime);
14852
- }
14853
15169
  getInsertText() {
14854
15170
  const data = this.input.value;
14855
15171
  const selectionStart = this.input.selectionStart;
@@ -14971,12 +15287,13 @@ class Editor {
14971
15287
  this.inputHandler = new InputHandler(this.textInput.input, this);
14972
15288
  this.documentHandler = new DocumentHandler(this);
14973
15289
  this.dragAndDrop = new DragAndDrop(this.container.nativeElement);
15290
+ this.clipboardHandler = new ClipboardHandler(this.clipboard);
14974
15291
  this.initResizeListener();
14975
15292
  this.focus();
14976
15293
  this.session.applyToolbarStyles();
14977
15294
  this.onSetCommentsVisibility(!!this.model.comments.length);
14978
15295
  this.search = new Search(editorService);
14979
- this.subscriptions.push(this.changedEdgeSizeSubscription(), this.changedEdgeSubscription(), this.changedTableSizeSubscription(), this.clipboardDataSubscription(), this.copySelectedSubscription(), this.createCustomComponentSubscription(), this.replaceByCustomComponentSubscription(), this.cutSelectedSubscription(), this.disableSelectionSubscription(), this.endMousePressSubscription(), this.imageLoadedSubscription(), this.insertBreakSubscription(), this.insertImageSubscription(), this.insertLinkSubscription(), this.insertTableColumnsSubscription(), this.insertTableRowsSubscription(), this.insertTableSubscription(), this.updateTableBorderStyleSubscription(), this.updateTableBorderWidthSubscription(), this.updateTableBordersSubscription(), this.selectSpacingSubscription(), this.selectBeforeSubscription(), this.selectAfterSubscription(), this.insertTextSubscription(), this.pasteFromClipboardSubscription(), this.printSubscription(), this.redoSubscription(), this.removeLeftSubscription(), this.removeNumberingsSubscription(), this.removeRightSubscription(), this.removeSelectedSubscription(), this.removeTableColumnsSubscription(), this.removeTableRowsSubscription(), this.removeTableSubscription(), this.rerenderSubscription(), this.resizeTableColumnsSubscription(), ...this.searchOptionSubscriptions(), ...this.replaceSubscription(), this.grammarReplaceSubscription(), this.ignoreGrammarErrorSubscription(), this.toggleGrammarChecksSubscription(), this.selectAllSubscription(), this.setImageStyleSubscription(), this.setNumberingTemplateTypeSubscription(), this.setParagraphStylesSubscription(), this.setTextStylesSubscription(), this.undoSubscription(), this.updateEdgeSubscription(), this.viewOnlyModeSubscription(), this.applyPageFormatSubscription(), this.applyRightMarginPageFormatSubscription(), this.applyLeftMarginPageFormatSubscription(), this.insertPageFormatSubscription(), this.applyDocumentPageFormatSubscription(), this.dragMoveSubscription(), this.dragDropSubscription(), this.applyFirstLinePositionSubscription(), this.applyRightIndentParagraphSubscription(), this.applyLeftIndentParagraphSubscription(), this.applyTabSettingsSubscription(), this.commandCreatedForEdges(), ...this.commentCreationSubscriptions(), this.removeCommentSubscription(), this.rerenderCommentsSubscription(), this.selectCommentSubscription(), this.setComentsVisibilitySubscription(), this.getCommentTextSubscription(), this.replaceCommentTextSubscription(), this.startNewListSubscription(), this.continueNumberingSubscription(), this.setNumberingValueSubscription());
15296
+ this.subscriptions.push(this.changedEdgeSizeSubscription(), this.changedEdgeSubscription(), this.changedTableSizeSubscription(), this.copySelectedSubscription(), this.createCustomComponentSubscription(), this.replaceByCustomComponentSubscription(), this.cutSelectedSubscription(), this.disableSelectionSubscription(), this.endMousePressSubscription(), this.imageLoadedSubscription(), this.insertBreakSubscription(), this.insertImageSubscription(), this.insertLinkSubscription(), this.insertTableColumnsSubscription(), this.insertTableRowsSubscription(), this.insertTableSubscription(), this.updateTableBorderStyleSubscription(), this.updateTableBorderWidthSubscription(), this.updateTableBordersSubscription(), this.selectSpacingSubscription(), this.selectBeforeSubscription(), this.selectAfterSubscription(), this.insertTextSubscription(), this.pasteFromClipboardSubscription(), this.printSubscription(), this.redoSubscription(), this.removeLeftSubscription(), this.removeNumberingsSubscription(), this.removeRightSubscription(), this.removeSelectedSubscription(), this.removeTableColumnsSubscription(), this.removeTableRowsSubscription(), this.removeTableSubscription(), this.rerenderSubscription(), this.resizeTableColumnsSubscription(), ...this.searchOptionSubscriptions(), ...this.replaceSubscription(), this.grammarReplaceSubscription(), this.ignoreGrammarErrorSubscription(), this.toggleGrammarChecksSubscription(), this.selectAllSubscription(), this.setImageStyleSubscription(), this.setNumberingTemplateTypeSubscription(), this.setParagraphStylesSubscription(), this.setTextStylesSubscription(), this.undoSubscription(), this.updateEdgeSubscription(), this.viewOnlyModeSubscription(), this.applyPageFormatSubscription(), this.applyRightMarginPageFormatSubscription(), this.applyLeftMarginPageFormatSubscription(), this.insertPageFormatSubscription(), this.applyDocumentPageFormatSubscription(), this.dragMoveSubscription(), this.dragDropSubscription(), this.applyFirstLinePositionSubscription(), this.applyRightIndentParagraphSubscription(), this.applyLeftIndentParagraphSubscription(), this.applyTabSettingsSubscription(), this.commandCreatedForEdges(), ...this.commentCreationSubscriptions(), this.removeCommentSubscription(), this.rerenderCommentsSubscription(), this.selectCommentSubscription(), this.setComentsVisibilitySubscription(), this.getCommentTextSubscription(), this.replaceCommentTextSubscription(), this.startNewListSubscription(), this.continueNumberingSubscription(), this.setNumberingValueSubscription(), this.insertContentsSubscription());
14980
15297
  }
14981
15298
  destroy() {
14982
15299
  this.subscriptions.forEach(s => s?.unsubscribe());
@@ -15036,9 +15353,6 @@ class Editor {
15036
15353
  const y = rect.top + cursor.pageY + cursor.height;
15037
15354
  this.overlayService.open(component, { textKey }, x, y);
15038
15355
  }
15039
- cut() {
15040
- this.removeSelected();
15041
- }
15042
15356
  insert(text) {
15043
15357
  const sanitizedText = text.replace(this.emojiRegex, ' ');
15044
15358
  if (this.selection.isEmpty) {
@@ -15070,6 +15384,11 @@ class Editor {
15070
15384
  this.onSelectionChange();
15071
15385
  this.onContentChange();
15072
15386
  }
15387
+ insertSlice(sliceData) {
15388
+ const slice = sliceData.data;
15389
+ const revisionId = sliceData.source.revisionId;
15390
+ this.editorService.requestContentsInsertion(slice, revisionId);
15391
+ }
15073
15392
  removeLeft() {
15074
15393
  if (this.selection.isEmpty) {
15075
15394
  this.selection.selectLeft(this.session);
@@ -15512,7 +15831,7 @@ class Editor {
15512
15831
  command = SaveCommandsHelper.getInsertTextCommand(text, insertIndex, this.targets);
15513
15832
  }
15514
15833
  else if (operation instanceof DeleteModel) {
15515
- this.session.removeByDocumentIndexes(operation.startIndex, operation.startIndex + operation.count);
15834
+ this.session.removeByDocumentIndexes(operation.startIndex, operation.startIndex + operation.count - 1);
15516
15835
  command = SaveCommandsHelper.getDeleteCommand(operation.startIndex, operation.count, this.targets);
15517
15836
  }
15518
15837
  else if (operation instanceof InsertStyledTextModel) {
@@ -15707,6 +16026,16 @@ class Editor {
15707
16026
  this.session.applyNewNumberingForParagraphs(operation.levels, operation.insertIndexes);
15708
16027
  command = SaveCommandsHelper.getApplyNewNumberingForParagraphsCommand(operation.insertIndexes, operation.levels, this.targets);
15709
16028
  }
16029
+ else if (operation instanceof InsertContentsModel) {
16030
+ const deepCopy = structuredClone(operation.contents);
16031
+ this.session.insertContents(operation.insertIndex, deepCopy);
16032
+ command = SaveCommandsHelper.getInsertContentsCommand(operation, this.targets);
16033
+ }
16034
+ else if (operation instanceof ReplaceByContentsModel) {
16035
+ const deepCopy = structuredClone(operation.contents);
16036
+ this.session.replaceByContents(operation.startIndex, operation.count, deepCopy);
16037
+ command = SaveCommandsHelper.getReplaceByContentsModel(operation, this.targets);
16038
+ }
15710
16039
  else {
15711
16040
  throw new Error('Undo/redo is not implemented for the Operation');
15712
16041
  }
@@ -15837,6 +16166,22 @@ class Editor {
15837
16166
  this.history.pushMoveRange(undoModel, redoModel, sourceRange);
15838
16167
  this.commandsService.createCommand(SaveCommandsHelper.getMoveRangeCommand(redoModel, []));
15839
16168
  }
16169
+ saveInsertContentsToHistory(redoModel) {
16170
+ const startIndex = redoModel.insertIndex;
16171
+ const undoModel = new DeleteModel({ startIndex, count: redoModel.contents.content.length });
16172
+ this.history.pushInsertContents(undoModel, redoModel);
16173
+ this.commandsService.createCommand(SaveCommandsHelper.getInsertContentsCommand(redoModel, this.targets));
16174
+ }
16175
+ saveReplaceByContentsToHistory(redoModel) {
16176
+ const undoSlice = ContentsOperationsHelper.GetRelativeContentSlice(this.session.model, redoModel.startIndex, redoModel.count);
16177
+ const undoModel = new ReplaceByContentsModel({
16178
+ startIndex: redoModel.startIndex,
16179
+ contents: undoSlice,
16180
+ count: redoModel.contents.content.length
16181
+ });
16182
+ this.history.pushReplaceByContents(undoModel, redoModel);
16183
+ this.commandsService.createCommand(SaveCommandsHelper.getReplaceByContentsModel(redoModel, this.targets));
16184
+ }
15840
16185
  saveReplaceToHistory(range, model) {
15841
16186
  const restoreModel = this.session.createRestoreFromSlice(range.start, range.end);
15842
16187
  this.history.pushReplace(restoreModel, model);
@@ -15980,29 +16325,42 @@ class Editor {
15980
16325
  this.showInsertOverlay(text);
15981
16326
  }
15982
16327
  onCut(event) {
15983
- event.preventDefault();
15984
- const data = this.getSelectedText();
15985
- if (!data) {
16328
+ const text = this.getSelectedText();
16329
+ const slice = this.getSelectedSlice();
16330
+ if (!text && !slice) {
15986
16331
  return;
15987
16332
  }
15988
- this.editorService.setClipboardData(data);
15989
- this.clipboard.copy(data);
15990
- this.cut();
16333
+ this.clipboardHandler.copyEvent(event, text, slice, this.editorService.revisionId);
16334
+ this.removeSelected();
15991
16335
  this.scrollCursorIntoMainView();
16336
+ this.editorService.setClipboardData(text);
15992
16337
  }
15993
16338
  onCopy(event) {
15994
- event.preventDefault();
15995
- const data = this.getSelectedText();
15996
- if (!data) {
16339
+ const text = this.getSelectedText();
16340
+ const slice = this.getSelectedSlice();
16341
+ if (!text && !slice) {
15997
16342
  return;
15998
16343
  }
15999
- this.editorService.setClipboardData(data);
16000
- this.clipboard.copy(data);
16344
+ this.clipboardHandler.copyEvent(event, text, slice, this.editorService.revisionId);
16345
+ this.editorService.setClipboardData(text);
16001
16346
  }
16002
16347
  onPaste(event) {
16003
- event.preventDefault();
16004
- const data = this.textInput.getClipboardData(event);
16005
- this.pasteData(data);
16348
+ const { text, sliceData } = this.clipboardHandler.readEvent(event);
16349
+ if (sliceData) {
16350
+ this.pasteData(text, sliceData);
16351
+ return;
16352
+ }
16353
+ this.clipboardHandler // If slice not found in event should check navigation clipboard for data.
16354
+ .readAsync()
16355
+ .then(asyncData => {
16356
+ if (text === asyncData.text && asyncData.sliceData) {
16357
+ this.pasteData(asyncData.text, asyncData.sliceData);
16358
+ }
16359
+ else if (text) {
16360
+ this.pasteData(text, null);
16361
+ }
16362
+ })
16363
+ .catch(() => { });
16006
16364
  }
16007
16365
  onCreateComment(commentType) {
16008
16366
  const { startIndex, endIndex } = ContentHelper.getSelectedPartDocumentIndexes(this.session.displayData.paragraphs, this.selection.range);
@@ -16310,6 +16668,19 @@ class Editor {
16310
16668
  this.onSelectionChange();
16311
16669
  this.onContentChange();
16312
16670
  }
16671
+ insertContent(insertIndex, contents) {
16672
+ const insertContents = new InsertContentsModel({ insertIndex, contents });
16673
+ this.saveInsertContentsToHistory(insertContents);
16674
+ this.session.insertContents(insertIndex, structuredClone(contents));
16675
+ this.onSelectionChange();
16676
+ }
16677
+ replaceByContents(startIndex, endIndex, contents) {
16678
+ const count = endIndex - startIndex + 1;
16679
+ const replaceByContents = new ReplaceByContentsModel({ startIndex, count, contents });
16680
+ this.saveReplaceByContentsToHistory(replaceByContents);
16681
+ this.session.replaceByContents(startIndex, count, structuredClone(contents));
16682
+ this.onSelectionChange();
16683
+ }
16313
16684
  moveRange(model) {
16314
16685
  this.regulatorService.setTargetedSessionAsCurrent(model.targetTargets);
16315
16686
  const sourceSession = this.regulatorService.getTargetedSession(model.sourceTargets);
@@ -16393,6 +16764,13 @@ class Editor {
16393
16764
  });
16394
16765
  return textInterval;
16395
16766
  }
16767
+ getSelectedSlice() {
16768
+ const selectionRange = this.selection.selectedRange;
16769
+ if (selectionRange.isEmpty) {
16770
+ return null;
16771
+ }
16772
+ return this.session.getContentsSlice(selectionRange.start, selectionRange.end);
16773
+ }
16396
16774
  initMainSession() {
16397
16775
  const pageWidth = this.customPageWidth ?? Math.max(...this.model.pageFormats.map(x => x.pageWidth));
16398
16776
  this.container.nativeElement.style.maxWidth = `${pageWidth}px`;
@@ -16877,49 +17255,59 @@ class Editor {
16877
17255
  }
16878
17256
  cutSelectedSubscription() {
16879
17257
  return this.editorService.cutSelected$.subscribe(() => {
16880
- this.onCut(new ClipboardEvent('cut'));
17258
+ const text = this.getSelectedText();
17259
+ const slice = this.getSelectedSlice();
17260
+ if (!text && !slice) {
17261
+ return;
17262
+ }
17263
+ this.clipboardHandler.copyAsync(text, slice, this.editorService.revisionId).catch(() => { });
17264
+ this.removeSelected();
17265
+ this.scrollCursorIntoMainView();
17266
+ this.editorService.setClipboardData(text);
16881
17267
  });
16882
17268
  }
16883
17269
  copySelectedSubscription() {
16884
17270
  return this.editorService.copySelected$.subscribe(() => {
16885
- this.onCopy(new ClipboardEvent('copy'));
17271
+ const text = this.getSelectedText();
17272
+ const slice = this.getSelectedSlice();
17273
+ if (!text && !slice) {
17274
+ return;
17275
+ }
17276
+ this.clipboardHandler.copyAsync(text, slice, this.editorService.revisionId).catch(() => { });
17277
+ this.editorService.setClipboardData(text);
16886
17278
  });
16887
17279
  }
16888
17280
  pasteFromClipboardSubscription() {
16889
- return this.editorService.pasteFromClipboard$.subscribe(() => {
16890
- this.readClipboard()
16891
- .then(data => this.pasteData(data))
16892
- .catch(() => {
16893
- // continue regardless error
16894
- });
17281
+ return this.editorService.pasteFromClipboard$
17282
+ .pipe(switchMap(() => from(this.clipboardHandler.readAsync())))
17283
+ .subscribe(({ text, sliceData }) => {
17284
+ this.pasteData(text, sliceData);
16895
17285
  });
16896
17286
  }
16897
- async readClipboard() {
16898
- const read = await navigator.permissions.query({ name: 'clipboard-read' });
16899
- return new Promise(resolve => {
16900
- if (navigator.clipboard && read.state != 'denied') {
16901
- navigator.clipboard
16902
- .readText()
16903
- .then(data => {
16904
- resolve(data);
16905
- })
16906
- .catch(() => {
16907
- // continue regardless error
16908
- });
17287
+ pasteData(text, sliceData) {
17288
+ if (sliceData) {
17289
+ this.insertSlice(sliceData);
17290
+ }
17291
+ else if (text) {
17292
+ const insertText = text.replace(/\r\n/g, '\n').replace(/\t/g, ' ');
17293
+ this.insert(insertText);
17294
+ this.scrollCursorIntoMainView();
17295
+ }
17296
+ }
17297
+ insertContentsSubscription() {
17298
+ return this.editorService.insertContents$.subscribe(contents => {
17299
+ const start = this.selection.range.start;
17300
+ const startIndex = ContentHelper.paragraphToDocumentIndex(this.session.displayData.paragraphs, start.row, start.column);
17301
+ if (this.selection.isEmpty) {
17302
+ this.insertContent(startIndex, contents);
16909
17303
  }
16910
17304
  else {
16911
- resolve(this.clipboardData);
17305
+ const end = this.selection.range.end;
17306
+ const endIndex = ContentHelper.paragraphToDocumentIndex(this.session.displayData.paragraphs, end.row, end.column) - 1;
17307
+ this.replaceByContents(startIndex, endIndex, contents);
16912
17308
  }
16913
17309
  });
16914
17310
  }
16915
- pasteData(data) {
16916
- if (!data) {
16917
- return;
16918
- }
16919
- const text = data.replace(/\r\n/g, '\n').replace(/\t/g, ' ');
16920
- this.insert(text);
16921
- this.scrollCursorIntoMainView();
16922
- }
16923
17311
  selectAllSubscription() {
16924
17312
  return this.editorService.selectAll$.subscribe(() => {
16925
17313
  this.selection.selectAll(this.session.model);
@@ -16931,11 +17319,6 @@ class Editor {
16931
17319
  this.removeSelected();
16932
17320
  });
16933
17321
  }
16934
- clipboardDataSubscription() {
16935
- return this.editorService.clipboardData$.subscribe(data => {
16936
- this.clipboardData = data;
16937
- });
16938
- }
16939
17322
  commandCreatedForEdges() {
16940
17323
  return this.commandsService.createCommand$
16941
17324
  .pipe(filter(x => !!x.targets.find(y => !!y.edgeData)))