@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.
- package/fesm2022/talrace-ngx-noder.mjs +955 -572
- package/fesm2022/talrace-ngx-noder.mjs.map +1 -1
- package/lib/editor/execution/edit.session.d.ts +6 -2
- package/lib/editor/execution/editor.d.ts +13 -4
- package/lib/editor/gadgets/clipboard-handler/clipboard-handler.d.ts +23 -0
- package/lib/editor/gadgets/clipboard-handler/clipboard-slice.interface.d.ts +9 -0
- package/lib/editor/gadgets/history/operation-history.d.ts +5 -0
- package/lib/editor/gadgets/history/operation.type.d.ts +3 -1
- package/lib/editor/interaction/editor.service.d.ts +13 -0
- package/lib/editor/interaction/text-input.d.ts +0 -1
- package/lib/editor/operations/enums/command-type.enum.d.ts +3 -1
- package/lib/editor/operations/helpers/contents-operations.helper.d.ts +2 -0
- package/lib/editor/operations/helpers/format-operations.helper.d.ts +1 -0
- package/lib/editor/operations/helpers/indexed-element-operations.helper.d.ts +1 -0
- package/lib/editor/operations/helpers/link-operations.helper.d.ts +1 -0
- package/lib/editor/operations/helpers/range-element-operations.helper.d.ts +1 -0
- package/lib/editor/operations/operations-helper.helper.d.ts +2 -0
- package/lib/editor/operations/save-commands.helper.d.ts +4 -0
- package/lib/models/generated/command.model.d.ts +4 -0
- package/lib/models/generated/contents.model.d.ts +24 -0
- package/lib/models/generated/insert-contents.model.d.ts +6 -0
- package/lib/models/generated/replace-by-contents.model.d.ts +7 -0
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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
|
|
2039
|
-
|
|
2040
|
-
|
|
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
|
-
|
|
2101
|
-
|
|
2102
|
-
this.mouseUp$?.unsubscribe();
|
|
2101
|
+
static sliceContent(content, startIndex, count) {
|
|
2102
|
+
return content.slice(startIndex, startIndex + count);
|
|
2103
2103
|
}
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
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
|
-
|
|
2114
|
-
this.
|
|
2115
|
-
this.
|
|
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
|
|
2166
|
-
constructor(
|
|
2167
|
-
|
|
2168
|
-
|
|
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
|
|
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
|
|
2199
|
-
static
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
const
|
|
2204
|
-
|
|
2205
|
-
|
|
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
|
|
2210
|
-
|
|
2211
|
-
|
|
2632
|
+
class ImageDataModel {
|
|
2633
|
+
constructor(fields) {
|
|
2634
|
+
if (fields) {
|
|
2635
|
+
Object.assign(this, fields);
|
|
2636
|
+
}
|
|
2212
2637
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
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
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
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
|
|
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
|
-
|
|
3085
|
-
|
|
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
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
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
|
-
|
|
3107
|
-
|
|
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
|
-
|
|
3112
|
-
if (
|
|
3113
|
-
|
|
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
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
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
|
-
|
|
3129
|
-
|
|
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
|
-
|
|
3138
|
-
|
|
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
|
|
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.
|
|
9476
|
-
this.
|
|
9477
|
-
this.
|
|
9478
|
-
this.
|
|
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.
|
|
9569
|
-
this.
|
|
9570
|
-
this.
|
|
9571
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
15984
|
-
const
|
|
15985
|
-
if (!
|
|
16328
|
+
const text = this.getSelectedText();
|
|
16329
|
+
const slice = this.getSelectedSlice();
|
|
16330
|
+
if (!text && !slice) {
|
|
15986
16331
|
return;
|
|
15987
16332
|
}
|
|
15988
|
-
this.editorService.
|
|
15989
|
-
this.
|
|
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
|
-
|
|
15995
|
-
const
|
|
15996
|
-
if (!
|
|
16339
|
+
const text = this.getSelectedText();
|
|
16340
|
+
const slice = this.getSelectedSlice();
|
|
16341
|
+
if (!text && !slice) {
|
|
15997
16342
|
return;
|
|
15998
16343
|
}
|
|
15999
|
-
this.editorService.
|
|
16000
|
-
this.
|
|
16344
|
+
this.clipboardHandler.copyEvent(event, text, slice, this.editorService.revisionId);
|
|
16345
|
+
this.editorService.setClipboardData(text);
|
|
16001
16346
|
}
|
|
16002
16347
|
onPaste(event) {
|
|
16003
|
-
|
|
16004
|
-
|
|
16005
|
-
|
|
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.
|
|
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.
|
|
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
|
|
16890
|
-
this.
|
|
16891
|
-
|
|
16892
|
-
|
|
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
|
-
|
|
16898
|
-
|
|
16899
|
-
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
16904
|
-
|
|
16905
|
-
|
|
16906
|
-
|
|
16907
|
-
|
|
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
|
-
|
|
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)))
|