devexpress-richedit 24.2.1-alpha-24260-0102 → 24.2.2-beta
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/bin/gulpfile.js +1 -1
- package/bin/index-custom.js +1 -1
- package/bin/localization-builder.js +1 -1
- package/bin/nspell-index.js +1 -1
- package/bin/nspell.webpack.config.js +1 -1
- package/bin/webpack-externals.js +1 -1
- package/bin/webpack.config.js +1 -1
- package/dist/dx.richedit.d.ts +12 -1
- package/dist/dx.richedit.js +528 -226
- package/dist/dx.richedit.min.js +2 -2
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/client/bars/rich-edit-ribbon/ribbon-items-data.js +2 -1
- package/lib/client/client-rich-edit.js +6 -6
- package/lib/client/commands/commands.js +3 -0
- package/lib/client/commands/new-document-command.js +2 -1
- package/lib/client/default-localization.js +2 -0
- package/lib/client/dialogs/hyperlink-dialog.js +13 -6
- package/lib/client/formats/docx/import/color/open-xml-color-import-helper.js +2 -2
- package/lib/client/formats/docx/import/importers/styles-importer.js +2 -1
- package/lib/client/i-rich-constructor-settings.d.ts +1 -2
- package/lib/client/model-api/collections/drawing-object-collection.js +1 -1
- package/lib/client/model-api/collections/hyperlink-collection.js +1 -1
- package/lib/client/public/commands/enum.d.ts +1 -0
- package/lib/client/public/commands/enum.js +1 -0
- package/lib/client/public/options.d.ts +1 -2
- package/lib/client/public/ribbon/item-ids.d.ts +1 -0
- package/lib/client/public/ribbon/item-ids.js +1 -0
- package/lib/client/public/rich-edit.js +1 -1
- package/lib/client/settings.js +2 -4
- package/lib/common/commands/client-command.d.ts +2 -1
- package/lib/common/commands/client-command.js +1 -0
- package/lib/common/commands/command-manager.js +2 -1
- package/lib/common/commands/dialogs/dialog-hyperlink-command.js +10 -4
- package/lib/common/commands/fields/create-field-command.d.ts +4 -0
- package/lib/common/commands/fields/create-field-command.js +8 -0
- package/lib/common/commands/fields/open-hyperlink-command.js +9 -6
- package/lib/common/commands/floating-objects/floating-object-drag-drop-change-position-command.js +1 -1
- package/lib/common/commands/floating-objects/insert-anchored-text-box-command.js +1 -1
- package/lib/common/formats/html/export/html-export.d.ts +7 -1
- package/lib/common/formats/html/export/html-export.js +35 -35
- package/lib/common/formats/html/import/html-importer.js +1 -1
- package/lib/common/formats/html/import/importers/list-base.js +4 -4
- package/lib/common/input-controller.d.ts +14 -1
- package/lib/common/input-controller.js +58 -20
- package/lib/common/layout/document-layout.js +1 -1
- package/lib/common/layout/main-structures/layout-boxes/layout-space-box.js +1 -1
- package/lib/common/model/color/color-model-info.d.ts +1 -1
- package/lib/common/model/color/color-model-info.js +2 -1
- package/lib/common/model/fields/field.d.ts +4 -1
- package/lib/common/model/fields/field.js +18 -2
- package/lib/common/model/fields/names.d.ts +2 -1
- package/lib/common/model/fields/names.js +1 -0
- package/lib/common/model/fields/parsers/field-code-parser-client-updating-base.js +1 -1
- package/lib/common/model/fields/parsers/field-code-parser-doc-variable.js +1 -1
- package/lib/common/model/fields/parsers/field-code-parser-hyperlink.js +32 -38
- package/lib/common/model/fields/parsers/field-code-parser-if.d.ts +39 -0
- package/lib/common/model/fields/parsers/field-code-parser-if.js +138 -0
- package/lib/common/model/fields/parsers/field-code-parser-merge-field.js +1 -1
- package/lib/common/model/fields/parsers/field-code-parser.d.ts +3 -2
- package/lib/common/model/fields/parsers/field-code-parser.js +6 -12
- package/lib/common/model/fields/tree-creator.js +2 -0
- package/lib/common/model/history/items/floating-objects/insert-anchored-picture-history-item.js +1 -0
- package/lib/common/model/history/items/switch-text-box-sub-documents-state-history-item.js +0 -1
- package/lib/common/model/manipulators/document/sub-document-inserter.d.ts +1 -0
- package/lib/common/model/manipulators/document/sub-document-inserter.js +4 -0
- package/lib/common/model/manipulators/range/remove-interval-operation.d.ts +2 -0
- package/lib/common/model/manipulators/range/remove-interval-operation.js +10 -2
- package/lib/common/model/manipulators/range-permission-manipulator.d.ts +4 -0
- package/lib/common/model/manipulators/range-permission-manipulator.js +35 -0
- package/lib/common/model/manipulators/text-box-manipulator.d.ts +1 -1
- package/lib/common/model/manipulators/text-box-manipulator.js +2 -1
- package/lib/common/model/manipulators/text-manipulator/text-manipulator.js +1 -1
- package/lib/common/model/options/fields.d.ts +1 -2
- package/lib/common/model/options/fields.js +2 -5
- package/lib/common/model/styles-manager.js +1 -0
- package/lib/common/selection/selection.js +2 -1
- package/lib/common/ui/ruler/controls/indent/first-line.js +5 -5
- package/lib/common/ui/ruler/controls/indent/left.js +6 -6
- package/lib/common/ui/ruler/controls/indent/right.js +4 -4
- package/lib/common/ui/ruler/controls/margin/left.js +1 -1
- package/lib/common/ui/ruler/controls/margin/right.js +1 -1
- package/lib/common/ui/ruler/controls/ruler.js +2 -2
- package/lib/common/ui/ruler/controls/tab/tab-type.js +3 -3
- package/lib/common/ui/ruler/controls/tab/tab.js +7 -7
- package/lib/common/ui/ruler/controls/tab/utils.d.ts +2 -2
- package/lib/common/ui/ruler/controls/tab/utils.js +5 -5
- package/lib/common/ui/ruler/controls/table.js +1 -1
- package/lib/common/ui/ruler/controls/vertical-line.d.ts +1 -2
- package/lib/common/ui/ruler/controls/vertical-line.js +2 -2
- package/lib/common/ui/ruler/controls/wrapper.js +1 -1
- package/lib/common/ui/ruler/manager.js +1 -1
- package/lib/common/ui/ruler/model-data.d.ts +8 -2
- package/lib/common/ui/ruler/model-data.js +6 -0
- package/lib/common/ui/ruler/ruler.js +2 -1
- package/lib/common/utils/utils.d.ts +10 -5
- package/lib/common/utils/utils.js +46 -18
- package/package.json +3 -3
@@ -4,6 +4,11 @@ import { IEventManager } from './interfaces/i-event-manager';
|
|
4
4
|
import { IRichEditControl } from './interfaces/i-rich-edit-core';
|
5
5
|
import { HtmlBuilder } from './formats/html/export/html-builder';
|
6
6
|
export declare const INPUT_CLASS_NAME = "dxreInputTarget";
|
7
|
+
declare enum IMEState {
|
8
|
+
None = 0,
|
9
|
+
Start = 1,
|
10
|
+
Process = 2
|
11
|
+
}
|
7
12
|
export declare abstract class InputEditorBase<TInpElement extends HTMLElement> {
|
8
13
|
private newLineRegexp;
|
9
14
|
eventManager: IEventManager;
|
@@ -14,7 +19,7 @@ export declare abstract class InputEditorBase<TInpElement extends HTMLElement> {
|
|
14
19
|
needProcessShortcut: boolean;
|
15
20
|
initializedIfNotReadOnly: boolean;
|
16
21
|
prevKeyCode: number;
|
17
|
-
|
22
|
+
IMEState: IMEState;
|
18
23
|
private inputWithAlt;
|
19
24
|
private processTextOnKeyPress;
|
20
25
|
protected evtHandlersHolder: DomEventHandlersHolder;
|
@@ -68,11 +73,15 @@ export declare class DivInputEditor extends InputEditorBase<HTMLElement> {
|
|
68
73
|
private cursorWasSetOnLastPosition;
|
69
74
|
private clearInputTimerId;
|
70
75
|
private lastCursorPosition;
|
76
|
+
private composUpdateTimerId;
|
77
|
+
private composEndTimerId;
|
78
|
+
private onTextInputTimerId;
|
71
79
|
constructor(control: IRichEditControl, eventManager: IEventManager, parent: HTMLElement);
|
72
80
|
dispose(): void;
|
73
81
|
initializeIfNotReadOnlyCore(): void;
|
74
82
|
setPosition(left: number, top: number): void;
|
75
83
|
createInputElement(): HTMLElement;
|
84
|
+
initEvents(): void;
|
76
85
|
onKeyDown(evt: KeyboardEvent): void;
|
77
86
|
onKeyUp(evt: KeyboardEvent): void;
|
78
87
|
onInput(evt: InputEvent): void;
|
@@ -93,6 +102,9 @@ export declare class DivInputEditor extends InputEditorBase<HTMLElement> {
|
|
93
102
|
getEditableDocumentContent(): string | NodeListOf<ChildNode>;
|
94
103
|
getEditableDocumentCursorPosition(): number;
|
95
104
|
selectEditableDocumentContent(): void;
|
105
|
+
onCompositionStart(_evt: KeyboardEvent): void;
|
106
|
+
onCompositionUpdate(_evt: KeyboardEvent): void;
|
107
|
+
onCompositionEnd(_evt: KeyboardEvent): void;
|
96
108
|
}
|
97
109
|
export declare class IFrameInputEditor extends InputEditorBase<HTMLIFrameElement> {
|
98
110
|
editableDocument: Document;
|
@@ -145,3 +157,4 @@ export declare class InputController {
|
|
145
157
|
getEditableDocumentContent(): string | NodeListOf<ChildNode>;
|
146
158
|
selectEditableDocumentContent(): void;
|
147
159
|
}
|
160
|
+
export {};
|
@@ -23,9 +23,16 @@ export const INPUT_CLASS_NAME = "dxreInputTarget";
|
|
23
23
|
const EMPTY_KEYCODE = 229;
|
24
24
|
const TAB_KEYCODE = 9;
|
25
25
|
const IDEOGRAPHIC_SPACE_CHARCODE = 12288;
|
26
|
+
var IMEState;
|
27
|
+
(function (IMEState) {
|
28
|
+
IMEState[IMEState["None"] = 0] = "None";
|
29
|
+
IMEState[IMEState["Start"] = 1] = "Start";
|
30
|
+
IMEState[IMEState["Process"] = 2] = "Process";
|
31
|
+
})(IMEState || (IMEState = {}));
|
26
32
|
export class InputEditorBase {
|
27
33
|
constructor(control, eventManager, parent) {
|
28
34
|
this.newLineRegexp = /(\r\n|\n|\r)/gm;
|
35
|
+
this.IMEState = IMEState.None;
|
29
36
|
this.processTextOnKeyPress = false;
|
30
37
|
this.evtHandlersHolder = new DomEventHandlersHolder();
|
31
38
|
this.control = control;
|
@@ -33,7 +40,6 @@ export class InputEditorBase {
|
|
33
40
|
this.canInsertTextOnInputEvent = this.canUseInputEvent();
|
34
41
|
this.createHierarchy(parent);
|
35
42
|
this.initialize();
|
36
|
-
this.isIME = false;
|
37
43
|
this.inputWithAlt = false;
|
38
44
|
}
|
39
45
|
dispose() {
|
@@ -106,7 +112,7 @@ export class InputEditorBase {
|
|
106
112
|
}
|
107
113
|
onKeyDown(evt) {
|
108
114
|
if (!this.control.clientSideEvents.raiseKeyDown(evt)) {
|
109
|
-
if (
|
115
|
+
if (this.IMEState === IMEState.None) {
|
110
116
|
evt = this.getNormalizedEvent(evt);
|
111
117
|
const keyCode = KeyUtils.getEventKeyCode(evt);
|
112
118
|
this.needProcessShortcut = !keyCode || keyCode == EMPTY_KEYCODE;
|
@@ -271,6 +277,9 @@ export class DivInputEditor extends InputEditorBase {
|
|
271
277
|
dispose() {
|
272
278
|
super.dispose();
|
273
279
|
clearTimeout(this.clearInputTimerId);
|
280
|
+
clearTimeout(this.composUpdateTimerId);
|
281
|
+
clearTimeout(this.composEndTimerId);
|
282
|
+
clearTimeout(this.onTextInputTimerId);
|
274
283
|
}
|
275
284
|
initializeIfNotReadOnlyCore() {
|
276
285
|
this.inputElement.contentEditable = "true";
|
@@ -281,14 +290,21 @@ export class DivInputEditor extends InputEditorBase {
|
|
281
290
|
}
|
282
291
|
createInputElement() {
|
283
292
|
const element = document.createElement("DIV");
|
284
|
-
|
285
|
-
element.autocapitalize = "off";
|
293
|
+
element.autocapitalize = "off";
|
286
294
|
if (Browser.MacOSMobilePlatform && (Number(Browser.PlaformMajorVersion) >= 16
|
287
295
|
|| Browser.Safari && Browser.MajorVersion >= 16)) {
|
288
296
|
element.classList.add('dxreiOS16');
|
289
297
|
}
|
290
298
|
return element;
|
291
299
|
}
|
300
|
+
initEvents() {
|
301
|
+
super.initEvents();
|
302
|
+
this.evtHandlersHolder.addListener(this.getEditableDocument(), "compositionstart", this.onCompositionStart.bind(this));
|
303
|
+
this.evtHandlersHolder.addListener(this.getEditableDocument(), "compositionupdate", (evt) => Browser.IE || Browser.Edge ?
|
304
|
+
this.onCompositionUpdate(evt) : this.composUpdateTimerId = setTimeout(() => this.onCompositionUpdate(evt), 0));
|
305
|
+
this.evtHandlersHolder.addListener(this.getEditableDocument(), "compositionend", (evt) => !Browser.Safari ?
|
306
|
+
this.onCompositionEnd(evt) : this.composEndTimerId = setTimeout(() => this.onCompositionEnd(evt), 0));
|
307
|
+
}
|
292
308
|
onKeyDown(evt) {
|
293
309
|
var _a;
|
294
310
|
this.handled = false;
|
@@ -357,21 +373,15 @@ export class DivInputEditor extends InputEditorBase {
|
|
357
373
|
this.onTextReplace(text.substr(lastWordStartIndex), text);
|
358
374
|
else
|
359
375
|
super.onTextInput(data);
|
360
|
-
if (this.previousText && text.length < this.previousText.length || !text.length) {
|
361
|
-
let deletedCharacterCount = this.previousText ? this.previousText.length - text.length : 1;
|
362
|
-
for (let i = 0; i < deletedCharacterCount; i++)
|
363
|
-
this.eventManager.onShortcut(KeyCode.Backspace);
|
364
|
-
this.previousText = text;
|
365
|
-
}
|
366
376
|
this.cursorWasSetOnLastPosition = true;
|
367
377
|
}
|
368
378
|
this.handled = true;
|
369
|
-
if (
|
379
|
+
if (text[text.length - 1] == " ")
|
370
380
|
this.clearInputElement();
|
371
381
|
}
|
372
382
|
}
|
373
383
|
tryHandleShortcutByInputString(data) {
|
374
|
-
if (data &&
|
384
|
+
if (data && this.IMEState === IMEState.None) {
|
375
385
|
let enteredChar = data.charAt(data.length - 1);
|
376
386
|
const keyCode = this.tryObtainCodeFromChar(enteredChar);
|
377
387
|
if (keyCode != EMPTY_KEYCODE) {
|
@@ -462,6 +472,31 @@ export class DivInputEditor extends InputEditorBase {
|
|
462
472
|
selection.selectAllChildren(this.inputElement);
|
463
473
|
super.selectEditableDocumentContent();
|
464
474
|
}
|
475
|
+
onCompositionStart(_evt) {
|
476
|
+
this.IMEState = IMEState.Start;
|
477
|
+
this.needProcessShortcut = false;
|
478
|
+
this.clearInputElement();
|
479
|
+
}
|
480
|
+
onCompositionUpdate(_evt) {
|
481
|
+
const text = this.getEditableDocumentText();
|
482
|
+
if (text.length && this.previousText != text) {
|
483
|
+
if (this.IMEState === IMEState.Start)
|
484
|
+
this.onText(text, text, this.previousText.length > 0);
|
485
|
+
else if (this.IMEState === IMEState.Process)
|
486
|
+
this.onTextReplace(text, text);
|
487
|
+
}
|
488
|
+
this.IMEState = IMEState.Process;
|
489
|
+
}
|
490
|
+
onCompositionEnd(_evt) {
|
491
|
+
const text = this.getEditableDocumentText();
|
492
|
+
if (this.previousText != text) {
|
493
|
+
if (text.length > 0)
|
494
|
+
this.onTextReplace(text, text);
|
495
|
+
else
|
496
|
+
this.onShortcutCore(_evt, KeyCode.Backspace);
|
497
|
+
}
|
498
|
+
this.IMEState = IMEState.None;
|
499
|
+
}
|
465
500
|
}
|
466
501
|
export class IFrameInputEditor extends InputEditorBase {
|
467
502
|
constructor(control, eventManager, parent) {
|
@@ -565,7 +600,7 @@ export class IFrameInputEditor extends InputEditorBase {
|
|
565
600
|
}
|
566
601
|
setEditableDocumentContent(content) {
|
567
602
|
super.setEditableDocumentContent(content);
|
568
|
-
this.
|
603
|
+
this.IMEState = IMEState.None;
|
569
604
|
this.editableDocument.body.innerHTML = "";
|
570
605
|
if (typeof content === "string")
|
571
606
|
this.editableDocument.body.innerHTML = content;
|
@@ -613,7 +648,7 @@ export class IFrameInputEditor extends InputEditorBase {
|
|
613
648
|
}
|
614
649
|
onBlur(evt) {
|
615
650
|
super.onBlur(evt);
|
616
|
-
this.
|
651
|
+
this.IMEState = IMEState.None;
|
617
652
|
this.endInputIME();
|
618
653
|
}
|
619
654
|
onShortcutCore(evt, shortcutCode) {
|
@@ -642,7 +677,7 @@ export class IFrameInputEditor extends InputEditorBase {
|
|
642
677
|
}
|
643
678
|
}
|
644
679
|
onCompositionStart(_evt) {
|
645
|
-
this.
|
680
|
+
this.IMEState = IMEState.Start;
|
646
681
|
this.needProcessShortcut = false;
|
647
682
|
if (!Browser.IE && !Browser.Edge)
|
648
683
|
this.clearInputElement();
|
@@ -650,10 +685,11 @@ export class IFrameInputEditor extends InputEditorBase {
|
|
650
685
|
}
|
651
686
|
onCompositionUpdate(_evt) {
|
652
687
|
const text = this.getEditableDocumentText();
|
653
|
-
if (this.
|
688
|
+
if (this.IMEState !== IMEState.None && text.length && this.previousText != text) {
|
654
689
|
this.onTextReplace(text, text);
|
655
690
|
this.updateInputIME();
|
656
691
|
}
|
692
|
+
this.IMEState = IMEState.Process;
|
657
693
|
}
|
658
694
|
onCompositionEnd(_evt) {
|
659
695
|
const text = this.getEditableDocumentText();
|
@@ -663,7 +699,7 @@ export class IFrameInputEditor extends InputEditorBase {
|
|
663
699
|
this.clearInputElement();
|
664
700
|
if (text.charCodeAt(text.length - 1) == IDEOGRAPHIC_SPACE_CHARCODE)
|
665
701
|
this.clearInputElement();
|
666
|
-
this.
|
702
|
+
this.IMEState = IMEState.None;
|
667
703
|
this.endInputIME();
|
668
704
|
}
|
669
705
|
startInputIME() {
|
@@ -732,7 +768,10 @@ export class InputController {
|
|
732
768
|
this.inputEditor = this.createInputEditor(parent, eventManager);
|
733
769
|
}
|
734
770
|
initExporter() {
|
735
|
-
this.exporter = new HtmlExporter(this.control.getExportModelOptions()
|
771
|
+
this.exporter = new HtmlExporter(this.control.getExportModelOptions(), {
|
772
|
+
sanitaizeHyperlinkURIs: true,
|
773
|
+
convertRelativeURIsToAbsolute: true
|
774
|
+
});
|
736
775
|
}
|
737
776
|
dispose() {
|
738
777
|
this.inputEditor.dispose();
|
@@ -797,9 +836,8 @@ export class InputController {
|
|
797
836
|
if (typeof html === 'string')
|
798
837
|
el.innerHTML = html;
|
799
838
|
});
|
800
|
-
if (typeof html !== "string")
|
839
|
+
if (typeof html !== "string")
|
801
840
|
builder.assignFrom(html);
|
802
|
-
}
|
803
841
|
builder.endChild('b');
|
804
842
|
builder.endChild('span');
|
805
843
|
builder.endChild('a');
|
@@ -19,7 +19,7 @@ export class AnchorObjectsPositionInfo {
|
|
19
19
|
}
|
20
20
|
add(obj, modelPosition) {
|
21
21
|
this.delete(obj.objectId);
|
22
|
-
this.cache[obj.objectId] = new ModelPositionHolder(modelPosition, this.model.
|
22
|
+
this.cache[obj.objectId] = new ModelPositionHolder(modelPosition, this.model.subDocumentsCollection.collection[obj.belongsToSubDocId].positionManager);
|
23
23
|
}
|
24
24
|
delete(id) {
|
25
25
|
const info = this.cache[id];
|
@@ -22,7 +22,7 @@ export class LayoutSpaceBox extends LayoutBox {
|
|
22
22
|
return LayoutBoxType.Space;
|
23
23
|
}
|
24
24
|
pushInfoForMeasure(info, showHiddenSymbols) {
|
25
|
-
info.push(new MeasureInfoNonText(
|
25
|
+
info.push(new MeasureInfoNonText(RichUtils.specialCharacters.Space, this.characterProperties));
|
26
26
|
if (showHiddenSymbols)
|
27
27
|
info.push(new MeasureInfoNonText(RichUtils.specialCharacters.HiddenSpace, this.characterProperties));
|
28
28
|
}
|
@@ -9,7 +9,7 @@ export declare class ColorModelInfo implements ICloneable<ColorModelInfo>, ISupp
|
|
9
9
|
static readonly auto: ColorModelInfo;
|
10
10
|
static readonly autoColor: ColorModelInfo;
|
11
11
|
static readonly noColor: ColorModelInfo;
|
12
|
-
static makeByThemeColorIndex(themeColorIndex: number, tint?: number): ColorModelInfo;
|
12
|
+
static makeByThemeColorIndex(themeColorIndex: number, tint?: number, themeValue?: ThemeColorValues): ColorModelInfo;
|
13
13
|
static makeByColor(color: number, tint?: number): ColorModelInfo;
|
14
14
|
static makeByColorIndex(colorIndex: number, tint?: number): ColorModelInfo;
|
15
15
|
static makeByColorHash(hash: string, tint?: number): ColorModelInfo;
|
@@ -9,10 +9,11 @@ import { ColorType, ThemeColorIndexConstants, ThemeColorValues } from './enums';
|
|
9
9
|
export class ColorModelInfo {
|
10
10
|
static get nullColor() { return ColorModelInfo.makeByColor(ColorHelper.AUTOMATIC_COLOR); }
|
11
11
|
;
|
12
|
-
static makeByThemeColorIndex(themeColorIndex, tint = 0) {
|
12
|
+
static makeByThemeColorIndex(themeColorIndex, tint = 0, themeValue = ThemeColorValues.None) {
|
13
13
|
const result = new ColorModelInfo();
|
14
14
|
result.themeColorIndex = themeColorIndex;
|
15
15
|
result.tint = tint;
|
16
|
+
result.themeValue = themeValue;
|
16
17
|
return result;
|
17
18
|
}
|
18
19
|
static makeByColor(color, tint = 0) {
|
@@ -29,8 +29,11 @@ export declare class HyperlinkInfo implements ICloneable<HyperlinkInfo> {
|
|
29
29
|
visited: boolean;
|
30
30
|
constructor(uri: string, anchor: string, tip: string, visited: boolean);
|
31
31
|
clone(): HyperlinkInfo;
|
32
|
-
|
32
|
+
getUriWithAnchor(): string;
|
33
33
|
static getNewCodeText(hyperlinkInfo: HyperlinkInfo): string;
|
34
|
+
isUri(): boolean;
|
35
|
+
isMail(): boolean;
|
36
|
+
isValid(): boolean;
|
34
37
|
}
|
35
38
|
export declare class SequenceInfo {
|
36
39
|
identifier: string;
|
@@ -4,6 +4,7 @@ import { ListUtils } from '@devexpress/utils/lib/utils/list';
|
|
4
4
|
import { SearchUtils } from '@devexpress/utils/lib/utils/search';
|
5
5
|
import { FieldDeletedSubDocumentChange } from '../changes/sub-document/field/deleted';
|
6
6
|
import { RunType } from '../runs/run-type';
|
7
|
+
import { UrlUtils } from '../../utils/utils';
|
7
8
|
export var FieldNameType;
|
8
9
|
(function (FieldNameType) {
|
9
10
|
FieldNameType[FieldNameType["None"] = 0] = "None";
|
@@ -33,8 +34,8 @@ export class HyperlinkInfo {
|
|
33
34
|
clone() {
|
34
35
|
return new HyperlinkInfo(this.uri, this.anchor, this.tip, this.visited);
|
35
36
|
}
|
36
|
-
|
37
|
-
return this.uri + (this.anchor
|
37
|
+
getUriWithAnchor() {
|
38
|
+
return this.uri + (this.anchor.length > 0 ? "#" + this.anchor : "");
|
38
39
|
}
|
39
40
|
static getNewCodeText(hyperlinkInfo) {
|
40
41
|
return [
|
@@ -45,6 +46,21 @@ export class HyperlinkInfo {
|
|
45
46
|
hyperlinkInfo.anchor == "" ? "" : " \\l \"" + hyperlinkInfo.anchor + "\""
|
46
47
|
].join("");
|
47
48
|
}
|
49
|
+
isUri() {
|
50
|
+
if (this.uri.length === 0)
|
51
|
+
return false;
|
52
|
+
if (this.uri.startsWith("#"))
|
53
|
+
return false;
|
54
|
+
if (this.isMail())
|
55
|
+
return false;
|
56
|
+
return UrlUtils.isValid(this.uri);
|
57
|
+
}
|
58
|
+
isMail() {
|
59
|
+
return this.uri.startsWith("mailto:");
|
60
|
+
}
|
61
|
+
isValid() {
|
62
|
+
return !!(this.uri || this.anchor);
|
63
|
+
}
|
48
64
|
}
|
49
65
|
export class SequenceInfo {
|
50
66
|
constructor(identifier, repeats, hidesResult, resets, resetsWith) {
|
@@ -10,7 +10,7 @@ export class FieldCodeParserClientUpdatingBase extends FieldCodeParser {
|
|
10
10
|
}
|
11
11
|
parseCodeCurrentFieldInternal(_responce) {
|
12
12
|
this.removeInterval(this.getTopField().getResultInterval());
|
13
|
-
if (this.parseSwitchesAndArgs(
|
13
|
+
if (this.parseSwitchesAndArgs())
|
14
14
|
this.fillResult();
|
15
15
|
this.parserState = FieldCodeParserState.end;
|
16
16
|
return true;
|
@@ -19,7 +19,7 @@ export class FieldCodeParserDocVariable extends FieldCodeParser {
|
|
19
19
|
this.parserState = FieldCodeParserState.end;
|
20
20
|
return true;
|
21
21
|
}
|
22
|
-
if (!this.parseSwitchesAndArgs(
|
22
|
+
if (!this.parseSwitchesAndArgs()) {
|
23
23
|
this.parserState = FieldCodeParserState.end;
|
24
24
|
return true;
|
25
25
|
}
|
@@ -6,10 +6,11 @@ import { HyperlinkInfo } from '../field';
|
|
6
6
|
import { FieldName } from '../names';
|
7
7
|
import { FieldCodeParserState, FieldSwitchType } from './field-code-parser';
|
8
8
|
import { FieldCodeParserClientUpdatingBase } from './field-code-parser-client-updating-base';
|
9
|
+
import { UrlUtils } from '../../../utils/utils';
|
9
10
|
export class FieldCodeParserHyperlink extends FieldCodeParserClientUpdatingBase {
|
10
11
|
get name() { return FieldName.Hyperlink; }
|
11
12
|
parseCodeCurrentFieldInternal(_responce) {
|
12
|
-
if (this.parseSwitchesAndArgs(
|
13
|
+
if (this.parseSwitchesAndArgs())
|
13
14
|
this.fillResult();
|
14
15
|
else
|
15
16
|
this.removeInterval(this.getTopField().getResultInterval());
|
@@ -17,54 +18,47 @@ export class FieldCodeParserHyperlink extends FieldCodeParserClientUpdatingBase
|
|
17
18
|
return true;
|
18
19
|
}
|
19
20
|
fillResult() {
|
20
|
-
var
|
21
|
-
|
22
|
-
|
21
|
+
var _a, _b;
|
22
|
+
const field = this.getTopField();
|
23
|
+
const text = (_b = (_a = this.parameterInfoList[0]) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : "";
|
24
|
+
const newHyperlinkInfo = this.updateHyperlinkInfo(text);
|
23
25
|
if (!newHyperlinkInfo) {
|
24
|
-
if (!this.modelManager.richOptions.fields.keepHyperlinkResultForInvalidReference)
|
26
|
+
if (!this.modelManager.richOptions.fields.keepHyperlinkResultForInvalidReference) {
|
25
27
|
this.removeInterval(this.getTopField().getResultInterval());
|
28
|
+
}
|
26
29
|
return true;
|
27
30
|
}
|
28
|
-
|
29
|
-
|
30
|
-
if (resultInterval.length
|
31
|
-
|
32
|
-
|
31
|
+
const modelManipulator = this.modelManager.modelManipulator;
|
32
|
+
const resultInterval = field.getResultInterval();
|
33
|
+
if (resultInterval.length === 0) {
|
34
|
+
const resultText = text !== null && text !== void 0 ? text : "#" + newHyperlinkInfo.anchor;
|
35
|
+
const newResultInterval = new FixedInterval(resultInterval.start, resultText.length);
|
33
36
|
this.setInputPositionState();
|
34
37
|
this.replaceTextByInterval(resultInterval, resultText);
|
35
|
-
|
38
|
+
const subDocumentInterval = new SubDocumentInterval(this.subDocument, newResultInterval);
|
39
|
+
const historyItem = new ApplyFieldHyperlinkStyleHistoryItem(modelManipulator, subDocumentInterval);
|
40
|
+
this.modelManager.history.addAndRedo(historyItem);
|
36
41
|
}
|
37
|
-
|
42
|
+
const historyItem = new ChangeFieldHyperlinkInfoHistoryItem(modelManipulator, this.subDocument, field.index, newHyperlinkInfo);
|
43
|
+
this.modelManager.history.addAndRedo(historyItem);
|
38
44
|
return true;
|
39
45
|
}
|
40
|
-
updateHyperlinkInfo(
|
41
|
-
|
46
|
+
updateHyperlinkInfo(text) {
|
47
|
+
const newHyperlinkInfo = new HyperlinkInfo("", "", "", false);
|
48
|
+
[newHyperlinkInfo.uri, newHyperlinkInfo.anchor] = UrlUtils.splitUrlByAnchor(text);
|
42
49
|
newHyperlinkInfo.visited = false;
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
break;
|
54
|
-
}
|
50
|
+
for (const switchInfo of this.switchInfoList) {
|
51
|
+
if (switchInfo.type != FieldSwitchType.FieldSpecific)
|
52
|
+
continue;
|
53
|
+
switch (switchInfo.name.toLocaleUpperCase()) {
|
54
|
+
case "O":
|
55
|
+
newHyperlinkInfo.tip = switchInfo.arg;
|
56
|
+
break;
|
57
|
+
case "L":
|
58
|
+
newHyperlinkInfo.anchor = switchInfo.arg;
|
59
|
+
break;
|
55
60
|
}
|
56
|
-
newHyperlinkInfo.tip = tipSwitch ? tipSwitch.arg : "";
|
57
|
-
var splitted = text.split("#");
|
58
|
-
if (splitted.length == 1) {
|
59
|
-
newHyperlinkInfo.uri = splitted[0];
|
60
|
-
newHyperlinkInfo.anchor = bookmarkSwitch ? bookmarkSwitch.arg : "";
|
61
|
-
if (newHyperlinkInfo.uri == "" && newHyperlinkInfo.anchor == "")
|
62
|
-
return null;
|
63
|
-
}
|
64
|
-
else {
|
65
|
-
newHyperlinkInfo.uri = splitted[0];
|
66
|
-
newHyperlinkInfo.anchor = splitted[1];
|
67
61
|
}
|
68
|
-
return newHyperlinkInfo;
|
62
|
+
return newHyperlinkInfo.isValid() ? newHyperlinkInfo : null;
|
69
63
|
}
|
70
64
|
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { FieldName } from '../names';
|
2
|
+
import { FieldCodeParserClientUpdatingBase } from './field-code-parser-client-updating-base';
|
3
|
+
export declare class FieldCodeParserIf extends FieldCodeParserClientUpdatingBase {
|
4
|
+
get name(): FieldName;
|
5
|
+
protected fillResult(): boolean;
|
6
|
+
private parseParameters;
|
7
|
+
}
|
8
|
+
export declare class IfExpression {
|
9
|
+
operator: string;
|
10
|
+
leftExpression: IfExpressionParameter;
|
11
|
+
rightExpression: IfExpressionParameter;
|
12
|
+
trueText: string;
|
13
|
+
falseText: string;
|
14
|
+
static operators: string[];
|
15
|
+
constructor(operator: string, leftExpression: IfExpressionParameter, rightExpression: IfExpressionParameter, trueText?: string, falseText?: string);
|
16
|
+
static isOperator(operator: string): boolean;
|
17
|
+
evaluate(): string;
|
18
|
+
private evaluateComparison;
|
19
|
+
static compareStrings(leftValue: string, rightValue: string): number;
|
20
|
+
static compareStringsWithWildcards(leftValue: string, rightValue: string): 0 | 1;
|
21
|
+
}
|
22
|
+
export declare class IfExpressionParameter {
|
23
|
+
text: string;
|
24
|
+
number: number;
|
25
|
+
isNumber: boolean;
|
26
|
+
constructor(text: string, isQuoted?: boolean);
|
27
|
+
}
|
28
|
+
export declare class IfExpressionError extends Error {
|
29
|
+
constructor(message: string);
|
30
|
+
}
|
31
|
+
export declare class IfExpressionInvalidOperatorError extends IfExpressionError {
|
32
|
+
constructor(message?: string);
|
33
|
+
}
|
34
|
+
export declare class IfExpressionTooManyParametersError extends IfExpressionError {
|
35
|
+
constructor(message?: string);
|
36
|
+
}
|
37
|
+
export declare class IfExpressionMissingParametersError extends IfExpressionError {
|
38
|
+
constructor(message?: string);
|
39
|
+
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
import { FieldName } from '../names';
|
2
|
+
import { FieldCodeParserClientUpdatingBase } from './field-code-parser-client-updating-base';
|
3
|
+
export class FieldCodeParserIf extends FieldCodeParserClientUpdatingBase {
|
4
|
+
get name() { return FieldName.If; }
|
5
|
+
fillResult() {
|
6
|
+
this.setInputPositionState();
|
7
|
+
let result = null;
|
8
|
+
try {
|
9
|
+
const expression = this.parseParameters(this.parameterInfoList);
|
10
|
+
result = expression.evaluate();
|
11
|
+
}
|
12
|
+
catch (err) {
|
13
|
+
if (err instanceof IfExpressionError) {
|
14
|
+
result = err.message;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
finally {
|
18
|
+
if (result) {
|
19
|
+
this.replaceTextByInterval(this.getTopField().getResultInterval(), result);
|
20
|
+
}
|
21
|
+
return true;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
parseParameters(parameters) {
|
25
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
26
|
+
if (parameters.length > 5)
|
27
|
+
throw new IfExpressionTooManyParametersError();
|
28
|
+
if (parameters.length === 0)
|
29
|
+
throw new IfExpressionMissingParametersError();
|
30
|
+
let leftExpression;
|
31
|
+
let operator;
|
32
|
+
let rightExpression;
|
33
|
+
let trueText;
|
34
|
+
let falseText;
|
35
|
+
if (parameters.length <= 3 && !IfExpression.isOperator((_a = parameters[1]) === null || _a === void 0 ? void 0 : _a.text)) {
|
36
|
+
leftExpression = new IfExpressionParameter((_b = parameters[0]) === null || _b === void 0 ? void 0 : _b.text, (_c = parameters[0]) === null || _c === void 0 ? void 0 : _c.quoted);
|
37
|
+
trueText = (_d = parameters[1]) === null || _d === void 0 ? void 0 : _d.text;
|
38
|
+
falseText = (_e = parameters[2]) === null || _e === void 0 ? void 0 : _e.text;
|
39
|
+
}
|
40
|
+
else {
|
41
|
+
leftExpression = new IfExpressionParameter((_f = parameters[0]) === null || _f === void 0 ? void 0 : _f.text, (_g = parameters[0]) === null || _g === void 0 ? void 0 : _g.quoted);
|
42
|
+
operator = (_h = parameters[1]) === null || _h === void 0 ? void 0 : _h.text;
|
43
|
+
rightExpression = new IfExpressionParameter((_j = parameters[2]) === null || _j === void 0 ? void 0 : _j.text, (_k = parameters[2]) === null || _k === void 0 ? void 0 : _k.quoted);
|
44
|
+
trueText = (_l = parameters[3]) === null || _l === void 0 ? void 0 : _l.text;
|
45
|
+
falseText = (_m = parameters[4]) === null || _m === void 0 ? void 0 : _m.text;
|
46
|
+
}
|
47
|
+
return new IfExpression(operator, leftExpression, rightExpression, trueText, falseText);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
export class IfExpression {
|
51
|
+
constructor(operator, leftExpression, rightExpression, trueText = undefined, falseText = undefined) {
|
52
|
+
this.operator = operator;
|
53
|
+
this.leftExpression = leftExpression;
|
54
|
+
this.rightExpression = rightExpression;
|
55
|
+
this.trueText = trueText;
|
56
|
+
this.falseText = falseText;
|
57
|
+
}
|
58
|
+
static isOperator(operator) {
|
59
|
+
return IfExpression.operators.includes(operator);
|
60
|
+
}
|
61
|
+
evaluate() {
|
62
|
+
if (!this.operator && !this.leftExpression.isNumber) {
|
63
|
+
return this.leftExpression.text ? this.trueText : this.falseText;
|
64
|
+
}
|
65
|
+
if (!IfExpression.isOperator(this.operator)) {
|
66
|
+
throw new IfExpressionInvalidOperatorError();
|
67
|
+
}
|
68
|
+
let difference;
|
69
|
+
if (this.leftExpression.isNumber && this.rightExpression.isNumber) {
|
70
|
+
difference = this.leftExpression.number - this.rightExpression.number;
|
71
|
+
}
|
72
|
+
else {
|
73
|
+
const isEqualityOperator = this.operator === "=" || this.operator === "<>";
|
74
|
+
const compareFunction = isEqualityOperator ? IfExpression.compareStringsWithWildcards : IfExpression.compareStrings;
|
75
|
+
difference = compareFunction(this.leftExpression.text, this.rightExpression.text);
|
76
|
+
}
|
77
|
+
return this.evaluateComparison(difference) ? this.trueText : this.falseText;
|
78
|
+
}
|
79
|
+
evaluateComparison(comparisonResult) {
|
80
|
+
switch (this.operator) {
|
81
|
+
case "<":
|
82
|
+
return comparisonResult < 0;
|
83
|
+
case ">":
|
84
|
+
return comparisonResult > 0;
|
85
|
+
case "=":
|
86
|
+
return comparisonResult === 0;
|
87
|
+
case "<=":
|
88
|
+
return comparisonResult <= 0;
|
89
|
+
case ">=":
|
90
|
+
return comparisonResult >= 0;
|
91
|
+
case "<>":
|
92
|
+
return comparisonResult != 0;
|
93
|
+
default:
|
94
|
+
return false;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
static compareStrings(leftValue, rightValue) {
|
98
|
+
return leftValue.localeCompare(rightValue);
|
99
|
+
}
|
100
|
+
static compareStringsWithWildcards(leftValue, rightValue) {
|
101
|
+
const escapedPattern = rightValue.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
102
|
+
const regexPattern = escapedPattern.replace(/\*/g, '.*').replace(/\?/g, '.');
|
103
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
104
|
+
return regex.test(leftValue) ? 0 : 1;
|
105
|
+
}
|
106
|
+
}
|
107
|
+
IfExpression.operators = ["<", ">", "=", "<=", ">=", "<>"];
|
108
|
+
export class IfExpressionParameter {
|
109
|
+
constructor(text, isQuoted = false) {
|
110
|
+
this.text = text;
|
111
|
+
this.number = parseFloat(text);
|
112
|
+
this.isNumber = !isQuoted && !Number.isNaN(this.number);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
export class IfExpressionError extends Error {
|
116
|
+
constructor(message) {
|
117
|
+
super(message);
|
118
|
+
Object.setPrototypeOf(this, IfExpressionError.prototype);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
export class IfExpressionInvalidOperatorError extends IfExpressionError {
|
122
|
+
constructor(message) {
|
123
|
+
super(message !== null && message !== void 0 ? message : "IF field error: Invalid comparison operator");
|
124
|
+
Object.setPrototypeOf(this, IfExpressionInvalidOperatorError.prototype);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
export class IfExpressionTooManyParametersError extends IfExpressionError {
|
128
|
+
constructor(message) {
|
129
|
+
super(message !== null && message !== void 0 ? message : "IF field error: Too many parameters");
|
130
|
+
Object.setPrototypeOf(this, IfExpressionTooManyParametersError.prototype);
|
131
|
+
}
|
132
|
+
}
|
133
|
+
export class IfExpressionMissingParametersError extends IfExpressionError {
|
134
|
+
constructor(message) {
|
135
|
+
super(message !== null && message !== void 0 ? message : "IF field error: Missing parameter(s)");
|
136
|
+
Object.setPrototypeOf(this, IfExpressionMissingParametersError.prototype);
|
137
|
+
}
|
138
|
+
}
|
@@ -25,7 +25,7 @@ export class FieldCodeParserMailMerge extends FieldCodeParserDocVariable {
|
|
25
25
|
}
|
26
26
|
getMergeFieldName() {
|
27
27
|
if (this.parameterInfoList.length == 0)
|
28
|
-
this.parseSwitchesAndArgs(
|
28
|
+
this.parseSwitchesAndArgs();
|
29
29
|
return this.parameterInfoList[0] ? this.parameterInfoList[0].text : '';
|
30
30
|
}
|
31
31
|
applyResponse(response) {
|