@microsoft/omnichannel-chat-widget 1.7.7-main.863787d → 1.7.7-main.bdac0a6

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 (19) hide show
  1. package/lib/cjs/common/Constants.js +2 -0
  2. package/lib/cjs/components/livechatwidget/common/createMarkdown.js +4 -3
  3. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +27 -22
  4. package/lib/cjs/components/webchatcontainerstateful/common/defaultProps/defaultWebChatContainerStatefulProps.js +2 -0
  5. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer.js +3 -1
  6. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.js +8 -7
  7. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware.js +3 -1
  8. package/lib/esm/common/Constants.js +2 -0
  9. package/lib/esm/components/livechatwidget/common/createMarkdown.js +4 -3
  10. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +28 -22
  11. package/lib/esm/components/webchatcontainerstateful/common/defaultProps/defaultWebChatContainerStatefulProps.js +2 -0
  12. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer.js +3 -1
  13. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.js +8 -7
  14. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware.js +3 -1
  15. package/lib/types/common/Constants.d.ts +2 -0
  16. package/lib/types/components/livechatwidget/common/createMarkdown.d.ts +1 -1
  17. package/lib/types/components/webchatcontainerstateful/interfaces/IWebChatContainerStatefulProps.d.ts +2 -0
  18. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.d.ts +1 -1
  19. package/package.json +1 -1
@@ -99,6 +99,8 @@ _defineProperty(Constants, "Zero", "zero");
99
99
  _defineProperty(Constants, "Title", "title");
100
100
  _defineProperty(Constants, "Target", "target");
101
101
  _defineProperty(Constants, "Blank", "_blank");
102
+ _defineProperty(Constants, "TargetSelf", "_self");
103
+ _defineProperty(Constants, "TargetTop", "_top");
102
104
  _defineProperty(Constants, "TargetRelationship", "rel");
103
105
  _defineProperty(Constants, "TargetRelationshipAttributes", "noopener noreferrer");
104
106
  // Markdown icons
@@ -11,7 +11,7 @@ var _defaultMarkdownLocalizedTexts = require("../../webchatcontainerstateful/com
11
11
  var _markdownHelper = require("./helpers/markdownHelper");
12
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineMarkdownSupport) => {
14
+ const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineMarkdownSupport, opensMarkdownLinksInSameTab) => {
15
15
  let markdown;
16
16
  if (!disableMarkdownMessageFormatting) {
17
17
  markdown = new _markdownIt.default(_Constants.Constants.Default, {
@@ -45,10 +45,11 @@ const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineMarkdown
45
45
  const targetAttrIndex = tokens[idx].attrIndex(_Constants.Constants.Target);
46
46
  // Put a transparent pixel instead of the "open in new window" icon, so developers can easily modify the icon in CSS.
47
47
  const TRANSPARENT_GIF = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
48
+ const targetValue = opensMarkdownLinksInSameTab ? _Constants.Constants.TargetTop : _Constants.Constants.Blank;
48
49
  if (~targetAttrIndex) {
49
- tokens[idx].attrs[targetAttrIndex][1] = _Constants.Constants.Blank;
50
+ tokens[idx].attrs[targetAttrIndex][1] = targetValue;
50
51
  } else {
51
- tokens[idx].attrPush([_Constants.Constants.Target, _Constants.Constants.Blank]);
52
+ tokens[idx].attrPush([_Constants.Constants.Target, targetValue]);
52
53
  }
53
54
  const relAttrIndex = tokens[idx].attrIndex(_Constants.Constants.TargetRelationship);
54
55
  if (~relAttrIndex) {
@@ -40,7 +40,7 @@ var _sanitizationMiddleware = _interopRequireDefault(require("../../webchatconta
40
40
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
41
41
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
42
  const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) => {
43
- var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _state$domainStates$l4, _state$domainStates$l5, _props$webChatContain9, _props$webChatContain10, _state$domainStates$r, _state$domainStates$r2, _props$webChatContain11, _props$webChatContain12, _state$domainStates$r3, _state$domainStates$r4, _props$webChatContain13, _props$webChatContain14, _defaultWebChatContai, _props$webChatContain15, _props$webChatContain16, _props$webChatContain17, _props$webChatContain18, _state$domainStates$r5, _state$domainStates$r6, _props$webChatContain19, _props$webChatContain20, _defaultWebChatContai2, _props$webChatContain21, _props$webChatContain22, _defaultWebChatContai3, _props$webChatContain23, _props$webChatContain24;
43
+ var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$webChatContain6, _state$domainStates$l4, _state$domainStates$l5, _props$webChatContain11, _props$webChatContain12, _state$domainStates$r, _state$domainStates$r2, _props$webChatContain13, _props$webChatContain14, _state$domainStates$r3, _state$domainStates$r4, _props$webChatContain15, _props$webChatContain16, _defaultWebChatContai, _props$webChatContain17, _props$webChatContain18, _props$webChatContain19, _props$webChatContain20, _state$domainStates$r5, _state$domainStates$r6, _props$webChatContain21, _props$webChatContain22, _defaultWebChatContai2, _props$webChatContain23, _props$webChatContain24, _defaultWebChatContai3, _props$webChatContain25, _props$webChatContain26;
44
44
  // Add a hook to make all links open a new window
45
45
  postDomPurifyActivities();
46
46
  const localizedTexts = {
@@ -50,12 +50,14 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
50
50
  const hyperlinkTextOverride = ((_props$webChatContain2 = props.webChatContainerProps) === null || _props$webChatContain2 === void 0 ? void 0 : _props$webChatContain2.hyperlinkTextOverride) ?? _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.hyperlinkTextOverride;
51
51
  const disableNewLineMarkdownSupport = ((_props$webChatContain3 = props.webChatContainerProps) === null || _props$webChatContain3 === void 0 ? void 0 : _props$webChatContain3.disableNewLineMarkdownSupport) ?? _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.disableNewLineMarkdownSupport;
52
52
  const disableMarkdownMessageFormatting = ((_props$webChatContain4 = props.webChatContainerProps) === null || _props$webChatContain4 === void 0 ? void 0 : _props$webChatContain4.disableMarkdownMessageFormatting) ?? _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.disableMarkdownMessageFormatting;
53
+ const opensMarkdownLinksInSameTab = (_props$webChatContain5 = props.webChatContainerProps) === null || _props$webChatContain5 === void 0 ? void 0 : _props$webChatContain5.opensMarkdownLinksInSameTab;
54
+ const honorsTargetInHTMLLinks = (_props$webChatContain6 = props.webChatContainerProps) === null || _props$webChatContain6 === void 0 ? void 0 : _props$webChatContain6.honorsTargetInHTMLLinks;
53
55
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
54
- const markdown = (0, _createMarkdown.createMarkdown)(disableMarkdownMessageFormatting, disableNewLineMarkdownSupport);
56
+ const markdown = (0, _createMarkdown.createMarkdown)(disableMarkdownMessageFormatting, disableNewLineMarkdownSupport, opensMarkdownLinksInSameTab);
55
57
  // Initialize Web Chat's redux store
56
58
  let webChatStore = _WebChatStoreLoader.WebChatStoreLoader.store;
57
59
  if (!webChatStore) {
58
- var _state$domainStates$l, _state$domainStates$l2, _state$domainStates$l3, _props$webChatContain5;
60
+ var _state$domainStates$l, _state$domainStates$l2, _state$domainStates$l3, _props$webChatContain7;
59
61
  const conversationEndCallback = async () => {
60
62
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
63
  const conversationDetails = await (0, _utils.getConversationDetailsCall)(facadeChatSDK);
@@ -87,18 +89,18 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
87
89
  };
88
90
  webChatStore = (0, _botframeworkWebchat.createStore)({},
89
91
  //initial state
90
- _preProcessingMiddleware.default, _attachmentProcessingMiddleware.default, (0, _attachmentUploadValidatorMiddleware.default)((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), _channelDataMiddleware.default, (0, _conversationEndMiddleware.default)(conversationEndCallback), (0, _dataMaskingMiddleware.default)((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), _messageTimestampMiddleware.createMessageTimeStampMiddleware, _messageSequenceIdOverrideMiddleware.createMessageSequenceIdOverrideMiddleware, _gifUploadMiddleware.default, _htmlPlayerMiddleware.default, _htmlTextMiddleware.default, (0, _maxMessageSizeValidator.default)(localizedTexts), _sanitizationMiddleware.default,
92
+ _preProcessingMiddleware.default, _attachmentProcessingMiddleware.default, (0, _attachmentUploadValidatorMiddleware.default)((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), _channelDataMiddleware.default, (0, _conversationEndMiddleware.default)(conversationEndCallback), (0, _dataMaskingMiddleware.default)((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), _messageTimestampMiddleware.createMessageTimeStampMiddleware, _messageSequenceIdOverrideMiddleware.createMessageSequenceIdOverrideMiddleware, _gifUploadMiddleware.default, _htmlPlayerMiddleware.default, (0, _htmlTextMiddleware.default)(honorsTargetInHTMLLinks), (0, _maxMessageSizeValidator.default)(localizedTexts), _sanitizationMiddleware.default,
91
93
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
- ...(((_props$webChatContain5 = props.webChatContainerProps) === null || _props$webChatContain5 === void 0 ? void 0 : _props$webChatContain5.storeMiddlewares) ?? []));
94
+ ...(((_props$webChatContain7 = props.webChatContainerProps) === null || _props$webChatContain7 === void 0 ? void 0 : _props$webChatContain7.storeMiddlewares) ?? []));
93
95
  _WebChatStoreLoader.WebChatStoreLoader.store = webChatStore;
94
96
  }
95
97
  const hyperlinkTextOverrideRenderer = new _HyperlinkTextOverrideRenderer.default(hyperlinkTextOverride);
96
98
  const markdownRenderers = [hyperlinkTextOverrideRenderer];
97
99
  const renderMarkdown = text => {
98
- var _props$webChatContain6, _props$webChatContain7;
99
- if ((_props$webChatContain6 = props.webChatContainerProps) !== null && _props$webChatContain6 !== void 0 && (_props$webChatContain7 = _props$webChatContain6.webChatProps) !== null && _props$webChatContain7 !== void 0 && _props$webChatContain7.renderMarkdown) {
100
- var _props$webChatContain8;
101
- text = (_props$webChatContain8 = props.webChatContainerProps) === null || _props$webChatContain8 === void 0 ? void 0 : _props$webChatContain8.webChatProps.renderMarkdown(text);
100
+ var _props$webChatContain8, _props$webChatContain9;
101
+ if ((_props$webChatContain8 = props.webChatContainerProps) !== null && _props$webChatContain8 !== void 0 && (_props$webChatContain9 = _props$webChatContain8.webChatProps) !== null && _props$webChatContain9 !== void 0 && _props$webChatContain9.renderMarkdown) {
102
+ var _props$webChatContain10;
103
+ text = (_props$webChatContain10 = props.webChatContainerProps) === null || _props$webChatContain10 === void 0 ? void 0 : _props$webChatContain10.webChatProps.renderMarkdown(text);
102
104
  } else {
103
105
  const render = disableMarkdownMessageFormatting ? markdown.renderInline.bind(markdown) : markdown.render.bind(markdown);
104
106
  text = render(text);
@@ -108,16 +110,19 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
108
110
  });
109
111
  const config = {
110
112
  FORBID_TAGS: ["form", "button", "script", "div", "input"],
111
- FORBID_ATTR: ["action"]
113
+ FORBID_ATTR: ["action"],
114
+ ADD_ATTR: ["target"]
112
115
  };
113
116
  text = _dompurify.default.sanitize(text, config);
114
117
  return text;
115
118
  };
116
119
  function postDomPurifyActivities() {
117
120
  _dompurify.default.addHook("afterSanitizeAttributes", function (node) {
118
- // set all elements owning target to target=_blank
119
- if ("target" in node) {
120
- node.setAttribute("target", "_blank");
121
+ const target = node.getAttribute(_Constants.Constants.Target);
122
+ if (target === _Constants.Constants.TargetSelf) {
123
+ node.setAttribute(_Constants.Constants.Target, _Constants.Constants.TargetTop);
124
+ } else if (!target) {
125
+ node.setAttribute(_Constants.Constants.Target, _Constants.Constants.Blank);
121
126
  }
122
127
  });
123
128
  }
@@ -127,18 +132,18 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
127
132
  dir: state.domainStates.globalDir,
128
133
  locale: (0, _utils.changeLanguageCodeFormatForWebChat)((0, _omnichannelChatSdk.getLocaleStringFromId)((_state$domainStates$l4 = state.domainStates.liveChatConfig) === null || _state$domainStates$l4 === void 0 ? void 0 : (_state$domainStates$l5 = _state$domainStates$l4.ChatWidgetLanguage) === null || _state$domainStates$l5 === void 0 ? void 0 : _state$domainStates$l5.msdyn_localeid)),
129
134
  store: webChatStore,
130
- activityMiddleware: (_props$webChatContain9 = props.webChatContainerProps) !== null && _props$webChatContain9 !== void 0 && (_props$webChatContain10 = _props$webChatContain9.renderingMiddlewareProps) !== null && _props$webChatContain10 !== void 0 && _props$webChatContain10.disableActivityMiddleware ? undefined : (0, _activityMiddleware.createActivityMiddleware)(renderMarkdown, (_state$domainStates$r = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r === void 0 ? void 0 : _state$domainStates$r.systemMessageStyleProps, (_state$domainStates$r2 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r2 === void 0 ? void 0 : _state$domainStates$r2.userMessageStyleProps),
131
- attachmentMiddleware: (_props$webChatContain11 = props.webChatContainerProps) !== null && _props$webChatContain11 !== void 0 && (_props$webChatContain12 = _props$webChatContain11.renderingMiddlewareProps) !== null && _props$webChatContain12 !== void 0 && _props$webChatContain12.disableAttachmentMiddleware ? undefined : (0, _attachmentMiddleware.createAttachmentMiddleware)(((_state$domainStates$r3 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r3 === void 0 ? void 0 : (_state$domainStates$r4 = _state$domainStates$r3.attachmentProps) === null || _state$domainStates$r4 === void 0 ? void 0 : _state$domainStates$r4.enableInlinePlaying) ?? _defaultAttachmentProps.defaultAttachmentProps.enableInlinePlaying),
132
- activityStatusMiddleware: (_props$webChatContain13 = props.webChatContainerProps) !== null && _props$webChatContain13 !== void 0 && (_props$webChatContain14 = _props$webChatContain13.renderingMiddlewareProps) !== null && _props$webChatContain14 !== void 0 && _props$webChatContain14.disableActivityStatusMiddleware ? undefined : (_defaultWebChatContai = _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai === void 0 ? void 0 : _defaultWebChatContai.activityStatusMiddleware,
133
- toastMiddleware: (_props$webChatContain15 = props.webChatContainerProps) !== null && _props$webChatContain15 !== void 0 && (_props$webChatContain16 = _props$webChatContain15.renderingMiddlewareProps) !== null && _props$webChatContain16 !== void 0 && _props$webChatContain16.disableToastMiddleware ? undefined : (0, _toastMiddleware.createToastMiddleware)(props.notificationPaneProps, endChat),
135
+ activityMiddleware: (_props$webChatContain11 = props.webChatContainerProps) !== null && _props$webChatContain11 !== void 0 && (_props$webChatContain12 = _props$webChatContain11.renderingMiddlewareProps) !== null && _props$webChatContain12 !== void 0 && _props$webChatContain12.disableActivityMiddleware ? undefined : (0, _activityMiddleware.createActivityMiddleware)(renderMarkdown, (_state$domainStates$r = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r === void 0 ? void 0 : _state$domainStates$r.systemMessageStyleProps, (_state$domainStates$r2 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r2 === void 0 ? void 0 : _state$domainStates$r2.userMessageStyleProps),
136
+ attachmentMiddleware: (_props$webChatContain13 = props.webChatContainerProps) !== null && _props$webChatContain13 !== void 0 && (_props$webChatContain14 = _props$webChatContain13.renderingMiddlewareProps) !== null && _props$webChatContain14 !== void 0 && _props$webChatContain14.disableAttachmentMiddleware ? undefined : (0, _attachmentMiddleware.createAttachmentMiddleware)(((_state$domainStates$r3 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r3 === void 0 ? void 0 : (_state$domainStates$r4 = _state$domainStates$r3.attachmentProps) === null || _state$domainStates$r4 === void 0 ? void 0 : _state$domainStates$r4.enableInlinePlaying) ?? _defaultAttachmentProps.defaultAttachmentProps.enableInlinePlaying),
137
+ activityStatusMiddleware: (_props$webChatContain15 = props.webChatContainerProps) !== null && _props$webChatContain15 !== void 0 && (_props$webChatContain16 = _props$webChatContain15.renderingMiddlewareProps) !== null && _props$webChatContain16 !== void 0 && _props$webChatContain16.disableActivityStatusMiddleware ? undefined : (_defaultWebChatContai = _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai === void 0 ? void 0 : _defaultWebChatContai.activityStatusMiddleware,
138
+ toastMiddleware: (_props$webChatContain17 = props.webChatContainerProps) !== null && _props$webChatContain17 !== void 0 && (_props$webChatContain18 = _props$webChatContain17.renderingMiddlewareProps) !== null && _props$webChatContain18 !== void 0 && _props$webChatContain18.disableToastMiddleware ? undefined : (0, _toastMiddleware.createToastMiddleware)(props.notificationPaneProps, endChat),
134
139
  renderMarkdown,
135
- avatarMiddleware: (_props$webChatContain17 = props.webChatContainerProps) !== null && _props$webChatContain17 !== void 0 && (_props$webChatContain18 = _props$webChatContain17.renderingMiddlewareProps) !== null && _props$webChatContain18 !== void 0 && _props$webChatContain18.disableAvatarMiddleware ? undefined : (0, _avatarMiddleware.createAvatarMiddleware)((_state$domainStates$r5 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r5 === void 0 ? void 0 : _state$domainStates$r5.avatarStyleProps, (_state$domainStates$r6 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r6 === void 0 ? void 0 : _state$domainStates$r6.avatarTextStyleProps),
136
- groupActivitiesMiddleware: (_props$webChatContain19 = props.webChatContainerProps) !== null && _props$webChatContain19 !== void 0 && (_props$webChatContain20 = _props$webChatContain19.renderingMiddlewareProps) !== null && _props$webChatContain20 !== void 0 && _props$webChatContain20.disableGroupActivitiesMiddleware ? undefined : (_defaultWebChatContai2 = _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai2 === void 0 ? void 0 : _defaultWebChatContai2.groupActivitiesMiddleware,
137
- typingIndicatorMiddleware: (_props$webChatContain21 = props.webChatContainerProps) !== null && _props$webChatContain21 !== void 0 && (_props$webChatContain22 = _props$webChatContain21.renderingMiddlewareProps) !== null && _props$webChatContain22 !== void 0 && _props$webChatContain22.disableTypingIndicatorMiddleware ? undefined : (_defaultWebChatContai3 = _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai3 === void 0 ? void 0 : _defaultWebChatContai3.typingIndicatorMiddleware,
140
+ avatarMiddleware: (_props$webChatContain19 = props.webChatContainerProps) !== null && _props$webChatContain19 !== void 0 && (_props$webChatContain20 = _props$webChatContain19.renderingMiddlewareProps) !== null && _props$webChatContain20 !== void 0 && _props$webChatContain20.disableAvatarMiddleware ? undefined : (0, _avatarMiddleware.createAvatarMiddleware)((_state$domainStates$r5 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r5 === void 0 ? void 0 : _state$domainStates$r5.avatarStyleProps, (_state$domainStates$r6 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r6 === void 0 ? void 0 : _state$domainStates$r6.avatarTextStyleProps),
141
+ groupActivitiesMiddleware: (_props$webChatContain21 = props.webChatContainerProps) !== null && _props$webChatContain21 !== void 0 && (_props$webChatContain22 = _props$webChatContain21.renderingMiddlewareProps) !== null && _props$webChatContain22 !== void 0 && _props$webChatContain22.disableGroupActivitiesMiddleware ? undefined : (_defaultWebChatContai2 = _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai2 === void 0 ? void 0 : _defaultWebChatContai2.groupActivitiesMiddleware,
142
+ typingIndicatorMiddleware: (_props$webChatContain23 = props.webChatContainerProps) !== null && _props$webChatContain23 !== void 0 && (_props$webChatContain24 = _props$webChatContain23.renderingMiddlewareProps) !== null && _props$webChatContain24 !== void 0 && _props$webChatContain24.disableTypingIndicatorMiddleware ? undefined : (_defaultWebChatContai3 = _defaultWebChatContainerStatefulProps.defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai3 === void 0 ? void 0 : _defaultWebChatContai3.typingIndicatorMiddleware,
138
143
  onTelemetry: (0, _WebChatLogger.createWebChatTelemetry)(),
139
- cardActionMiddleware: (0, _cardActionMiddleware.createCardActionMiddleware)(((_props$webChatContain23 = props.webChatContainerProps) === null || _props$webChatContain23 === void 0 ? void 0 : _props$webChatContain23.botMagicCode) || undefined),
144
+ cardActionMiddleware: (0, _cardActionMiddleware.createCardActionMiddleware)(((_props$webChatContain25 = props.webChatContainerProps) === null || _props$webChatContain25 === void 0 ? void 0 : _props$webChatContain25.botMagicCode) || undefined),
140
145
  sendTypingIndicator: true,
141
- ...((_props$webChatContain24 = props.webChatContainerProps) === null || _props$webChatContain24 === void 0 ? void 0 : _props$webChatContain24.webChatProps)
146
+ ...((_props$webChatContain26 = props.webChatContainerProps) === null || _props$webChatContain26 === void 0 ? void 0 : _props$webChatContain26.webChatProps)
142
147
  };
143
148
  return webChatProps;
144
149
  };
@@ -16,6 +16,8 @@ const defaultWebChatContainerStatefulProps = {
16
16
  containerStyles: _defaultWebChatStatefulContainerStyles.defaultWebChatStatefulContainerStyles,
17
17
  disableNewLineMarkdownSupport: false,
18
18
  disableMarkdownMessageFormatting: false,
19
+ opensMarkdownLinksInSameTab: false,
20
+ honorsTargetInHTMLLinks: false,
19
21
  hyperlinkTextOverride: false,
20
22
  directLine: new _mockadapter.default(),
21
23
  adaptiveCardStyles: _defaultAdaptiveCardStyles.defaultAdaptiveCardStyles
@@ -18,7 +18,9 @@ class HyperlinkTextOverrideRenderer {
18
18
  convertTextToHtmlNode(text) {
19
19
  const htmlNode = document.createElement(_Constants.HtmlAttributeNames.div);
20
20
  try {
21
- text = _dompurify.default.sanitize(text); // eslint-disable-line @typescript-eslint/no-explicit-any
21
+ text = _dompurify.default.sanitize(text, {
22
+ ADD_ATTR: ["target"]
23
+ });
22
24
  htmlNode.innerHTML = text;
23
25
  } catch {
24
26
  return htmlNode;
@@ -22,8 +22,9 @@ const convertTextToHtmlNode = text => {
22
22
  if (!text) return "";
23
23
  const element = document.createElement(_Constants.HtmlAttributeNames.div);
24
24
  try {
25
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- text = _dompurify.default.sanitize(text);
25
+ text = _dompurify.default.sanitize(text, {
26
+ ADD_ATTR: ["target"]
27
+ });
27
28
  element.innerHTML = text;
28
29
  } catch (e) {
29
30
  const errorMessage = `Failed to purify and set innertHTML with text: ${text}`;
@@ -39,7 +40,7 @@ const convertTextToHtmlNode = text => {
39
40
  };
40
41
 
41
42
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
- const processHTMLText = (action, text) => {
43
+ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
43
44
  const htmlNode = convertTextToHtmlNode(text);
44
45
  const aNodes = htmlNode.getElementsByTagName(_Constants.HtmlAttributeNames.aTagName);
45
46
  if ((aNodes === null || aNodes === void 0 ? void 0 : aNodes.length) > 0) {
@@ -52,8 +53,8 @@ const processHTMLText = (action, text) => {
52
53
  continue;
53
54
  }
54
55
 
55
- // Add target to 'a' node if target is missing or does not equal to blank
56
- if (!aNode.target || aNode.target !== _Constants.Constants.blank) {
56
+ // Add target to 'a' node if target is missing or if honorsTargetInHTMLLinks is false
57
+ if (!aNode.target || !honorsTargetInHTMLLinks) {
57
58
  aNode.target = _Constants.Constants.blank;
58
59
  }
59
60
 
@@ -92,7 +93,7 @@ const processHTMLText = (action, text) => {
92
93
  };
93
94
 
94
95
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
95
- const htmlTextMiddleware = _ref => {
96
+ const htmlTextMiddleware = honorsTargetInHTMLLinks => _ref => {
96
97
  let {
97
98
  dispatch
98
99
  } = _ref;
@@ -102,7 +103,7 @@ const htmlTextMiddleware = _ref => {
102
103
  var _action$payload, _action$payload$activ;
103
104
  const text = (_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : (_action$payload$activ = _action$payload.activity) === null || _action$payload$activ === void 0 ? void 0 : _action$payload$activ.text;
104
105
  if (text) {
105
- action = processHTMLText(action, text);
106
+ action = processHTMLText(action, text, honorsTargetInHTMLLinks ?? false);
106
107
  }
107
108
  } catch (e) {
108
109
  let errorMessage = "Failed to validate action.";
@@ -26,7 +26,9 @@ const sanitizationMiddleware = _ref => {
26
26
  var _action$payload;
27
27
  let text = (_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : _action$payload.text;
28
28
  if (text) {
29
- text = _dompurify.default.sanitize(text) ?? " ";
29
+ text = _dompurify.default.sanitize(text, {
30
+ ADD_ATTR: ["target"]
31
+ }) ?? " ";
30
32
  }
31
33
  } catch (e) {
32
34
  const copyDataForTelemetry = {
@@ -92,6 +92,8 @@ _defineProperty(Constants, "Zero", "zero");
92
92
  _defineProperty(Constants, "Title", "title");
93
93
  _defineProperty(Constants, "Target", "target");
94
94
  _defineProperty(Constants, "Blank", "_blank");
95
+ _defineProperty(Constants, "TargetSelf", "_self");
96
+ _defineProperty(Constants, "TargetTop", "_top");
95
97
  _defineProperty(Constants, "TargetRelationship", "rel");
96
98
  _defineProperty(Constants, "TargetRelationshipAttributes", "noopener noreferrer");
97
99
  // Markdown icons
@@ -5,7 +5,7 @@ import { defaultMarkdownLocalizedTexts } from "../../webchatcontainerstateful/co
5
5
  import { addSlackMarkdownIt } from "./helpers/markdownHelper";
6
6
 
7
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
- export const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineMarkdownSupport) => {
8
+ export const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineMarkdownSupport, opensMarkdownLinksInSameTab) => {
9
9
  let markdown;
10
10
  if (!disableMarkdownMessageFormatting) {
11
11
  markdown = new MarkdownIt(Constants.Default, {
@@ -39,10 +39,11 @@ export const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineM
39
39
  const targetAttrIndex = tokens[idx].attrIndex(Constants.Target);
40
40
  // Put a transparent pixel instead of the "open in new window" icon, so developers can easily modify the icon in CSS.
41
41
  const TRANSPARENT_GIF = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
42
+ const targetValue = opensMarkdownLinksInSameTab ? Constants.TargetTop : Constants.Blank;
42
43
  if (~targetAttrIndex) {
43
- tokens[idx].attrs[targetAttrIndex][1] = Constants.Blank;
44
+ tokens[idx].attrs[targetAttrIndex][1] = targetValue;
44
45
  } else {
45
- tokens[idx].attrPush([Constants.Target, Constants.Blank]);
46
+ tokens[idx].attrPush([Constants.Target, targetValue]);
46
47
  }
47
48
  const relAttrIndex = tokens[idx].attrIndex(Constants.TargetRelationship);
48
49
  if (~relAttrIndex) {
@@ -31,10 +31,11 @@ import htmlPlayerMiddleware from "../../webchatcontainerstateful/webchatcontroll
31
31
  import htmlTextMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware";
32
32
  import preProcessingMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/preProcessingMiddleware";
33
33
  import sanitizationMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware";
34
+ import { Constants } from "../../../common/Constants";
34
35
 
35
36
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
37
  export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) => {
37
- var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _state$domainStates$l4, _state$domainStates$l5, _props$webChatContain9, _props$webChatContain10, _state$domainStates$r, _state$domainStates$r2, _props$webChatContain11, _props$webChatContain12, _state$domainStates$r3, _state$domainStates$r4, _props$webChatContain13, _props$webChatContain14, _defaultWebChatContai, _props$webChatContain15, _props$webChatContain16, _props$webChatContain17, _props$webChatContain18, _state$domainStates$r5, _state$domainStates$r6, _props$webChatContain19, _props$webChatContain20, _defaultWebChatContai2, _props$webChatContain21, _props$webChatContain22, _defaultWebChatContai3, _props$webChatContain23, _props$webChatContain24;
38
+ var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$webChatContain6, _state$domainStates$l4, _state$domainStates$l5, _props$webChatContain11, _props$webChatContain12, _state$domainStates$r, _state$domainStates$r2, _props$webChatContain13, _props$webChatContain14, _state$domainStates$r3, _state$domainStates$r4, _props$webChatContain15, _props$webChatContain16, _defaultWebChatContai, _props$webChatContain17, _props$webChatContain18, _props$webChatContain19, _props$webChatContain20, _state$domainStates$r5, _state$domainStates$r6, _props$webChatContain21, _props$webChatContain22, _defaultWebChatContai2, _props$webChatContain23, _props$webChatContain24, _defaultWebChatContai3, _props$webChatContain25, _props$webChatContain26;
38
39
  // Add a hook to make all links open a new window
39
40
  postDomPurifyActivities();
40
41
  const localizedTexts = {
@@ -44,12 +45,14 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
44
45
  const hyperlinkTextOverride = ((_props$webChatContain2 = props.webChatContainerProps) === null || _props$webChatContain2 === void 0 ? void 0 : _props$webChatContain2.hyperlinkTextOverride) ?? defaultWebChatContainerStatefulProps.hyperlinkTextOverride;
45
46
  const disableNewLineMarkdownSupport = ((_props$webChatContain3 = props.webChatContainerProps) === null || _props$webChatContain3 === void 0 ? void 0 : _props$webChatContain3.disableNewLineMarkdownSupport) ?? defaultWebChatContainerStatefulProps.disableNewLineMarkdownSupport;
46
47
  const disableMarkdownMessageFormatting = ((_props$webChatContain4 = props.webChatContainerProps) === null || _props$webChatContain4 === void 0 ? void 0 : _props$webChatContain4.disableMarkdownMessageFormatting) ?? defaultWebChatContainerStatefulProps.disableMarkdownMessageFormatting;
48
+ const opensMarkdownLinksInSameTab = (_props$webChatContain5 = props.webChatContainerProps) === null || _props$webChatContain5 === void 0 ? void 0 : _props$webChatContain5.opensMarkdownLinksInSameTab;
49
+ const honorsTargetInHTMLLinks = (_props$webChatContain6 = props.webChatContainerProps) === null || _props$webChatContain6 === void 0 ? void 0 : _props$webChatContain6.honorsTargetInHTMLLinks;
47
50
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
48
- const markdown = createMarkdown(disableMarkdownMessageFormatting, disableNewLineMarkdownSupport);
51
+ const markdown = createMarkdown(disableMarkdownMessageFormatting, disableNewLineMarkdownSupport, opensMarkdownLinksInSameTab);
49
52
  // Initialize Web Chat's redux store
50
53
  let webChatStore = WebChatStoreLoader.store;
51
54
  if (!webChatStore) {
52
- var _state$domainStates$l, _state$domainStates$l2, _state$domainStates$l3, _props$webChatContain5;
55
+ var _state$domainStates$l, _state$domainStates$l2, _state$domainStates$l3, _props$webChatContain7;
53
56
  const conversationEndCallback = async () => {
54
57
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
58
  const conversationDetails = await getConversationDetailsCall(facadeChatSDK);
@@ -81,18 +84,18 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
81
84
  };
82
85
  webChatStore = createStore({},
83
86
  //initial state
84
- preProcessingMiddleware, attachmentProcessingMiddleware, createAttachmentUploadValidatorMiddleware((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), channelDataMiddleware, createConversationEndMiddleware(conversationEndCallback), createDataMaskingMiddleware((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), createMessageTimeStampMiddleware, createMessageSequenceIdOverrideMiddleware, gifUploadMiddleware, htmlPlayerMiddleware, htmlTextMiddleware, createMaxMessageSizeValidator(localizedTexts), sanitizationMiddleware,
87
+ preProcessingMiddleware, attachmentProcessingMiddleware, createAttachmentUploadValidatorMiddleware((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), channelDataMiddleware, createConversationEndMiddleware(conversationEndCallback), createDataMaskingMiddleware((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), createMessageTimeStampMiddleware, createMessageSequenceIdOverrideMiddleware, gifUploadMiddleware, htmlPlayerMiddleware, htmlTextMiddleware(honorsTargetInHTMLLinks), createMaxMessageSizeValidator(localizedTexts), sanitizationMiddleware,
85
88
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
- ...(((_props$webChatContain5 = props.webChatContainerProps) === null || _props$webChatContain5 === void 0 ? void 0 : _props$webChatContain5.storeMiddlewares) ?? []));
89
+ ...(((_props$webChatContain7 = props.webChatContainerProps) === null || _props$webChatContain7 === void 0 ? void 0 : _props$webChatContain7.storeMiddlewares) ?? []));
87
90
  WebChatStoreLoader.store = webChatStore;
88
91
  }
89
92
  const hyperlinkTextOverrideRenderer = new HyperlinkTextOverrideRenderer(hyperlinkTextOverride);
90
93
  const markdownRenderers = [hyperlinkTextOverrideRenderer];
91
94
  const renderMarkdown = text => {
92
- var _props$webChatContain6, _props$webChatContain7;
93
- if ((_props$webChatContain6 = props.webChatContainerProps) !== null && _props$webChatContain6 !== void 0 && (_props$webChatContain7 = _props$webChatContain6.webChatProps) !== null && _props$webChatContain7 !== void 0 && _props$webChatContain7.renderMarkdown) {
94
- var _props$webChatContain8;
95
- text = (_props$webChatContain8 = props.webChatContainerProps) === null || _props$webChatContain8 === void 0 ? void 0 : _props$webChatContain8.webChatProps.renderMarkdown(text);
95
+ var _props$webChatContain8, _props$webChatContain9;
96
+ if ((_props$webChatContain8 = props.webChatContainerProps) !== null && _props$webChatContain8 !== void 0 && (_props$webChatContain9 = _props$webChatContain8.webChatProps) !== null && _props$webChatContain9 !== void 0 && _props$webChatContain9.renderMarkdown) {
97
+ var _props$webChatContain10;
98
+ text = (_props$webChatContain10 = props.webChatContainerProps) === null || _props$webChatContain10 === void 0 ? void 0 : _props$webChatContain10.webChatProps.renderMarkdown(text);
96
99
  } else {
97
100
  const render = disableMarkdownMessageFormatting ? markdown.renderInline.bind(markdown) : markdown.render.bind(markdown);
98
101
  text = render(text);
@@ -102,16 +105,19 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
102
105
  });
103
106
  const config = {
104
107
  FORBID_TAGS: ["form", "button", "script", "div", "input"],
105
- FORBID_ATTR: ["action"]
108
+ FORBID_ATTR: ["action"],
109
+ ADD_ATTR: ["target"]
106
110
  };
107
111
  text = DOMPurify.sanitize(text, config);
108
112
  return text;
109
113
  };
110
114
  function postDomPurifyActivities() {
111
115
  DOMPurify.addHook("afterSanitizeAttributes", function (node) {
112
- // set all elements owning target to target=_blank
113
- if ("target" in node) {
114
- node.setAttribute("target", "_blank");
116
+ const target = node.getAttribute(Constants.Target);
117
+ if (target === Constants.TargetSelf) {
118
+ node.setAttribute(Constants.Target, Constants.TargetTop);
119
+ } else if (!target) {
120
+ node.setAttribute(Constants.Target, Constants.Blank);
115
121
  }
116
122
  });
117
123
  }
@@ -121,18 +127,18 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
121
127
  dir: state.domainStates.globalDir,
122
128
  locale: changeLanguageCodeFormatForWebChat(getLocaleStringFromId((_state$domainStates$l4 = state.domainStates.liveChatConfig) === null || _state$domainStates$l4 === void 0 ? void 0 : (_state$domainStates$l5 = _state$domainStates$l4.ChatWidgetLanguage) === null || _state$domainStates$l5 === void 0 ? void 0 : _state$domainStates$l5.msdyn_localeid)),
123
129
  store: webChatStore,
124
- activityMiddleware: (_props$webChatContain9 = props.webChatContainerProps) !== null && _props$webChatContain9 !== void 0 && (_props$webChatContain10 = _props$webChatContain9.renderingMiddlewareProps) !== null && _props$webChatContain10 !== void 0 && _props$webChatContain10.disableActivityMiddleware ? undefined : createActivityMiddleware(renderMarkdown, (_state$domainStates$r = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r === void 0 ? void 0 : _state$domainStates$r.systemMessageStyleProps, (_state$domainStates$r2 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r2 === void 0 ? void 0 : _state$domainStates$r2.userMessageStyleProps),
125
- attachmentMiddleware: (_props$webChatContain11 = props.webChatContainerProps) !== null && _props$webChatContain11 !== void 0 && (_props$webChatContain12 = _props$webChatContain11.renderingMiddlewareProps) !== null && _props$webChatContain12 !== void 0 && _props$webChatContain12.disableAttachmentMiddleware ? undefined : createAttachmentMiddleware(((_state$domainStates$r3 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r3 === void 0 ? void 0 : (_state$domainStates$r4 = _state$domainStates$r3.attachmentProps) === null || _state$domainStates$r4 === void 0 ? void 0 : _state$domainStates$r4.enableInlinePlaying) ?? defaultAttachmentProps.enableInlinePlaying),
126
- activityStatusMiddleware: (_props$webChatContain13 = props.webChatContainerProps) !== null && _props$webChatContain13 !== void 0 && (_props$webChatContain14 = _props$webChatContain13.renderingMiddlewareProps) !== null && _props$webChatContain14 !== void 0 && _props$webChatContain14.disableActivityStatusMiddleware ? undefined : (_defaultWebChatContai = defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai === void 0 ? void 0 : _defaultWebChatContai.activityStatusMiddleware,
127
- toastMiddleware: (_props$webChatContain15 = props.webChatContainerProps) !== null && _props$webChatContain15 !== void 0 && (_props$webChatContain16 = _props$webChatContain15.renderingMiddlewareProps) !== null && _props$webChatContain16 !== void 0 && _props$webChatContain16.disableToastMiddleware ? undefined : createToastMiddleware(props.notificationPaneProps, endChat),
130
+ activityMiddleware: (_props$webChatContain11 = props.webChatContainerProps) !== null && _props$webChatContain11 !== void 0 && (_props$webChatContain12 = _props$webChatContain11.renderingMiddlewareProps) !== null && _props$webChatContain12 !== void 0 && _props$webChatContain12.disableActivityMiddleware ? undefined : createActivityMiddleware(renderMarkdown, (_state$domainStates$r = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r === void 0 ? void 0 : _state$domainStates$r.systemMessageStyleProps, (_state$domainStates$r2 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r2 === void 0 ? void 0 : _state$domainStates$r2.userMessageStyleProps),
131
+ attachmentMiddleware: (_props$webChatContain13 = props.webChatContainerProps) !== null && _props$webChatContain13 !== void 0 && (_props$webChatContain14 = _props$webChatContain13.renderingMiddlewareProps) !== null && _props$webChatContain14 !== void 0 && _props$webChatContain14.disableAttachmentMiddleware ? undefined : createAttachmentMiddleware(((_state$domainStates$r3 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r3 === void 0 ? void 0 : (_state$domainStates$r4 = _state$domainStates$r3.attachmentProps) === null || _state$domainStates$r4 === void 0 ? void 0 : _state$domainStates$r4.enableInlinePlaying) ?? defaultAttachmentProps.enableInlinePlaying),
132
+ activityStatusMiddleware: (_props$webChatContain15 = props.webChatContainerProps) !== null && _props$webChatContain15 !== void 0 && (_props$webChatContain16 = _props$webChatContain15.renderingMiddlewareProps) !== null && _props$webChatContain16 !== void 0 && _props$webChatContain16.disableActivityStatusMiddleware ? undefined : (_defaultWebChatContai = defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai === void 0 ? void 0 : _defaultWebChatContai.activityStatusMiddleware,
133
+ toastMiddleware: (_props$webChatContain17 = props.webChatContainerProps) !== null && _props$webChatContain17 !== void 0 && (_props$webChatContain18 = _props$webChatContain17.renderingMiddlewareProps) !== null && _props$webChatContain18 !== void 0 && _props$webChatContain18.disableToastMiddleware ? undefined : createToastMiddleware(props.notificationPaneProps, endChat),
128
134
  renderMarkdown,
129
- avatarMiddleware: (_props$webChatContain17 = props.webChatContainerProps) !== null && _props$webChatContain17 !== void 0 && (_props$webChatContain18 = _props$webChatContain17.renderingMiddlewareProps) !== null && _props$webChatContain18 !== void 0 && _props$webChatContain18.disableAvatarMiddleware ? undefined : createAvatarMiddleware((_state$domainStates$r5 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r5 === void 0 ? void 0 : _state$domainStates$r5.avatarStyleProps, (_state$domainStates$r6 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r6 === void 0 ? void 0 : _state$domainStates$r6.avatarTextStyleProps),
130
- groupActivitiesMiddleware: (_props$webChatContain19 = props.webChatContainerProps) !== null && _props$webChatContain19 !== void 0 && (_props$webChatContain20 = _props$webChatContain19.renderingMiddlewareProps) !== null && _props$webChatContain20 !== void 0 && _props$webChatContain20.disableGroupActivitiesMiddleware ? undefined : (_defaultWebChatContai2 = defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai2 === void 0 ? void 0 : _defaultWebChatContai2.groupActivitiesMiddleware,
131
- typingIndicatorMiddleware: (_props$webChatContain21 = props.webChatContainerProps) !== null && _props$webChatContain21 !== void 0 && (_props$webChatContain22 = _props$webChatContain21.renderingMiddlewareProps) !== null && _props$webChatContain22 !== void 0 && _props$webChatContain22.disableTypingIndicatorMiddleware ? undefined : (_defaultWebChatContai3 = defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai3 === void 0 ? void 0 : _defaultWebChatContai3.typingIndicatorMiddleware,
135
+ avatarMiddleware: (_props$webChatContain19 = props.webChatContainerProps) !== null && _props$webChatContain19 !== void 0 && (_props$webChatContain20 = _props$webChatContain19.renderingMiddlewareProps) !== null && _props$webChatContain20 !== void 0 && _props$webChatContain20.disableAvatarMiddleware ? undefined : createAvatarMiddleware((_state$domainStates$r5 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r5 === void 0 ? void 0 : _state$domainStates$r5.avatarStyleProps, (_state$domainStates$r6 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r6 === void 0 ? void 0 : _state$domainStates$r6.avatarTextStyleProps),
136
+ groupActivitiesMiddleware: (_props$webChatContain21 = props.webChatContainerProps) !== null && _props$webChatContain21 !== void 0 && (_props$webChatContain22 = _props$webChatContain21.renderingMiddlewareProps) !== null && _props$webChatContain22 !== void 0 && _props$webChatContain22.disableGroupActivitiesMiddleware ? undefined : (_defaultWebChatContai2 = defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai2 === void 0 ? void 0 : _defaultWebChatContai2.groupActivitiesMiddleware,
137
+ typingIndicatorMiddleware: (_props$webChatContain23 = props.webChatContainerProps) !== null && _props$webChatContain23 !== void 0 && (_props$webChatContain24 = _props$webChatContain23.renderingMiddlewareProps) !== null && _props$webChatContain24 !== void 0 && _props$webChatContain24.disableTypingIndicatorMiddleware ? undefined : (_defaultWebChatContai3 = defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai3 === void 0 ? void 0 : _defaultWebChatContai3.typingIndicatorMiddleware,
132
138
  onTelemetry: createWebChatTelemetry(),
133
- cardActionMiddleware: createCardActionMiddleware(((_props$webChatContain23 = props.webChatContainerProps) === null || _props$webChatContain23 === void 0 ? void 0 : _props$webChatContain23.botMagicCode) || undefined),
139
+ cardActionMiddleware: createCardActionMiddleware(((_props$webChatContain25 = props.webChatContainerProps) === null || _props$webChatContain25 === void 0 ? void 0 : _props$webChatContain25.botMagicCode) || undefined),
134
140
  sendTypingIndicator: true,
135
- ...((_props$webChatContain24 = props.webChatContainerProps) === null || _props$webChatContain24 === void 0 ? void 0 : _props$webChatContain24.webChatProps)
141
+ ...((_props$webChatContain26 = props.webChatContainerProps) === null || _props$webChatContain26 === void 0 ? void 0 : _props$webChatContain26.webChatProps)
136
142
  };
137
143
  return webChatProps;
138
144
  };
@@ -9,6 +9,8 @@ export const defaultWebChatContainerStatefulProps = {
9
9
  containerStyles: defaultWebChatStatefulContainerStyles,
10
10
  disableNewLineMarkdownSupport: false,
11
11
  disableMarkdownMessageFormatting: false,
12
+ opensMarkdownLinksInSameTab: false,
13
+ honorsTargetInHTMLLinks: false,
12
14
  hyperlinkTextOverride: false,
13
15
  directLine: new MockAdapter(),
14
16
  adaptiveCardStyles: defaultAdaptiveCardStyles
@@ -11,7 +11,9 @@ class HyperlinkTextOverrideRenderer {
11
11
  convertTextToHtmlNode(text) {
12
12
  const htmlNode = document.createElement(HtmlAttributeNames.div);
13
13
  try {
14
- text = DOMPurify.sanitize(text); // eslint-disable-line @typescript-eslint/no-explicit-any
14
+ text = DOMPurify.sanitize(text, {
15
+ ADD_ATTR: ["target"]
16
+ });
15
17
  htmlNode.innerHTML = text;
16
18
  } catch {
17
19
  return htmlNode;
@@ -16,8 +16,9 @@ const convertTextToHtmlNode = text => {
16
16
  if (!text) return "";
17
17
  const element = document.createElement(HtmlAttributeNames.div);
18
18
  try {
19
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
- text = DOMPurify.sanitize(text);
19
+ text = DOMPurify.sanitize(text, {
20
+ ADD_ATTR: ["target"]
21
+ });
21
22
  element.innerHTML = text;
22
23
  } catch (e) {
23
24
  const errorMessage = `Failed to purify and set innertHTML with text: ${text}`;
@@ -33,7 +34,7 @@ const convertTextToHtmlNode = text => {
33
34
  };
34
35
 
35
36
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- const processHTMLText = (action, text) => {
37
+ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
37
38
  const htmlNode = convertTextToHtmlNode(text);
38
39
  const aNodes = htmlNode.getElementsByTagName(HtmlAttributeNames.aTagName);
39
40
  if ((aNodes === null || aNodes === void 0 ? void 0 : aNodes.length) > 0) {
@@ -46,8 +47,8 @@ const processHTMLText = (action, text) => {
46
47
  continue;
47
48
  }
48
49
 
49
- // Add target to 'a' node if target is missing or does not equal to blank
50
- if (!aNode.target || aNode.target !== Constants.blank) {
50
+ // Add target to 'a' node if target is missing or if honorsTargetInHTMLLinks is false
51
+ if (!aNode.target || !honorsTargetInHTMLLinks) {
51
52
  aNode.target = Constants.blank;
52
53
  }
53
54
 
@@ -86,7 +87,7 @@ const processHTMLText = (action, text) => {
86
87
  };
87
88
 
88
89
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
89
- const htmlTextMiddleware = _ref => {
90
+ const htmlTextMiddleware = honorsTargetInHTMLLinks => _ref => {
90
91
  let {
91
92
  dispatch
92
93
  } = _ref;
@@ -96,7 +97,7 @@ const htmlTextMiddleware = _ref => {
96
97
  var _action$payload, _action$payload$activ;
97
98
  const text = (_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : (_action$payload$activ = _action$payload.activity) === null || _action$payload$activ === void 0 ? void 0 : _action$payload$activ.text;
98
99
  if (text) {
99
- action = processHTMLText(action, text);
100
+ action = processHTMLText(action, text, honorsTargetInHTMLLinks ?? false);
100
101
  }
101
102
  } catch (e) {
102
103
  let errorMessage = "Failed to validate action.";
@@ -20,7 +20,9 @@ const sanitizationMiddleware = _ref => {
20
20
  var _action$payload;
21
21
  let text = (_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : _action$payload.text;
22
22
  if (text) {
23
- text = DOMPurify.sanitize(text) ?? " ";
23
+ text = DOMPurify.sanitize(text, {
24
+ ADD_ATTR: ["target"]
25
+ }) ?? " ";
24
26
  }
25
27
  } catch (e) {
26
28
  const copyDataForTelemetry = {
@@ -74,6 +74,8 @@ export declare class Constants {
74
74
  static readonly Title = "title";
75
75
  static readonly Target = "target";
76
76
  static readonly Blank = "_blank";
77
+ static readonly TargetSelf = "_self";
78
+ static readonly TargetTop = "_top";
77
79
  static readonly TargetRelationship = "rel";
78
80
  static readonly TargetRelationshipAttributes = "noopener noreferrer";
79
81
  static readonly OpenLinkIconCssClass = "webchat__render-markdown__external-link-icon";
@@ -1,2 +1,2 @@
1
1
  import MarkdownIt from "markdown-it";
2
- export declare const createMarkdown: (disableMarkdownMessageFormatting: boolean, disableNewLineMarkdownSupport: boolean) => MarkdownIt;
2
+ export declare const createMarkdown: (disableMarkdownMessageFormatting: boolean, disableNewLineMarkdownSupport: boolean, opensMarkdownLinksInSameTab?: boolean) => MarkdownIt;
@@ -11,6 +11,8 @@ export interface IWebChatContainerStatefulProps {
11
11
  containerStyles?: IStyle;
12
12
  disableNewLineMarkdownSupport?: boolean;
13
13
  disableMarkdownMessageFormatting?: boolean;
14
+ opensMarkdownLinksInSameTab?: boolean;
15
+ honorsTargetInHTMLLinks?: boolean;
14
16
  webChatStyles?: StyleOptions;
15
17
  webChatProps?: IWebChatProps;
16
18
  directLine?: any;
@@ -4,7 +4,7 @@
4
4
  * Ensures that links within messages are processed so that the caller website cannot be traced.
5
5
  ******/
6
6
  import { IWebChatAction } from "../../../interfaces/IWebChatAction";
7
- declare const htmlTextMiddleware: ({ dispatch }: {
7
+ declare const htmlTextMiddleware: (honorsTargetInHTMLLinks?: boolean) => ({ dispatch }: {
8
8
  dispatch: any;
9
9
  }) => (next: any) => (action: IWebChatAction) => any;
10
10
  export default htmlTextMiddleware;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.7.7-main.863787d",
3
+ "version": "1.7.7-main.bdac0a6",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",