devexpress-richedit 25.1.2-beta → 25.1.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 (56) 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.css +1 -1
  9. package/dist/dx.richedit.d.ts +1 -2
  10. package/dist/dx.richedit.js +1243 -1208
  11. package/dist/dx.richedit.min.js +2 -2
  12. package/index.d.ts +1 -1
  13. package/index.js +1 -1
  14. package/lib/client/client-rich-edit.js +2 -2
  15. package/lib/client/commands/commands.js +0 -3
  16. package/lib/client/model-api/character-properties.js +13 -17
  17. package/lib/client/model-api/document.js +2 -0
  18. package/lib/client/model-api/images/images.js +1 -1
  19. package/lib/client/public/commands/enum.d.ts +1 -2
  20. package/lib/client/public/commands/enum.js +0 -1
  21. package/lib/client/public/options.d.ts +1 -0
  22. package/lib/client/utils/focus-helper.js +22 -5
  23. package/lib/common/canvas/canvas-manager.js +1 -1
  24. package/lib/common/canvas/canvas-size-info.d.ts +1 -0
  25. package/lib/common/canvas/canvas-size-info.js +2 -2
  26. package/lib/common/canvas/renderes/view-manager.js +4 -3
  27. package/lib/common/commands/client-command.d.ts +1 -2
  28. package/lib/common/commands/client-command.js +0 -1
  29. package/lib/common/commands/command-manager.js +0 -2
  30. package/lib/common/commands/document/print-document-on-client-command.d.ts +2 -0
  31. package/lib/common/commands/document/print-document-on-client-command.js +46 -18
  32. package/lib/common/commands/layout/apply-style-command.d.ts +2 -2
  33. package/lib/common/commands/layout/apply-style-command.js +3 -4
  34. package/lib/common/commands/toc/set-paragraph-level-command.js +1 -1
  35. package/lib/common/input-controller.js +1 -1
  36. package/lib/common/layout/document-layout.js +4 -1
  37. package/lib/common/layout-formatter/row/word-holder.js +1 -1
  38. package/lib/common/model/borders/border-info.js +1 -1
  39. package/lib/common/model/caches/images.d.ts +4 -1
  40. package/lib/common/model/caches/images.js +6 -2
  41. package/lib/common/model/character/character-properties.d.ts +1 -1
  42. package/lib/common/model/character/character-properties.js +14 -2
  43. package/lib/common/model/fields/field.d.ts +1 -1
  44. package/lib/common/model/fields/field.js +4 -3
  45. package/lib/common/model/fields/tree-creator.js +1 -1
  46. package/lib/common/model/history/items/character-properties-history-items.d.ts +2 -1
  47. package/lib/common/model/history/items/character-properties-history-items.js +3 -2
  48. package/lib/common/model/manipulators/character-properties-manipulator.js +2 -2
  49. package/lib/common/model/manipulators/i-properties-manipulator.d.ts +1 -1
  50. package/lib/common/model/manipulators/picture-manipulator/picture-manipulator.js +2 -2
  51. package/lib/common/model/options/fonts.d.ts +1 -1
  52. package/lib/common/ui/ruler/controls/ruler.js +3 -7
  53. package/lib/common/ui/ruler/controls/vertical-line.js +2 -1
  54. package/package.json +3 -3
  55. package/lib/common/commands/layout/toggle-allow-zoom-command.d.ts +0 -7
  56. package/lib/common/commands/layout/toggle-allow-zoom-command.js +0 -17
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * DevExpress WebRichEdit (index.d.ts)
3
- * Version: 25.1.2
3
+ * Version: 25.1.3
4
4
  * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
5
5
  * License: https://www.devexpress.com/Support/EULAs
6
6
  */
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * DevExpress WebRichEdit (index.js)
3
- * Version: 25.1.2
3
+ * Version: 25.1.3
4
4
  * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
5
5
  * License: https://www.devexpress.com/Support/EULAs
6
6
  */
@@ -62,8 +62,8 @@ export class ClientRichEdit {
62
62
  this.rawDataSource = settings.rawDataSource;
63
63
  this.contextMenuSettings = settings.contextMenuSettings;
64
64
  this.fullScreenHelper = new FullScreenHelper(element);
65
- if ("eyJsaWNlbnNlS2V5IjoiZXdvZ0lDSm1iM0p0WVhRaU9pQXhMQW9nSUNKcGJuUmxjbTVoYkZWellXZGxTV1FpT2lBaVJWTTBSVlk0YmxKaVpYVk9OVGRWVEdSbFlVeHhZeUlLZlE9PS5MN1o0YXlNMTRnUWtScExSaEt6MGZSMDU5d1E5cWhhMi9ESThnRG83SEJxbFM2L1BMNVRtTmRrTVRzMmdUL3oyUFVQZDgyZGRMM0dsbjZiQUM0aXB4cUI0Y1ozT1FkZjhVc1pmMm9TOCs5SnliZGdCS1diYnFseXdEMUVFbkwwNmV0eWdtQT09In0=")
66
- config(JSON.parse(atob("eyJsaWNlbnNlS2V5IjoiZXdvZ0lDSm1iM0p0WVhRaU9pQXhMQW9nSUNKcGJuUmxjbTVoYkZWellXZGxTV1FpT2lBaVJWTTBSVlk0YmxKaVpYVk9OVGRWVEdSbFlVeHhZeUlLZlE9PS5MN1o0YXlNMTRnUWtScExSaEt6MGZSMDU5d1E5cWhhMi9ESThnRG83SEJxbFM2L1BMNVRtTmRrTVRzMmdUL3oyUFVQZDgyZGRMM0dsbjZiQUM0aXB4cUI0Y1ozT1FkZjhVc1pmMm9TOCs5SnliZGdCS1diYnFseXdEMUVFbkwwNmV0eWdtQT09In0=")));
65
+ if ("eyJsaWNlbnNlS2V5IjoiZXdvZ0lDSm1iM0p0WVhRaU9pQXhMQW9nSUNKcGJuUmxjbTVoYkZWellXZGxTV1FpT2lBaVZqSlJjRkZ0U2xaWVYzazJUbVY0YTNFNVdHczVieUlLZlE9PS5EMTNKeDFkWmJlWFE0bGVWQ05XZnk5U2FLeWFHbmxMOE1xYkF2YzloQ3FVZTlBajJWYzJUS2RaU01RR05xVkVkSjMrTWZQKzQrQTBqMFhCSGxEczdEV2xpWFlNK01EMEVCaEJVQ0JTVzVmeWRGSzhyOGpEMDRzV2ZKYS9CTDRFTGdLOWZpZz09In0=")
66
+ config(JSON.parse(atob("eyJsaWNlbnNlS2V5IjoiZXdvZ0lDSm1iM0p0WVhRaU9pQXhMQW9nSUNKcGJuUmxjbTVoYkZWellXZGxTV1FpT2lBaVZqSlJjRkZ0U2xaWVYzazJUbVY0YTNFNVdHczVieUlLZlE9PS5EMTNKeDFkWmJlWFE0bGVWQ05XZnk5U2FLeWFHbmxMOE1xYkF2YzloQ3FVZTlBajJWYzJUS2RaU01RR05xVkVkSjMrTWZQKzQrQTBqMFhCSGxEczdEV2xpWFlNK01EMEVCaEJVQ0JTVzVmeWRGSzhyOGpEMDRzV2ZKYS9CTDRFTGdLOWZpZz09In0=")));
67
67
  this.prepareElement(element, settings);
68
68
  this.initDefaultFontsAndStyles();
69
69
  this.initBars(settings.ribbon, settings.fonts);
@@ -441,9 +441,6 @@ export function executeApiCommandCore(commandManager, commandId, parameter) {
441
441
  break;
442
442
  }
443
443
  ;
444
- case ViewTabCommandId.ToggleAllowZoom:
445
- parameter = undefined;
446
- break;
447
444
  case HeaderAndFooterTabCommandId.GoToPageHeader:
448
445
  parameter = undefined;
449
446
  break;
@@ -40,7 +40,7 @@ export function convertToCharacterPropertiesApi(properties, colorProvider) {
40
40
  return value;
41
41
  }
42
42
  export function convertFromCharacterPropertiesApi(properties, fontInfoCache, parameterIndex, setRestAsUndefined, propsCoreTemplate) {
43
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
43
+ var _a, _b, _c, _d, _e, _f, _g, _h;
44
44
  properties = ApiParametersChecker.check(properties, parameterIndex, false, [
45
45
  ApiParametersChecker.objectDescriptor('properties', 'CharacterProperties', (val) => val)
46
46
  ]);
@@ -60,31 +60,27 @@ export function convertFromCharacterPropertiesApi(properties, fontInfoCache, par
60
60
  propsCoreTemplate.fontItalic = (_d = ApiParametersChecker.check(properties.italic, parameterIndex, true, [
61
61
  ApiParametersChecker.booleanDescriptor('properties.italic', (val) => val)
62
62
  ])) !== null && _d !== void 0 ? _d : propsCoreTemplate.fontItalic;
63
- propsCoreTemplate.fontInfo = (_e = ApiParametersChecker.check(properties.fontName, parameterIndex, true, [
64
- ApiParametersChecker.stringDescriptor('properties.fontName', (val) => {
65
- const fontInfo = fontInfoCache.getItemByName(val);
66
- if (!fontInfo)
67
- throw Error('Unknown font name');
68
- return fontInfo;
69
- }, false)
70
- ])) !== null && _e !== void 0 ? _e : propsCoreTemplate.fontInfo;
71
- propsCoreTemplate.fontSize = (_f = ApiParametersChecker.check(properties.size, parameterIndex, true, [
63
+ const fontInfo = ApiParametersChecker.check(properties.fontName, parameterIndex, true, [
64
+ ApiParametersChecker.stringDescriptor('properties.fontName', (value) => fontInfoCache.getItemByName(value), false)
65
+ ]);
66
+ propsCoreTemplate.fontInfo = fontInfo === undefined ? propsCoreTemplate.fontInfo : fontInfo !== null && fontInfo !== void 0 ? fontInfo : fontInfoCache.addFont(properties.fontName, properties.fontName);
67
+ propsCoreTemplate.fontSize = (_e = ApiParametersChecker.check(properties.size, parameterIndex, true, [
72
68
  ApiParametersChecker.numberDescriptor('properties.size', (val) => val, 0, 601)
73
- ])) !== null && _f !== void 0 ? _f : propsCoreTemplate.fontSize;
74
- propsCoreTemplate.hidden = (_g = ApiParametersChecker.check(properties.hidden, parameterIndex, true, [
69
+ ])) !== null && _e !== void 0 ? _e : propsCoreTemplate.fontSize;
70
+ propsCoreTemplate.hidden = (_f = ApiParametersChecker.check(properties.hidden, parameterIndex, true, [
75
71
  ApiParametersChecker.booleanDescriptor('properties.hidden', (val) => val)
76
- ])) !== null && _g !== void 0 ? _g : propsCoreTemplate.hidden;
72
+ ])) !== null && _f !== void 0 ? _f : propsCoreTemplate.hidden;
77
73
  const shadigInfoColor = ApiParametersChecker.check(properties.backColor, parameterIndex, true, ModelParametersChecker.colorDescriptors('properties.backColor'));
78
74
  propsCoreTemplate.shadingInfo = shadigInfoColor === undefined ? propsCoreTemplate.shadingInfo :
79
75
  ShadingInfo.createByColor(ColorModelInfo.makeByColor(shadigInfoColor));
80
- propsCoreTemplate.script = (_h = ApiParametersChecker.check(properties.script, parameterIndex, true, [
76
+ propsCoreTemplate.script = (_g = ApiParametersChecker.check(properties.script, parameterIndex, true, [
81
77
  ApiParametersChecker.enumDescriptor('properties.script', (val) => val, CharacterPropertiesScriptApi, 'CharacterPropertiesScript')
82
- ])) !== null && _h !== void 0 ? _h : propsCoreTemplate.script;
78
+ ])) !== null && _g !== void 0 ? _g : propsCoreTemplate.script;
83
79
  const underlineColor = ApiParametersChecker.check(properties.underlineColor, parameterIndex, true, ModelParametersChecker.colorDescriptors('properties.underlineColor'));
84
80
  propsCoreTemplate.underlineColor = underlineColor === undefined ? propsCoreTemplate.underlineColor : ColorModelInfo.makeByColor(underlineColor);
85
- propsCoreTemplate.underlineWordsOnly = (_j = ApiParametersChecker.check(properties.underlineWordsOnly, parameterIndex, true, [
81
+ propsCoreTemplate.underlineWordsOnly = (_h = ApiParametersChecker.check(properties.underlineWordsOnly, parameterIndex, true, [
86
82
  ApiParametersChecker.booleanDescriptor('properties.underlineWordsOnly', (val) => val)
87
- ])) !== null && _j !== void 0 ? _j : propsCoreTemplate.underlineWordsOnly;
83
+ ])) !== null && _h !== void 0 ? _h : propsCoreTemplate.underlineWordsOnly;
88
84
  const strikeout = ApiParametersChecker.check(properties.strikeout, parameterIndex, true, [
89
85
  ApiParametersChecker.booleanDescriptor('properties.strikeout', (val) => val)
90
86
  ]);
@@ -7,6 +7,7 @@ import { HyperlinkCollection } from './collections/hyperlink-collection';
7
7
  import { ListCollection } from './collections/numbered-list-collection';
8
8
  import { SectionCollection } from './collections/section-collection';
9
9
  import { SubDocumentCollection as SubDocumentCollection } from './collections/sub-documents-collection';
10
+ import { FontCorrector } from '../../common/model/creator/font-corrector';
10
11
  export class RichEditDocumentApi {
11
12
  constructor(processor) {
12
13
  this._processor = processor;
@@ -105,6 +106,7 @@ export class RichEditDocumentApi {
105
106
  this._processor.modelManager.model.defaultCharacterProperties =
106
107
  this._processor.modelManager.model.cache.maskedCharacterPropertiesCache.getItem(propertiesCore);
107
108
  NumberMapUtils.forEach(this._processor.modelManager.model.subDocuments, (sd) => sd.resetMergedFormattingCache(ResetFormattingCacheType.All));
109
+ new FontCorrector(this._processor.modelManager.modelManipulator, this._processor.modelManager.model, this._processor.modelManager.richOptions.fonts).correct();
108
110
  this._processor.layoutFormatterManager.restartManager.restartAllLayout();
109
111
  this._processor.endUpdate();
110
112
  }
@@ -197,7 +197,7 @@ export class ImagesApi {
197
197
  applyVerticalPosition(verticalPosition, anchorInfo);
198
198
  const anchorPictureInfo = new AnchorPictureInfo(new PictureSize(true, 0, cacheInfo, new Size(100, 100)), shape, anchorInfo, new NonVisualDrawingObjectInfo(), new NonVisualDrawingObjectInfo());
199
199
  anchorPictureInfo.containerProperties.description = options.description;
200
- this._processor.modelManager.modelManipulator.picture.insertAnchoredPictureViaHistory(new SubDocumentPosition(this._subDocument, position), inputPos.charPropsBundle, anchorPictureInfo, new ImageLoadingOptions(false, size ? new Size(size.width, size.height) : undefined, (_picInterval, _cacheInfo) => setTimeout(() => {
200
+ this._processor.modelManager.modelManipulator.picture.insertAnchoredPictureViaHistory(new SubDocumentPosition(this._subDocument, position), inputPos.charPropsBundle, anchorPictureInfo, ImageLoadingOptions.initByActualSize(size ? new Size(size.width, size.height) : undefined, (_picInterval, _cacheInfo) => setTimeout(() => {
201
201
  callback(getFloatingImageApiFromRun(this._processor, this._subDocument, this._subDocument.getRunAndIndexesByPosition(position)));
202
202
  }, 0)));
203
203
  this._processor.endUpdate();
@@ -150,8 +150,7 @@ export declare enum ViewTabCommandId {
150
150
  SwitchToPrintLayout = 406,
151
151
  ToggleShowHorizontalRuler = 94,
152
152
  ToggleFullScreen = 98,
153
- ChangeZoomLevel = 460,
154
- ToggleAllowZoom = 461
153
+ ChangeZoomLevel = 460
155
154
  }
156
155
  export declare enum HeaderAndFooterTabCommandId {
157
156
  GoToPageHeader = 227,
@@ -158,7 +158,6 @@ export var ViewTabCommandId;
158
158
  ViewTabCommandId[ViewTabCommandId["ToggleShowHorizontalRuler"] = 94] = "ToggleShowHorizontalRuler";
159
159
  ViewTabCommandId[ViewTabCommandId["ToggleFullScreen"] = 98] = "ToggleFullScreen";
160
160
  ViewTabCommandId[ViewTabCommandId["ChangeZoomLevel"] = 460] = "ChangeZoomLevel";
161
- ViewTabCommandId[ViewTabCommandId["ToggleAllowZoom"] = 461] = "ToggleAllowZoom";
162
161
  })(ViewTabCommandId || (ViewTabCommandId = {}));
163
162
  export var HeaderAndFooterTabCommandId;
164
163
  (function (HeaderAndFooterTabCommandId) {
@@ -158,6 +158,7 @@ export interface IRichEditFontsSettings {
158
158
  export interface IFontSettings {
159
159
  name: string;
160
160
  fontFamily: string;
161
+ useGoogleFonts?: boolean;
161
162
  italicFontUri?: string;
162
163
  boldFontUri?: string;
163
164
  boldItalicFontUri?: string;
@@ -1,3 +1,4 @@
1
+ var _a;
1
2
  export class FocusHelper {
2
3
  static preventFocusOnClick(element) {
3
4
  return new FocusBlocker(element);
@@ -10,23 +11,24 @@ class FocusBlocker {
10
11
  this.addEventListeners(target);
11
12
  }
12
13
  addEventListeners(element) {
13
- element.addEventListener("pointerdown", this.onPointerDownBinded);
14
+ element.addEventListener("mousedown", this.onPointerDownBinded);
14
15
  }
15
16
  removeEventListeners(element) {
16
- element.removeEventListener("pointerdown", this.onPointerDownBinded);
17
+ element.removeEventListener("mousedown", this.onPointerDownBinded);
17
18
  }
18
19
  onPointerDown(event) {
19
20
  for (const element of event.composedPath()) {
20
- if (!(element instanceof HTMLElement))
21
- continue;
22
21
  if (element === this.target) {
23
22
  event.preventDefault();
24
23
  break;
25
24
  }
26
- if (!this.target.contains(element) || element.tabIndex > -1)
25
+ if (element instanceof Element && this.isFocusableElement(element))
27
26
  break;
28
27
  }
29
28
  }
29
+ isFocusableElement(element) {
30
+ return element.matches(FocusBlocker.focusableSelector);
31
+ }
30
32
  dispose() {
31
33
  if (this.target) {
32
34
  this.removeEventListeners(this.target);
@@ -34,3 +36,18 @@ class FocusBlocker {
34
36
  }
35
37
  }
36
38
  }
39
+ _a = FocusBlocker;
40
+ FocusBlocker.focusableSelectors = [
41
+ 'a[href]',
42
+ 'area[href]',
43
+ 'input',
44
+ 'select',
45
+ 'textarea',
46
+ 'button',
47
+ 'iframe',
48
+ 'object',
49
+ 'embed',
50
+ '[tabindex]:not([tabindex="-1"])',
51
+ '[contenteditable]:not([contenteditable="false"])'
52
+ ];
53
+ FocusBlocker.focusableSelector = _a.focusableSelectors.join(',');
@@ -254,7 +254,7 @@ export class CanvasManager extends BatchUpdatableObject {
254
254
  const canvasX = MixedSize.fromUI(DomUtils.getAbsolutePositionX(canvas));
255
255
  const canvasY = MixedSize.fromUI(DomUtils.getAbsolutePositionY(canvas));
256
256
  const offsetY = MixedSize.fromUI(canvas.scrollTop).addSize(clientY).subtractSize(canvasY).useScale(scaleY);
257
- const pageIndex = this.viewManager.layout.findPageIndexByOffsetY(offsetY.LayoutSize, this.sizes);
257
+ const pageIndex = this.viewManager.layout.findPageIndexByOffsetY(offsetY.LayoutSize * scaleY, this.sizes);
258
258
  const visibleAreaWidth = MixedSize.fromUI(this.sizes.getVisibleAreaWidth(false));
259
259
  const visibleAreaHeight = MixedSize.fromUI(this.sizes.getVisibleAreaHeight(false));
260
260
  if (checkScroll) {
@@ -15,6 +15,7 @@ export declare class CanvasSizeInfo implements IControlHeightProvider {
15
15
  isInitialized(): boolean;
16
16
  initialize(page: HTMLElement, canvas: HTMLDivElement): void;
17
17
  getPageOffsetY(layoutPage: LayoutPage): number;
18
+ get zoomLevel(): number;
18
19
  private setVisibleAreaSize;
19
20
  getVisibleAreaWidth(includeScrollBars: boolean): number;
20
21
  getVisibleAreaHeight(includeScrollBars: boolean): number;
@@ -22,9 +22,9 @@ export class CanvasSizeInfo {
22
22
  this.setVisibleAreaSize(SizeUtils.getClientWidth(canvas), SizeUtils.getClientHeight(canvas));
23
23
  }
24
24
  getPageOffsetY(layoutPage) {
25
- const pageOffsetY = layoutPage.y + (this.topSpacing + layoutPage.index * this.betweenPageSpacing);
26
- return pageOffsetY * this.zoomLevelHolder.zoomLevel;
25
+ return layoutPage.y + (this.topSpacing + layoutPage.index * this.betweenPageSpacing);
27
26
  }
27
+ get zoomLevel() { return this.zoomLevelHolder.zoomLevel; }
28
28
  setVisibleAreaSize(width, height) {
29
29
  this.visibleAreaSize.width = width;
30
30
  this.visibleAreaSize.height = height;
@@ -28,6 +28,7 @@ import { ControlOptions, DocumentCapability } from '../../model/options/control'
28
28
  import { RichEditClientCommand } from '../../commands/client-command';
29
29
  import { ZoomLevelChange } from '../../model/changes/model/zoom-level';
30
30
  import { ModelChangeType } from '../../model/changes/enums';
31
+ import { MixedSize } from '../../../common/utils/mixed-size';
31
32
  export class ViewManager {
32
33
  get renderer() { return this.renderers[this.innerClientProperties.viewsSettings.viewType]; }
33
34
  get printLayoutRenderer() { return this.renderers[ViewType.PrintLayout]; }
@@ -113,9 +114,9 @@ export class ViewManager {
113
114
  const pageInfo = layoutSelection.selectionInfo.pageInfos[pageIndex];
114
115
  const item = pageInfo.oldItems[0];
115
116
  const layoutPage = this.layout.pages[pageIndex];
116
- const x = layoutPage.x + this.cache[pageIndex].page.offsetLeft + item.x;
117
- const y = this.sizes.getPageOffsetY(layoutPage) + item.y;
118
- this.inputController.setPosition(x, y);
117
+ const x = MixedSize.fromLayout(layoutPage.x + this.cache[pageIndex].page.offsetLeft + item.x).useScale(this.zoomLevel);
118
+ const y = MixedSize.fromLayout(this.sizes.getPageOffsetY(layoutPage) + item.y).useScale(this.zoomLevel);
119
+ this.inputController.setPosition(x.UISize, y.UISize);
119
120
  }
120
121
  }
121
122
  NotifySearchSelectionLayoutChanged() {
@@ -420,6 +420,5 @@ export declare enum RichEditClientCommand {
420
420
  NoSpellingSuggestions = 457,
421
421
  GetHtml = 458,
422
422
  CreateEmptyIfField = 459,
423
- ChangeZoomLevel = 460,
424
- ToggleAllowZoom = 461
423
+ ChangeZoomLevel = 460
425
424
  }
@@ -422,5 +422,4 @@ export var RichEditClientCommand;
422
422
  RichEditClientCommand[RichEditClientCommand["GetHtml"] = 458] = "GetHtml";
423
423
  RichEditClientCommand[RichEditClientCommand["CreateEmptyIfField"] = 459] = "CreateEmptyIfField";
424
424
  RichEditClientCommand[RichEditClientCommand["ChangeZoomLevel"] = 460] = "ChangeZoomLevel";
425
- RichEditClientCommand[RichEditClientCommand["ToggleAllowZoom"] = 461] = "ToggleAllowZoom";
426
425
  })(RichEditClientCommand || (RichEditClientCommand = {}));
@@ -67,7 +67,6 @@ import { GoToNextHeaderFooterCommand, GoToPreviousHeaderFooterCommand } from './
67
67
  import { InsertFooterCommand, InsertHeaderCommand } from './header-footer/insert-header-footer-commands';
68
68
  import { LinkHeaderFooterToPreviousCommand } from './header-footer/link-header-footer-commands';
69
69
  import { ApplyStyleCommand } from './layout/apply-style-command';
70
- import { ToggleAllowZoomCommand } from './layout/toggle-allow-zoom-command';
71
70
  import { ChangeZoomLevelCommand } from './layout/change-zoom-level-command';
72
71
  import { ClearFormattingCommand } from './layout/clear-formatting-command';
73
72
  import { ChangeViewTypeCommand, SwitchToPrintLayoutViewCommand, SwitchToSimpleViewCommand } from './layout/switch-view-command';
@@ -558,7 +557,6 @@ export class CommandManager {
558
557
  this.createCommand(control, RichEditClientCommand.SwitchToSimpleView, SwitchToSimpleViewCommand);
559
558
  this.createCommand(control, RichEditClientCommand.SwitchToPrintLayoutView, SwitchToPrintLayoutViewCommand);
560
559
  this.createCommand(control, RichEditClientCommand.ChangeZoomLevel, ChangeZoomLevelCommand);
561
- this.createCommand(control, RichEditClientCommand.ToggleAllowZoom, ToggleAllowZoomCommand);
562
560
  this.createCommand(control, RichEditClientCommand.ShowErrorLoadPictureMessage, ShowLoadPictureErrorDialogCommand);
563
561
  this.assingCommand(RichEditClientCommand.PrintDocumentOnClient, new PrintDocumentOnClient(control, printNonce));
564
562
  }
@@ -13,6 +13,8 @@ export declare class PrintDocumentOnClient extends CommandBase<SimpleCommandStat
13
13
  executeCore(_state: SimpleCommandState, options: CommandSimpleOptions<PrintMode | PrintingSettings | undefined>): boolean;
14
14
  private printCore;
15
15
  private generatePrintDocument;
16
+ private getGoogleFonts;
17
+ private createGoogleFontStyleLink;
16
18
  private generatePrintContent;
17
19
  private createZIndexStyles;
18
20
  }
@@ -80,8 +80,18 @@ export class PrintDocumentOnClient extends CommandBase {
80
80
  return true;
81
81
  }
82
82
  printCore(htmlPrinting, printWindow, closePrintDialogWithHtmlPreview, needSwitchViewType, needToggleHiddenSymbols) {
83
- if (htmlPrinting)
84
- this.generatePrintDocument(printWindow, closePrintDialogWithHtmlPreview);
83
+ if (htmlPrinting) {
84
+ this.generatePrintDocument(printWindow.document);
85
+ printWindow.focus();
86
+ const interval = setInterval(() => {
87
+ if (printWindow.document.readyState == 'complete') {
88
+ printWindow.print();
89
+ if (closePrintDialogWithHtmlPreview && !Browser.AndroidMobilePlatform)
90
+ printWindow.close();
91
+ clearInterval(interval);
92
+ }
93
+ }, 100);
94
+ }
85
95
  else {
86
96
  pdfExport(this.control, (blob, _stream) => {
87
97
  if (window.navigator.msSaveOrOpenBlob && !Browser.Edge)
@@ -96,12 +106,27 @@ export class PrintDocumentOnClient extends CommandBase {
96
106
  this.control.commandManager.getCommand(RichEditClientCommand.ToggleShowWhitespace).execute(this.control.commandManager.isPublicApiCall);
97
107
  this.control.commandManager.isPrintingProcessing = false;
98
108
  }
99
- generatePrintDocument(printWindow, closePrintDialogWithHtmlPreview) {
109
+ generatePrintDocument(document) {
100
110
  const height = this.control.layout.pages[0].height;
101
111
  const width = this.control.layout.pages[0].width;
102
- let printWindowContent = `<!DOCTYPE html>
103
- <html moznomarginboxes mozdisallowselectionprint>
112
+ let fontLink = "";
113
+ let divsToLoadFonts = "";
114
+ const googleFonts = this.getGoogleFonts();
115
+ if (googleFonts.length > 0) {
116
+ fontLink = this.createGoogleFontStyleLink(googleFonts);
117
+ divsToLoadFonts = googleFonts.reduce((prev, curr) => {
118
+ const fontStyles = [`font-family:${curr}`, 'font-weight:bold', 'font-style:italic'];
119
+ const result = [];
120
+ for (let i = 1; i <= fontStyles.length; i++)
121
+ result.push(`<div style="font-size:1pt;position:absolute;top:-1000px;${fontStyles.slice(0, i).join(';')}">${curr}</div>`);
122
+ return prev ? [prev, ...result].join('\n') : result.join('\n');
123
+ }, null);
124
+ }
125
+ document.documentElement.innerHTML =
126
+ `<!DOCTYPE html>
127
+ <html moznomarginboxes mozdisallowselectionprint>
104
128
  <head>
129
+ ${fontLink}
105
130
  <style ${this._nonce ? `nonce="${this._nonce}"` : ''}>
106
131
  html, body {
107
132
  margin: 0;
@@ -120,22 +145,25 @@ export class PrintDocumentOnClient extends CommandBase {
120
145
  </style>
121
146
  </head>
122
147
  <body>
148
+ ${divsToLoadFonts}
123
149
  </body>
124
- </html>`;
125
- printWindow.document.write(printWindowContent);
126
- printWindow.document.close();
150
+ </html>`;
127
151
  this.generatePrintContent().forEach((child) => {
128
- printWindow.document.body.appendChild(child);
152
+ document.body.appendChild(child);
129
153
  });
130
- printWindow.focus();
131
- const interval = setInterval(() => {
132
- if (printWindow.document.readyState == 'complete') {
133
- printWindow.print();
134
- if (closePrintDialogWithHtmlPreview && !Browser.AndroidMobilePlatform)
135
- printWindow.close();
136
- clearInterval(interval);
137
- }
138
- }, 100);
154
+ }
155
+ getGoogleFonts() {
156
+ return this.control.modelManager.richOptions.fonts.fonts.reduce((res, f) => {
157
+ if (f.useGoogleFonts)
158
+ res.push(f.fontFamily);
159
+ return res;
160
+ }, []);
161
+ }
162
+ createGoogleFontStyleLink(fontFamilies) {
163
+ const url = new URL('https://fonts.googleapis.com/css');
164
+ url.searchParams.append('family', fontFamilies.join('|'));
165
+ url.searchParams.append('display', 'auto');
166
+ return `<link href="${url.toString()}" rel="stylesheet" />`;
139
167
  }
140
168
  generatePrintContent() {
141
169
  const layout = this.control.layout;
@@ -6,7 +6,7 @@ import { CommandBase, CommandSimpleOptions } from '../command-base';
6
6
  import { ApplyStyleCommandState } from '../command-states';
7
7
  export interface IApplyStyleCommandParams {
8
8
  styleName: string;
9
- keepDirectFormatting?: boolean;
9
+ keepCustomFormatting?: boolean;
10
10
  }
11
11
  export declare class ApplyStyleCommand extends CommandBase<ApplyStyleCommandState> {
12
12
  getState(): ApplyStyleCommandState;
@@ -14,7 +14,7 @@ export declare class ApplyStyleCommand extends CommandBase<ApplyStyleCommandStat
14
14
  DEPRECATEDConvertOptionsParameter(parameter: string | IApplyStyleCommandParams): IApplyStyleCommandParams;
15
15
  executeCore(state: ApplyStyleCommandState, options: CommandSimpleOptions<IApplyStyleCommandParams>): boolean;
16
16
  applyCharacterStyle(subDocumentInterval: SubDocumentInterval, style: CharacterStyle, isPresetStyle: boolean): void;
17
- applyParagraphStyle(subDocumentInterval: SubDocumentInterval, style: ParagraphStyle, isPresetStyle: boolean, keepDirectFormatting?: boolean): void;
17
+ applyParagraphStyle(subDocumentInterval: SubDocumentInterval, style: ParagraphStyle, isPresetStyle: boolean, keepCustomFormatting?: boolean): void;
18
18
  applyParagraphLinkedStyle(subDocumentInterval: SubDocumentInterval, style: ParagraphStyle, isPresetStyle: boolean): void;
19
19
  private addLinkedCharacterStyle;
20
20
  calculateAffectedParagraphCount(subDocumentInterval: SubDocumentInterval): number;
@@ -70,7 +70,7 @@ export class ApplyStyleCommand extends CommandBase {
70
70
  paragraphStyle = StylesManager.getPresetParagraphStyleByName(styleName).clone();
71
71
  isPresetStyle = true;
72
72
  }
73
- this.applyParagraphStyle(subDocumentInterval, paragraphStyle, isPresetStyle, parameter.keepDirectFormatting);
73
+ this.applyParagraphStyle(subDocumentInterval, paragraphStyle, isPresetStyle, parameter.keepCustomFormatting);
74
74
  }
75
75
  else if (!StylesManager.isParagraphStyle(parameter.styleName) && state.characterStyleChangeEnabled) {
76
76
  const styleName = StylesManager.getStyleNameWithoutPrefix(parameter.styleName);
@@ -105,7 +105,7 @@ export class ApplyStyleCommand extends CommandBase {
105
105
  this.modelManipulator.style.applyCharacterStyle(subDocumentInterval, characterStyle, false);
106
106
  }
107
107
  }
108
- applyParagraphStyle(subDocumentInterval, style, isPresetStyle, keepDirectFormatting = false) {
108
+ applyParagraphStyle(subDocumentInterval, style, isPresetStyle, keepCustomFormatting = false) {
109
109
  const count = this.calculateAffectedParagraphCount(subDocumentInterval);
110
110
  if (count > 0 && ControlOptions.isEnabled(this.control.modelManager.richOptions.control.paragraphStyle)) {
111
111
  const { interval, subDocument } = subDocumentInterval;
@@ -118,8 +118,7 @@ export class ApplyStyleCommand extends CommandBase {
118
118
  style = isPresetStyle ? modelManipulator.model.stylesManager.addParagraphStyle(style) : style;
119
119
  this.history.addAndRedo(new ApplyParagraphStyleHistoryItem(modelManipulator, paragraphSubDocumentInterval, style));
120
120
  this.history.addAndRedo(new ParagraphUseValueHistoryItem(modelManipulator, paragraphSubDocumentInterval, 0));
121
- if (!keepDirectFormatting)
122
- this.history.addAndRedo(new FontUseValueHistoryItem(modelManipulator, paragraphSubDocumentInterval, 0));
121
+ this.history.addAndRedo(new FontUseValueHistoryItem(modelManipulator, paragraphSubDocumentInterval, 0, keepCustomFormatting));
123
122
  this.history.addAndRedo(new AddParagraphToListHistoryItem(modelManipulator, subDocument, paragraphIndex, NumberingList.NumberingListNotSettedIndex, -1));
124
123
  }
125
124
  }
@@ -22,7 +22,7 @@ export class SetParagraphLevelCommandBase extends CommandBase {
22
22
  if (!paragraphStyle)
23
23
  paragraphStyle = StylesManager.getPresetParagraphStyleByName(styleName);
24
24
  if (paragraphStyle) {
25
- const commandOptions = new CommandSimpleOptions(this.control, { styleName: StylesManager.paragraphPrefix + styleName, keepDirectFormatting: true });
25
+ const commandOptions = new CommandSimpleOptions(this.control, { styleName: StylesManager.paragraphPrefix + styleName, keepCustomFormatting: true });
26
26
  this.commandManager.getCommand(RichEditClientCommand.ChangeStyle).execute(this.commandManager.isPublicApiCall, commandOptions);
27
27
  }
28
28
  else {
@@ -722,7 +722,7 @@ export class IFrameInputEditor extends InputEditorBase {
722
722
  const propChar = HtmlConverter.getSizeSignificantRules(this.control.inputPosition.getMergedCharacterPropertiesRaw()).join(";");
723
723
  this.editableDocument.body.style.cssText = "padding: 0px; margin: 0px; overflow: hidden; color: transparent; " + propChar;
724
724
  this.editableDocument.body.style.textIndent = currentTextIndent;
725
- if (Browser.Firefox) {
725
+ if (Browser.Firefox && Browser.Version <= 137) {
726
726
  this.editableDocument.body.style.zoom = this.control.viewManager.zoomLevel;
727
727
  }
728
728
  let layoutX = layoutPosition.getLayoutX(this.control.measurer, DocumentLayoutDetailsLevel.Row);
@@ -1,6 +1,7 @@
1
1
  import { NumberMapUtils } from '@devexpress/utils/lib/utils/map/number';
2
2
  import { ColorHelper } from '../model/color/color';
3
3
  import { SearchUtils } from '@devexpress/utils/lib/utils/search';
4
+ import { MixedSize } from '../utils/mixed-size';
4
5
  export class ModelPositionHolder {
5
6
  constructor(pos, posManager) {
6
7
  this.pos = posManager.registerPosition(pos);
@@ -66,6 +67,8 @@ export class DocumentLayout {
66
67
  return this.pages.find((page) => !!page.mainSubDocumentPageAreas[subDocumentId] || !!page.otherPageAreas[subDocumentId]);
67
68
  }
68
69
  findPageIndexByOffsetY(offsetY, sizeInfo) {
69
- return Math.max(0, SearchUtils.normedInterpolationIndexOf(this.pages, (p) => sizeInfo.getPageOffsetY(p), offsetY));
70
+ const getPageOffsetY = (p) => MixedSize.fromLayout(sizeInfo.getPageOffsetY(p)).useScale(sizeInfo.zoomLevel).UISize;
71
+ const normedInterpolationIndex = SearchUtils.normedInterpolationIndexOf(this.pages, getPageOffsetY, offsetY);
72
+ return Math.max(0, normedInterpolationIndex);
70
73
  }
71
74
  }
@@ -25,7 +25,7 @@ export class WordHolderInfo {
25
25
  }
26
26
  if (res == null)
27
27
  return false;
28
- if (this.rowFormatter.row.isEmpty()) {
28
+ if (this.rowFormatter.row.isEmpty() || this.rowFormatter.row.containsSpacesOnly()) {
29
29
  if (this.rowFormatter.rowSizesManager.rowFormattingInfo.isFloatingIntersectRow) {
30
30
  this.rowFormatter.rowSizesManager.rowFormattingInfo.findNextYPosWhatHasNeededSpace(res.requiredWidth);
31
31
  return this.pushBoxes();
@@ -5,7 +5,7 @@ import { BorderLineStyle } from './enums';
5
5
  import { LayoutBorder } from './layout-border';
6
6
  export class BorderInfo {
7
7
  constructor() {
8
- this.style = BorderLineStyle.None;
8
+ this.style = BorderLineStyle.Nil;
9
9
  this.color = ColorModelInfoCache.defaultItem;
10
10
  this.width = 0;
11
11
  this.offset = 0;
@@ -8,12 +8,15 @@ export declare class CacheImageInfo {
8
8
  private _convertedBase64?;
9
9
  private _size?;
10
10
  private _isLoaded;
11
+ private _isSizeDefined;
11
12
  tmpId?: number;
12
13
  actualId?: number;
13
14
  imageUrl?: string;
14
15
  file?: File;
15
16
  get isLoaded(): boolean;
16
17
  set isLoaded(val: boolean);
18
+ get isSizeDefined(): boolean;
19
+ set isSizeDefined(val: boolean);
17
20
  get size(): Size;
18
21
  set size(val: Size);
19
22
  get currId(): number;
@@ -22,7 +25,7 @@ export declare class CacheImageInfo {
22
25
  get pdfCompatibleBase64(): string | undefined;
23
26
  get referenceInfo(): CacheImageInfo | undefined;
24
27
  set referenceInfo(val: CacheImageInfo | undefined);
25
- constructor(base64?: string, actualId?: number, tmpId?: number, imageUrl?: string, file?: File, referenceInfo?: CacheImageInfo, size?: Size, isLoaded?: boolean);
28
+ constructor(base64?: string, actualId?: number, tmpId?: number, imageUrl?: string, file?: File, referenceInfo?: CacheImageInfo, size?: Size, isLoaded?: boolean, isActualSize?: boolean);
26
29
  equals(obj: CacheImageInfo): boolean;
27
30
  clone(): CacheImageInfo;
28
31
  shouldMakeImagePdfCompatible(): boolean;
@@ -7,6 +7,8 @@ export class CacheImageInfo {
7
7
  static get emptyPictureSize() { return new Size(CacheImageInfo.emptyPicDimension, CacheImageInfo.emptyPicDimension); }
8
8
  get isLoaded() { return this._referenceInfo ? this._referenceInfo._isLoaded : this._isLoaded; }
9
9
  set isLoaded(val) { this._isLoaded = val; }
10
+ get isSizeDefined() { return this._referenceInfo ? this._referenceInfo._isSizeDefined : this._isSizeDefined; }
11
+ set isSizeDefined(val) { this._isSizeDefined = val; }
10
12
  get size() { return this._referenceInfo ? this._referenceInfo._size : this._size; }
11
13
  set size(val) { this._size = val; }
12
14
  get currId() { return this.actualId !== undefined ? this.actualId : this.tmpId; }
@@ -19,15 +21,17 @@ export class CacheImageInfo {
19
21
  this._base64 = undefined;
20
22
  this._size = undefined;
21
23
  this._isLoaded = undefined;
24
+ this._isSizeDefined = undefined;
22
25
  this.file = undefined;
23
26
  }
24
- constructor(base64, actualId, tmpId, imageUrl, file, referenceInfo, size, isLoaded) {
27
+ constructor(base64, actualId, tmpId, imageUrl, file, referenceInfo, size, isLoaded, isActualSize) {
25
28
  this._base64 = base64 !== undefined ? Base64Utils.normalizeToDataUrl(base64, "image/png") : undefined;
26
29
  this.actualId = actualId;
27
30
  this.tmpId = tmpId;
28
31
  this._referenceInfo = referenceInfo;
29
32
  this._size = size ? size : CacheImageInfo.emptyPictureSize;
30
33
  this._isLoaded = isLoaded !== undefined ? isLoaded : false;
34
+ this._isSizeDefined = isActualSize ? isActualSize : !!size;
31
35
  this.imageUrl = imageUrl;
32
36
  this.file = file;
33
37
  }
@@ -41,7 +45,7 @@ export class CacheImageInfo {
41
45
  this.size.equals(obj.size);
42
46
  }
43
47
  clone() {
44
- return new CacheImageInfo(this._base64, this.actualId, this.tmpId, this.imageUrl, this.file, this._referenceInfo, this._size, this._isLoaded);
48
+ return new CacheImageInfo(this._base64, this.actualId, this.tmpId, this.imageUrl, this.file, this._referenceInfo, this._size, this._isLoaded, this._isSizeDefined);
45
49
  }
46
50
  shouldMakeImagePdfCompatible() {
47
51
  if (isDefined(this._convertedBase64))
@@ -54,7 +54,7 @@ export declare class MaskedCharacterProperties extends CharacterProperties imple
54
54
  protected calculateHash(): number;
55
55
  getUseValue(value: CharacterPropertiesMask): boolean;
56
56
  setUseValue(mask: CharacterPropertiesMask, value: boolean): void;
57
- setUseValueFull(value: number): void;
57
+ setUseValueFull(value: number, onlyForDefault?: boolean): void;
58
58
  getLowPartUseValue(value: number): number;
59
59
  getHighPartUseValue(value: number): number;
60
60
  getUseValueFull(): number;
@@ -5,6 +5,7 @@ import { ColorHelper } from '../color/color';
5
5
  import { ColorModelInfo } from '../color/color-model-info';
6
6
  import { ShadingInfo } from '../shadings/shading-info';
7
7
  import { ShadingPattern } from '../shadings/shading-pattern';
8
+ import { CharacterPropertyDescriptor } from './character-property-descriptor';
8
9
  import { CompositeFontInfo } from './composite-font-info';
9
10
  import { CharacterFormattingScript, CharacterPropertiesMask, StrikeoutType, UnderlineType } from './enums';
10
11
  import { LangInfo } from './lang-info';
@@ -143,8 +144,19 @@ export class MaskedCharacterProperties extends CharacterProperties {
143
144
  this.useValueExt &= ~this.getHighPartUseValue(mask);
144
145
  }
145
146
  }
146
- setUseValueFull(value) {
147
- this.useValue = this.getLowPartUseValue(value);
147
+ setUseValueFull(value, onlyForDefault = false) {
148
+ const lowPartUseValue = this.getLowPartUseValue(value);
149
+ if (onlyForDefault) {
150
+ CharacterPropertyDescriptor.ALL_FIELDS.forEach((desc) => {
151
+ const prop = desc.getProp(this);
152
+ const mask = desc.maskValue();
153
+ if (desc.binaryEquals(prop, desc.defaultValue))
154
+ this.setUseValue(mask, !!(mask & lowPartUseValue));
155
+ });
156
+ }
157
+ else {
158
+ this.useValue = lowPartUseValue;
159
+ }
148
160
  this.useValueExt = this.getHighPartUseValue(value);
149
161
  }
150
162
  getLowPartUseValue(value) {
@@ -99,7 +99,7 @@ export declare class Field {
99
99
  static correctIntervalDueToFieldsWithoutUiChecks(subDocument: SubDocument, newInterval: FixedInterval): FixedInterval;
100
100
  private static correctIntervalDueToFieldsCaseSelectionCollapsed;
101
101
  static correctIntervalDueToFields(subDocument: SubDocument, newInterval: FixedInterval): number;
102
- private static isFloatingObjectSelected;
102
+ private static isResizableObjectSelected;
103
103
  static correctWhenPositionInStartCode(fields: Field[], position: number): number;
104
104
  clone(subDocument: SubDocument): Field;
105
105
  }