devexpress-richedit 24.1.6-build-24246-0102 → 24.1.6

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.
@@ -53,8 +53,8 @@ export class ClientRichEdit {
53
53
  this.rawDataSource = settings.rawDataSource;
54
54
  this.contextMenuSettings = settings.contextMenuSettings;
55
55
  this.fullScreenHelper = new FullScreenHelper(element);
56
- if ("eyJsaWNlbnNlS2V5IjoiZXdvZ0lDSm1iM0p0WVhRaU9pQXhMQW9nSUNKcGJuUmxjbTVoYkZWellXZGxTV1FpT2lBaWExcHBaR1pSWjA1WGEyVkxaVmx6U2tJNFdHcFhaeUlLZlE9PS5mL01XY3Z5bDUyTFJMRWlMaEVyYnF1eW5yQ3FEQjdvZ0U1QVgxcGdpMXduSW9sT1MySFluNjBWeDBTb0VJVVpEUGhIRlBSQkdpSzg2cFA1K0xjMG56dUd6RFpEZkVUUS9CeklldjJoNTYzdWc2SzlKMCswMER0eTlvVW1GU2xvRTl6WTdQZz09In0=")
57
- config(JSON.parse(atob("eyJsaWNlbnNlS2V5IjoiZXdvZ0lDSm1iM0p0WVhRaU9pQXhMQW9nSUNKcGJuUmxjbTVoYkZWellXZGxTV1FpT2lBaWExcHBaR1pSWjA1WGEyVkxaVmx6U2tJNFdHcFhaeUlLZlE9PS5mL01XY3Z5bDUyTFJMRWlMaEVyYnF1eW5yQ3FEQjdvZ0U1QVgxcGdpMXduSW9sT1MySFluNjBWeDBTb0VJVVpEUGhIRlBSQkdpSzg2cFA1K0xjMG56dUd6RFpEZkVUUS9CeklldjJoNTYzdWc2SzlKMCswMER0eTlvVW1GU2xvRTl6WTdQZz09In0=")));
56
+ if ("eyJsaWNlbnNlS2V5IjoiZXdvZ0lDSm1iM0p0WVhRaU9pQXhMQW9nSUNKcGJuUmxjbTVoYkZWellXZGxTV1FpT2lBaWNIQktkR3hUTlRaeU1HRjZNV3R4VldwWFNuTXRaeUlLZlE9PS5GSzV0WCtSUkt0akY2Q2NwaExOa0R2V0RCTHVkb0ZrdTN3LzJEMGMxRVlWMXp4KzJEYURkYnA0MGtPbXpKTnBRMXB0TUpiT1NTUm1JVmJaSU5VejRINDE3ejZMTDF4cDRZdWpyL2hQU3RiZlNodkNJMGFmemN4TzhXL1ZaVUJUR2gyZUh6UT09In0=")
57
+ config(JSON.parse(atob("eyJsaWNlbnNlS2V5IjoiZXdvZ0lDSm1iM0p0WVhRaU9pQXhMQW9nSUNKcGJuUmxjbTVoYkZWellXZGxTV1FpT2lBaWNIQktkR3hUTlRaeU1HRjZNV3R4VldwWFNuTXRaeUlLZlE9PS5GSzV0WCtSUkt0akY2Q2NwaExOa0R2V0RCTHVkb0ZrdTN3LzJEMGMxRVlWMXp4KzJEYURkYnA0MGtPbXpKTnBRMXB0TUpiT1NTUm1JVmJaSU5VejRINDE3ejZMTDF4cDRZdWpyL2hQU3RiZlNodkNJMGFmemN4TzhXL1ZaVUJUR2gyZUh6UT09In0=")));
58
58
  this.prepareElement(element, settings);
59
59
  this.initDefaultFontsAndStyles();
60
60
  this.initBars(settings.ribbon, settings.fonts);
@@ -80,6 +80,8 @@ export interface IRichEditFieldsSettings {
80
80
  defaultDateFormat?: string;
81
81
  openHyperlinkOnClick?: boolean;
82
82
  keepHyperlinkResultForInvalidReference?: boolean;
83
+ disableRelativeHyperlinkUri?: boolean;
84
+ allowedHyperlinkUriProtocols?: string[];
83
85
  createHyperlinkTooltip?: (hyperlinkTooltip: string, hint: string) => string;
84
86
  }
85
87
  export interface IRichEditRangePermissionsSettings {
@@ -93,6 +93,8 @@ export interface IFieldsSettings {
93
93
  defaultDateFormat?: string;
94
94
  openHyperlinkOnClick?: boolean;
95
95
  keepHyperlinkResultForInvalidReference?: boolean;
96
+ disableRelativeHyperlinkUri?: boolean;
97
+ allowedHyperlinkUriProtocols?: string[];
96
98
  createHyperlinkTooltip?: (hyperlinkTooltip: string, hint: string) => string;
97
99
  }
98
100
  export interface IBookmarkSettings {
@@ -146,6 +146,10 @@ export class Settings {
146
146
  result.fields.createHyperlinkTooltip = this.parseEventHandler(settings.fields.createHyperlinkTooltip);
147
147
  if (isDefined(settings.fields.keepHyperlinkResultForInvalidReference))
148
148
  result.fields.keepHyperlinkResultForInvalidReference = settings.fields.keepHyperlinkResultForInvalidReference;
149
+ if (isDefined(settings.fields.disableRelativeHyperlinkUri))
150
+ result.fields.disableRelativeHyperlinkUri = settings.fields.disableRelativeHyperlinkUri;
151
+ if (isDefined(settings.fields.allowedHyperlinkUriProtocols))
152
+ result.fields.allowedHyperlinkUriProtocols = settings.fields.allowedHyperlinkUriProtocols;
149
153
  }
150
154
  }
151
155
  static parsePrintingSettings(settings, result) {
@@ -4,6 +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
8
  export class OpenHyperlinkCommand extends HyperlinkCommandBase {
8
9
  executeCore(state, options) {
9
10
  let field;
@@ -27,8 +28,11 @@ export class OpenHyperlinkCommand extends HyperlinkCommandBase {
27
28
  if (hyperlinkInfo.anchor)
28
29
  this.control.commandManager.getCommand(RichEditClientCommand.GoToBookmark)
29
30
  .execute(this.control.commandManager.isPublicApiCall, new CommandSimpleOptions(this.control, hyperlinkInfo.anchor));
30
- else if (!(Url.containsClientScript(hyperlinkInfo.uri) || /^\s*data\s*\:\s*/gi.test(hyperlinkInfo.uri)))
31
- Url.navigate(hyperlinkInfo.uri, "_blank");
31
+ else {
32
+ const options = createUrlValidationOptions(this.control);
33
+ if (isUrlValid(hyperlinkInfo.uri, options))
34
+ Url.navigate(hyperlinkInfo.uri, "_blank");
35
+ }
32
36
  return true;
33
37
  }
34
38
  isEnabledInReadOnlyMode() {
@@ -6,6 +6,8 @@ export declare class FieldsSettings {
6
6
  defaultTimeFormat: string;
7
7
  defaultDateFormat: string;
8
8
  openHyperlinkOnClick: boolean;
9
+ disableRelativeHyperlinkUri: boolean;
10
+ allowedHyperlinkUriProtocols: string[];
9
11
  keepHyperlinkResultForInvalidReference: boolean;
10
12
  createHyperlinkTooltip: (hyperlinkTooltip: string, hint: string) => string;
11
13
  constructor();
@@ -3,6 +3,7 @@ import { isDefined, isNonNullString } from '@devexpress/utils/lib/utils/common';
3
3
  export class FieldsSettings {
4
4
  constructor() {
5
5
  this.openHyperlinkOnClick = false;
6
+ this.disableRelativeHyperlinkUri = false;
6
7
  this.updateFieldsBeforePrint = true;
7
8
  this.updateFieldsOnPaste = true;
8
9
  this.defaultTimeFormat = FieldsSettings.DEFAULT_TIME_FORMAT;
@@ -27,9 +28,12 @@ export class FieldsSettings {
27
28
  this.openHyperlinkOnClick = obj.openHyperlinkOnClick;
28
29
  if (isDefined(obj.keepHyperlinkResultForInvalidReference))
29
30
  this.keepHyperlinkResultForInvalidReference = obj.keepHyperlinkResultForInvalidReference;
30
- if (isDefined(obj.createHyperlinkTooltip) && obj.createHyperlinkTooltip !== '') {
31
+ if (isDefined(obj.createHyperlinkTooltip) && obj.createHyperlinkTooltip !== '')
31
32
  this.createHyperlinkTooltip = convertToFunction(obj.createHyperlinkTooltip);
32
- }
33
+ if (isDefined(obj.disableRelativeHyperlinkUri))
34
+ this.disableRelativeHyperlinkUri = obj.disableRelativeHyperlinkUri;
35
+ if (isDefined(obj.allowedHyperlinkUriProtocols))
36
+ this.allowedHyperlinkUriProtocols = obj.allowedHyperlinkUriProtocols;
33
37
  }
34
38
  clone() {
35
39
  const result = new FieldsSettings();
@@ -1,4 +1,5 @@
1
1
  import { Point } from '@devexpress/utils/lib/geometry/point';
2
+ import { IRichEditControl } from '../interfaces/i-rich-edit-core';
2
3
  export declare function rotatePoint(point: Point, angle: number, center: Point): Point;
3
4
  export declare class SearchTreeItemResult<T> {
4
5
  readonly parentList: T[];
@@ -11,3 +12,9 @@ export declare function searchTreeItem<T extends {
11
12
  }>(items: T[], comparer: (item: T) => boolean): SearchTreeItemResult<T> | null;
12
13
  export declare function convertToFunction(func: any): any | null;
13
14
  export declare function splitByLines(text: string): string[];
15
+ export interface IUrlValidationOptions {
16
+ allowRelativeUrl?: boolean;
17
+ allowedProtocols?: string[];
18
+ }
19
+ export declare function createUrlValidationOptions(control: IRichEditControl): IUrlValidationOptions;
20
+ export declare function isUrlValid(url: string, options?: IUrlValidationOptions): boolean;
@@ -56,3 +56,29 @@ export function convertToFunction(func) {
56
56
  export function splitByLines(text) {
57
57
  return text ? text.split(/\r\n|\r|\n/) : [''];
58
58
  }
59
+ export function createUrlValidationOptions(control) {
60
+ const fieldSettings = control.modelManager.richOptions.fields;
61
+ return {
62
+ allowRelativeUrl: !fieldSettings.disableRelativeHyperlinkUri,
63
+ allowedProtocols: fieldSettings.allowedHyperlinkUriProtocols
64
+ };
65
+ }
66
+ const disallowedProtocols = [
67
+ 'data',
68
+ 'javascript'
69
+ ];
70
+ export function isUrlValid(url, options) {
71
+ let currentLocation;
72
+ if (options === null || options === void 0 ? void 0 : options.allowRelativeUrl)
73
+ currentLocation = window.location.href;
74
+ try {
75
+ const resultUrl = new URL(url, currentLocation);
76
+ const protocol = resultUrl.protocol.slice(0, -1);
77
+ const allowedProtocols = options === null || options === void 0 ? void 0 : options.allowedProtocols;
78
+ if (allowedProtocols)
79
+ return allowedProtocols.includes(protocol);
80
+ return !disallowedProtocols.includes(protocol);
81
+ }
82
+ catch (_a) { }
83
+ return false;
84
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devexpress-richedit",
3
- "version": "24.1.6-build-24246-0102",
3
+ "version": "24.1.6",
4
4
  "homepage": "https://www.devexpress.com/",
5
5
  "bugs": "https://www.devexpress.com/support/",
6
6
  "author": "Developer Express Inc.",
@@ -14,8 +14,8 @@
14
14
  "build-nspell": "webpack --mode production --config=bin/nspell.webpack.config.js"
15
15
  },
16
16
  "peerDependencies": {
17
- "devextreme": "24.1.6-build-24244-1936",
18
- "devextreme-dist": "24.1.6-build-24244-1936"
17
+ "devextreme": "24.1.6",
18
+ "devextreme-dist": "24.1.6"
19
19
  },
20
20
  "dependencies": {
21
21
  "jszip": "~3.10.1",