devexpress-richedit 24.2.1-alpha-24260-0102 → 24.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/bin/gulpfile.js +1 -1
  2. package/bin/index-custom.js +1 -1
  3. package/bin/localization-builder.js +1 -1
  4. package/bin/nspell-index.js +1 -1
  5. package/bin/nspell.webpack.config.js +1 -1
  6. package/bin/webpack-externals.js +1 -1
  7. package/bin/webpack.config.js +1 -1
  8. package/dist/dx.richedit.d.ts +12 -1
  9. package/dist/dx.richedit.js +5908 -406
  10. package/dist/dx.richedit.min.js +2 -2
  11. package/index.d.ts +1 -1
  12. package/index.js +1 -1
  13. package/lib/client/bars/rich-edit-ribbon/ribbon-items-data.js +2 -1
  14. package/lib/client/client-rich-edit.js +6 -6
  15. package/lib/client/commands/commands.js +3 -0
  16. package/lib/client/commands/mail-merge-command.d.ts +4 -1
  17. package/lib/client/commands/mail-merge-command.js +51 -18
  18. package/lib/client/commands/new-document-command.js +2 -1
  19. package/lib/client/default-localization.js +2 -0
  20. package/lib/client/dialogs/hyperlink-dialog.js +13 -6
  21. package/lib/client/formats/docx/export/exporters/styles.d.ts +5 -0
  22. package/lib/client/formats/docx/export/exporters/styles.js +30 -1
  23. package/lib/client/formats/docx/import/color/open-xml-color-import-helper.js +2 -2
  24. package/lib/client/formats/docx/import/importers/styles-importer.js +2 -1
  25. package/lib/client/formatters-options.js +2 -2
  26. package/lib/client/i-rich-constructor-settings.d.ts +1 -2
  27. package/lib/client/model-api/api-utils/range-permission-finder.js +3 -1
  28. package/lib/client/model-api/collections/drawing-object-collection.js +1 -1
  29. package/lib/client/model-api/collections/hyperlink-collection.js +1 -1
  30. package/lib/client/model-api/collections/range-permission-collection.js +3 -2
  31. package/lib/client/public/commands/enum.d.ts +1 -0
  32. package/lib/client/public/commands/enum.js +1 -0
  33. package/lib/client/public/options.d.ts +1 -2
  34. package/lib/client/public/ribbon/item-ids.d.ts +1 -0
  35. package/lib/client/public/ribbon/item-ids.js +1 -0
  36. package/lib/client/public/rich-edit.js +1 -1
  37. package/lib/client/settings.js +2 -4
  38. package/lib/common/commands/client-command.d.ts +2 -1
  39. package/lib/common/commands/client-command.js +1 -0
  40. package/lib/common/commands/command-manager.js +2 -1
  41. package/lib/common/commands/dialogs/dialog-hyperlink-command.js +10 -4
  42. package/lib/common/commands/fields/create-field-command.d.ts +4 -0
  43. package/lib/common/commands/fields/create-field-command.js +8 -0
  44. package/lib/common/commands/fields/open-hyperlink-command.js +9 -6
  45. package/lib/common/commands/floating-objects/floating-object-drag-drop-change-position-command.js +1 -1
  46. package/lib/common/commands/floating-objects/insert-anchored-text-box-command.js +1 -1
  47. package/lib/common/formats/html/export/html-export.d.ts +7 -1
  48. package/lib/common/formats/html/export/html-export.js +35 -35
  49. package/lib/common/formats/html/import/html-importer.js +1 -1
  50. package/lib/common/formats/html/import/importers/list-base.js +4 -4
  51. package/lib/common/formats/rtf/export/helpers/rtf-export-helper.js +3 -2
  52. package/lib/common/input-controller.d.ts +14 -1
  53. package/lib/common/input-controller.js +58 -20
  54. package/lib/common/layout/document-layout.js +1 -1
  55. package/lib/common/layout/main-structures/layout-boxes/layout-space-box.js +1 -1
  56. package/lib/common/model/color/color-model-info.d.ts +1 -1
  57. package/lib/common/model/color/color-model-info.js +2 -1
  58. package/lib/common/model/fields/field.d.ts +4 -1
  59. package/lib/common/model/fields/field.js +18 -2
  60. package/lib/common/model/fields/names.d.ts +2 -1
  61. package/lib/common/model/fields/names.js +1 -0
  62. package/lib/common/model/fields/parsers/field-code-parser-client-updating-base.js +1 -1
  63. package/lib/common/model/fields/parsers/field-code-parser-doc-variable.js +1 -1
  64. package/lib/common/model/fields/parsers/field-code-parser-hyperlink.js +32 -38
  65. package/lib/common/model/fields/parsers/field-code-parser-if.d.ts +40 -0
  66. package/lib/common/model/fields/parsers/field-code-parser-if.js +141 -0
  67. package/lib/common/model/fields/parsers/field-code-parser-merge-field.js +1 -1
  68. package/lib/common/model/fields/parsers/field-code-parser.d.ts +3 -2
  69. package/lib/common/model/fields/parsers/field-code-parser.js +6 -12
  70. package/lib/common/model/fields/tree-creator.js +2 -0
  71. package/lib/common/model/history/items/floating-objects/insert-anchored-picture-history-item.js +1 -0
  72. package/lib/common/model/history/items/switch-text-box-sub-documents-state-history-item.js +0 -1
  73. package/lib/common/model/manipulators/document/sub-document-inserter.d.ts +1 -0
  74. package/lib/common/model/manipulators/document/sub-document-inserter.js +4 -0
  75. package/lib/common/model/manipulators/range/remove-interval-operation.d.ts +2 -0
  76. package/lib/common/model/manipulators/range/remove-interval-operation.js +10 -2
  77. package/lib/common/model/manipulators/range-permission-manipulator.d.ts +4 -0
  78. package/lib/common/model/manipulators/range-permission-manipulator.js +35 -0
  79. package/lib/common/model/manipulators/text-box-manipulator.d.ts +1 -1
  80. package/lib/common/model/manipulators/text-box-manipulator.js +2 -1
  81. package/lib/common/model/manipulators/text-manipulator/text-manipulator.js +1 -1
  82. package/lib/common/model/options/fields.d.ts +1 -2
  83. package/lib/common/model/options/fields.js +2 -5
  84. package/lib/common/model/range-permissions.js +6 -4
  85. package/lib/common/model/styles-manager.js +1 -0
  86. package/lib/common/selection/selection.js +2 -1
  87. package/lib/common/ui/ruler/controls/indent/first-line.js +5 -5
  88. package/lib/common/ui/ruler/controls/indent/left.js +6 -6
  89. package/lib/common/ui/ruler/controls/indent/right.js +4 -4
  90. package/lib/common/ui/ruler/controls/margin/left.js +1 -1
  91. package/lib/common/ui/ruler/controls/margin/right.js +1 -1
  92. package/lib/common/ui/ruler/controls/ruler.js +2 -2
  93. package/lib/common/ui/ruler/controls/tab/tab-type.js +3 -3
  94. package/lib/common/ui/ruler/controls/tab/tab.js +7 -7
  95. package/lib/common/ui/ruler/controls/tab/utils.d.ts +2 -2
  96. package/lib/common/ui/ruler/controls/tab/utils.js +5 -5
  97. package/lib/common/ui/ruler/controls/table.js +1 -1
  98. package/lib/common/ui/ruler/controls/vertical-line.d.ts +1 -2
  99. package/lib/common/ui/ruler/controls/vertical-line.js +2 -2
  100. package/lib/common/ui/ruler/controls/wrapper.js +1 -1
  101. package/lib/common/ui/ruler/manager.js +1 -1
  102. package/lib/common/ui/ruler/model-data.d.ts +8 -2
  103. package/lib/common/ui/ruler/model-data.js +6 -0
  104. package/lib/common/ui/ruler/ruler.js +2 -1
  105. package/lib/common/utils/utils.d.ts +10 -5
  106. package/lib/common/utils/utils.js +46 -18
  107. package/package.json +3 -3
@@ -4,7 +4,7 @@ import { ReadOnlyMode } from '../../interfaces/i-rich-edit-core';
4
4
  import { RichEditClientCommand } from '../client-command';
5
5
  import { CommandSimpleOptions } from '../command-base';
6
6
  import { HyperlinkCommandBase } from './hyperlink-command-base';
7
- import { createUrlValidationOptions, isUrlValid } from '../../../common/utils/utils';
7
+ import { createUrlValidationOptions, UrlUtils } from '../../../common/utils/utils';
8
8
  export class OpenHyperlinkCommand extends HyperlinkCommandBase {
9
9
  executeCore(state, options) {
10
10
  let field;
@@ -25,13 +25,16 @@ export class OpenHyperlinkCommand extends HyperlinkCommandBase {
25
25
  this.history.endTransaction();
26
26
  this.aspxForceSendingRequest();
27
27
  }
28
- if (hyperlinkInfo.anchor)
28
+ if (hyperlinkInfo.isUri()) {
29
+ const options = createUrlValidationOptions(this.control.modelManager);
30
+ let uri = hyperlinkInfo.getUriWithAnchor();
31
+ if (!UrlUtils.isValid(uri, options))
32
+ uri = UrlUtils.EmptyPage;
33
+ Url.navigate(uri, "_blank");
34
+ }
35
+ else {
29
36
  this.control.commandManager.getCommand(RichEditClientCommand.GoToBookmark)
30
37
  .execute(this.control.commandManager.isPublicApiCall, new CommandSimpleOptions(this.control, hyperlinkInfo.anchor));
31
- else {
32
- const options = createUrlValidationOptions(this.control);
33
- if (isUrlValid(hyperlinkInfo.uri, options))
34
- Url.navigate(hyperlinkInfo.uri, "_blank");
35
38
  }
36
39
  return true;
37
40
  }
@@ -200,7 +200,7 @@ export class FloatingObjectDragDropChangePositionCommand extends CommandBase {
200
200
  const newRun = this.activeSubDocument.getRunAndIndexesByPosition(position).run;
201
201
  if (newRun.getType() == RunType.AnchoredTextBoxRun) {
202
202
  const oldTextBoxRun = oldRun;
203
- const originalSubDocument = this.control.modelManager.model.subDocuments[oldTextBoxRun.subDocId];
203
+ const originalSubDocument = this.control.modelManager.model.subDocumentsCollection.collection[oldTextBoxRun.subDocId];
204
204
  this.history.addAndRedo(new SwitchTextBoxSubDocumentsStateHistoryItem(this.modelManipulator, originalSubDocument, this.activeSubDocument, position));
205
205
  }
206
206
  }
@@ -44,7 +44,7 @@ export class InsertAnchoredTextBoxCommand extends CommandBase {
44
44
  anchorInfo.zOrder = this.modelManipulator.floatingObject.zOrder.getNewZOrder(options.subDocument);
45
45
  anchorInfo.layoutTableCell = true;
46
46
  history.addTransaction(() => {
47
- this.modelManipulator.textBox.insertAnchoredTextBoxViaHistoty(new SubDocumentPosition(this.selection.activeSubDocument, this.selection.lastSelectedInterval.start), this.inputPosition.charPropsBundle, new BaseTextBoxInfo(null, size, new Shape(ColorUtils.fromString(ColorUtils.colorNames.white), ColorHelper.BLACK_COLOR, UnitConverter.pointsToTwips(3.0 / 4)), anchorInfo, textBoxProperties, new NonVisualDrawingObjectInfo()));
47
+ this.modelManipulator.textBox.insertAnchoredTextBoxViaHistory(new SubDocumentPosition(this.selection.activeSubDocument, this.selection.lastSelectedInterval.start), this.inputPosition.charPropsBundle, new BaseTextBoxInfo(null, size, new Shape(ColorUtils.fromString(ColorUtils.colorNames.white), ColorHelper.BLACK_COLOR, UnitConverter.pointsToTwips(3.0 / 4)), anchorInfo, textBoxProperties, new NonVisualDrawingObjectInfo()));
48
48
  this.history.addAndRedo(new SelectionHistoryItem(this.modelManipulator, this.selection, this.selection.getState(), this.selection.getState().setInterval(new FixedInterval(this.selection.lastSelectedInterval.start, 1))));
49
49
  this.control.commandManager.getCommand(RichEditClientCommand.ChangeActiveSubDocumentToTextBox)
50
50
  .execute(this.control.commandManager.isPublicApiCall, options);
@@ -6,21 +6,27 @@ import { SubDocument } from '../../../model/sub-document';
6
6
  import { HtmlBuilder } from './html-builder';
7
7
  import { IExportModelOptions } from '../../i-document-exporter';
8
8
  interface List {
9
+ parentList?: List;
9
10
  numberingListIndex: number;
10
11
  listLevelIndex: number;
11
12
  start: number;
12
13
  end: number;
13
14
  }
15
+ interface IHtmlExporterOptions {
16
+ sanitaizeHyperlinkURIs?: boolean;
17
+ convertRelativeURIsToAbsolute?: boolean;
18
+ }
14
19
  export declare class HtmlExporter {
15
20
  rangeCopy: RangeCopy;
16
21
  private exportModelOptions;
22
+ private htmlExporterOptions;
17
23
  private get modelManager();
18
24
  private get colorProvider();
19
25
  private get unitConverter();
20
26
  private get documentRenderer();
21
27
  private get lastMaxNumPages();
22
28
  private get pageIndex();
23
- constructor(exportModelOptions: IExportModelOptions);
29
+ constructor(exportModelOptions: IExportModelOptions, htmlExporterOptions?: IHtmlExporterOptions);
24
30
  getHtmlElementsByInterval(model: DocumentModel, subDocument: SubDocument, interval: FixedInterval, guidLabel: string): HtmlBuilder;
25
31
  getParagraphsByInterval(subDocument: SubDocument, interval: FixedInterval): Paragraph[];
26
32
  getListsByParagraphs(paragraphs: Paragraph[]): List[];
@@ -24,6 +24,8 @@ import { TableWidthUnitType } from '../../../model/tables/secondary-structures/t
24
24
  import { HtmlConverter } from '../../../rich-utils/html-converter';
25
25
  import { HtmlBuilder } from './html-builder';
26
26
  import { isDefined } from '@devexpress/utils/lib/utils/common';
27
+ import { createUrlValidationOptions, UrlUtils } from '../../../../common/utils/utils';
28
+ import { ListUtils } from '@devexpress/utils/lib/utils/list';
27
29
  export class HtmlExporter {
28
30
  get modelManager() { return this.exportModelOptions.modelManager; }
29
31
  get colorProvider() { return this.modelManager.model.colorProvider; }
@@ -33,11 +35,13 @@ export class HtmlExporter {
33
35
  ;
34
36
  get pageIndex() { return this.exportModelOptions.pageIndex; }
35
37
  ;
36
- constructor(exportModelOptions) {
38
+ constructor(exportModelOptions, htmlExporterOptions = null) {
37
39
  this.rangeCopy = null;
38
40
  this.exportModelOptions = exportModelOptions;
41
+ this.htmlExporterOptions = htmlExporterOptions;
39
42
  }
40
43
  getHtmlElementsByInterval(model, subDocument, interval, guidLabel) {
44
+ var _a, _b, _c, _d;
41
45
  if (interval.length === 0)
42
46
  return;
43
47
  const unitTypeToString = this.unitConverter.getUnits() == RichEditUnit.Centimeter ? "cm" : "in";
@@ -337,7 +341,18 @@ export class HtmlExporter {
337
341
  break;
338
342
  }
339
343
  if (hyperlinkInfo && !isInsideHyperlink) {
340
- const url = hyperlinkInfo.uri + (hyperlinkInfo.anchor != "" ? "#" + hyperlinkInfo.anchor : "");
344
+ const sanitaizeHyperlinkURIs = (_b = (_a = this.htmlExporterOptions) === null || _a === void 0 ? void 0 : _a.sanitaizeHyperlinkURIs) !== null && _b !== void 0 ? _b : false;
345
+ const convertRelativeURIsToAbsolute = (_d = (_c = this.htmlExporterOptions) === null || _c === void 0 ? void 0 : _c.convertRelativeURIsToAbsolute) !== null && _d !== void 0 ? _d : false;
346
+ let url = hyperlinkInfo.uri;
347
+ const options = createUrlValidationOptions(this.exportModelOptions.modelManager);
348
+ if (!sanitaizeHyperlinkURIs || UrlUtils.isValid(url, options)) {
349
+ if (convertRelativeURIsToAbsolute && UrlUtils.isRelative(url))
350
+ url = UrlUtils.convertToAbsolute(url).href;
351
+ if (hyperlinkInfo.anchor != "")
352
+ url = url + "#" + hyperlinkInfo.anchor;
353
+ }
354
+ else
355
+ url = UrlUtils.EmptyPage;
341
356
  const tooltip = hyperlinkInfo.tip;
342
357
  html
343
358
  .clear()
@@ -455,42 +470,27 @@ export class HtmlExporter {
455
470
  }
456
471
  getListsByParagraphs(paragraphs) {
457
472
  const listsInInterval = [];
473
+ let previousList = null;
458
474
  for (let i = 0, paragraph; paragraph = paragraphs[i]; i++) {
459
475
  if (paragraph.isInList()) {
460
- const paragraphNumberingListIndex = paragraph.getNumberingListIndex();
461
- const paragraphListLevelIndex = paragraph.getListLevelIndex();
462
- const paragraphStart = paragraph.startLogPosition.value;
463
- const paragraphEnd = paragraph.getEndPosition();
464
- let existingItem = null;
465
- for (let j = 0; j < listsInInterval.length; j++) {
466
- if (listsInInterval[j].numberingListIndex === paragraphNumberingListIndex
467
- && listsInInterval[j].listLevelIndex === paragraphListLevelIndex) {
468
- existingItem = listsInInterval[j];
469
- }
470
- }
471
- if (existingItem && (paragraphListLevelIndex === 0 || existingItem.end == paragraphStart
472
- || listsInInterval[listsInInterval.length - 1].listLevelIndex > paragraphListLevelIndex)) {
473
- existingItem.end = paragraphEnd;
474
- }
475
- else {
476
- listsInInterval.push({
477
- numberingListIndex: paragraphNumberingListIndex,
478
- listLevelIndex: paragraphListLevelIndex,
479
- start: paragraphStart,
480
- end: paragraphEnd,
481
- });
482
- }
483
- let listLevelIndex = paragraphListLevelIndex;
484
- while (listLevelIndex > 0) {
485
- let parentItem = null;
486
- for (let j = 0; j < listsInInterval.length; j++) {
487
- if (listsInInterval[j].listLevelIndex == listLevelIndex - 1)
488
- parentItem = listsInInterval[j];
489
- }
490
- if (parentItem)
491
- parentItem.end = paragraphEnd;
492
- listLevelIndex--;
476
+ const numberingListIndex = paragraph.getNumberingListIndex();
477
+ const listLevelIndex = paragraph.getListLevelIndex();
478
+ const start = paragraph.startLogPosition.value;
479
+ const end = paragraph.getEndPosition();
480
+ let list = ListUtils.reverseElementBy(listsInInterval, (list) => {
481
+ return list.listLevelIndex <= (previousList === null || previousList === void 0 ? void 0 : previousList.listLevelIndex)
482
+ && list.numberingListIndex === numberingListIndex
483
+ && list.listLevelIndex === listLevelIndex;
484
+ });
485
+ if (!list) {
486
+ const parentList = (previousList === null || previousList === void 0 ? void 0 : previousList.numberingListIndex) === numberingListIndex ? previousList : null;
487
+ list = { parentList, numberingListIndex, listLevelIndex, start, end };
488
+ listsInInterval.push(list);
493
489
  }
490
+ previousList = list;
491
+ do {
492
+ list.end = end;
493
+ } while (list = list.parentList);
494
494
  }
495
495
  }
496
496
  return listsInInterval;
@@ -191,7 +191,7 @@ export class HtmlImporter {
191
191
  const missTag = HtmlImporter.MapMissTablePropertiesByTagNames[ListUtils.last(this.levelInfo).tagImporter.elementTag()];
192
192
  ListUtils.forEach(this.currElementChildren, (childElement) => {
193
193
  const childElemStyle = this.getStyles(childElement);
194
- if (!Object.keys(childElemStyle).length)
194
+ if (childElement.nodeType !== Node.ELEMENT_NODE)
195
195
  return;
196
196
  for (var prop in this.getStyles(element)) {
197
197
  if (missTag && /^(border|background|marginLeft)/gi.test(prop))
@@ -13,9 +13,7 @@ export class HtmlListTagImporterBase extends HtmlTagImporterBase {
13
13
  this.importer.addCurrLevelParagraphRunIfNeeded();
14
14
  const listIndex = this.importer.listIndex;
15
15
  const parentList = ListUtils.last(this.importer.listInfos);
16
- const listLevel = parentList
17
- ? parentList.listLevel + 1
18
- : 0;
16
+ const listLevel = parentList ? parentList.listLevel + 1 : 0;
19
17
  if (listLevel === 9) {
20
18
  this._ignored = true;
21
19
  return;
@@ -31,6 +29,8 @@ export class HtmlListTagImporterBase extends HtmlTagImporterBase {
31
29
  if (this._ignored)
32
30
  return;
33
31
  this.importer.listInfos.pop();
34
- this.importer.listIndex++;
32
+ const parentList = ListUtils.last(this.importer.listInfos);
33
+ if (!parentList)
34
+ this.importer.listIndex++;
35
35
  }
36
36
  }
@@ -4,6 +4,7 @@ import { DXColor } from '../../../../model/color/dx-color';
4
4
  import { ListUtils } from '@devexpress/utils/lib/utils/list';
5
5
  import { NumberMapUtils } from '@devexpress/utils/lib/utils/map/number';
6
6
  import { RtfContentExporter } from '../exporters/rtf-content-exporter';
7
+ import { Comparers } from '@devexpress/utils/lib/utils/comparers';
7
8
  export class RtfExportHelper {
8
9
  constructor() {
9
10
  this.colorCollection = [];
@@ -39,11 +40,11 @@ export class RtfExportHelper {
39
40
  return DXColor.blend(color, DXColor.white);
40
41
  }
41
42
  getUserIndex(rangePermission) {
42
- let index = this.userCollection.indexOf(rangePermission.userName);
43
+ let index = this.userCollection.findIndex((userName) => Comparers.stringIgnoreCase(userName, rangePermission.userName) == 0);
43
44
  if (index >= 0)
44
45
  return index + 1;
45
46
  const predefinedUserGroups = RtfContentExporter.predefinedUserGroups;
46
- const id = NumberMapUtils.keyBy(predefinedUserGroups, (g) => g == rangePermission.group);
47
+ const id = NumberMapUtils.keyBy(predefinedUserGroups, (g) => Comparers.stringIgnoreCase(g, rangePermission.group) == 0);
47
48
  return id != null ? id : 0;
48
49
  }
49
50
  }
@@ -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
- isIME: boolean;
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 (!this.isIME) {
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
- if (Browser.Safari)
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 (Browser.MacOSMobilePlatform && text[text.length - 1] == " ")
379
+ if (text[text.length - 1] == " ")
370
380
  this.clearInputElement();
371
381
  }
372
382
  }
373
383
  tryHandleShortcutByInputString(data) {
374
- if (data && !this.isIME) {
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.isIME = false;
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.isIME = false;
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.isIME = true;
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.isIME && text.length && this.previousText != text) {
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.isIME = false;
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.subDocuments[obj.belongsToSubDocId].positionManager);
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("&nbsp;", this.characterProperties));
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
- getUriPlusAnchor(): string;
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
- getUriPlusAnchor() {
37
- return this.uri + (this.anchor == "" ? "" : "#" + 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) {
@@ -11,5 +11,6 @@ export declare enum FieldName {
11
11
  Tc = 9,
12
12
  PageRef = 10,
13
13
  Toc = 11,
14
- FillIn = 12
14
+ FillIn = 12,
15
+ If = 13
15
16
  }
@@ -13,4 +13,5 @@ export var FieldName;
13
13
  FieldName[FieldName["PageRef"] = 10] = "PageRef";
14
14
  FieldName[FieldName["Toc"] = 11] = "Toc";
15
15
  FieldName[FieldName["FillIn"] = 12] = "FillIn";
16
+ FieldName[FieldName["If"] = 13] = "If";
16
17
  })(FieldName || (FieldName = {}));
@@ -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(true))
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(true)) {
22
+ if (!this.parseSwitchesAndArgs()) {
23
23
  this.parserState = FieldCodeParserState.end;
24
24
  return true;
25
25
  }