@microsoft/omnichannel-chat-widget 1.7.7-main.863787d → 1.7.7-main.a833758
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/common/Constants.js +3 -0
- package/lib/cjs/common/utils.js +14 -2
- package/lib/cjs/components/livechatwidget/common/createMarkdown.js +4 -3
- package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +27 -22
- package/lib/cjs/components/prechatsurveypanestateful/PreChatSurveyPaneStateful.js +10 -5
- package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +13 -1
- package/lib/cjs/components/webchatcontainerstateful/common/defaultProps/defaultWebChatContainerStatefulProps.js +2 -0
- package/lib/cjs/components/webchatcontainerstateful/common/defaultStyles/defaultWebChatStyles.js +1 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer.js +3 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +15 -2
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.js +9 -10
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware.js +3 -1
- package/lib/cjs/plugins/createChatTranscript.js +5 -1
- package/lib/esm/common/Constants.js +3 -0
- package/lib/esm/common/utils.js +11 -1
- package/lib/esm/components/livechatwidget/common/createMarkdown.js +4 -3
- package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +28 -22
- package/lib/esm/components/prechatsurveypanestateful/PreChatSurveyPaneStateful.js +10 -5
- package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +15 -3
- package/lib/esm/components/webchatcontainerstateful/common/defaultProps/defaultWebChatContainerStatefulProps.js +2 -0
- package/lib/esm/components/webchatcontainerstateful/common/defaultStyles/defaultWebChatStyles.js +1 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer.js +3 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +15 -2
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.js +9 -10
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware.js +3 -1
- package/lib/esm/plugins/createChatTranscript.js +5 -1
- package/lib/types/common/Constants.d.ts +3 -0
- package/lib/types/common/facades/FacadeChatSDK.d.ts +1 -1
- package/lib/types/common/utils.d.ts +1 -0
- package/lib/types/components/livechatwidget/common/createMarkdown.d.ts +1 -1
- package/lib/types/components/webchatcontainerstateful/interfaces/IWebChatContainerStatefulProps.d.ts +3 -0
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.d.ts +1 -1
- package/package.json +2 -2
|
@@ -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
|
|
@@ -130,6 +132,7 @@ class HtmlClassNames {}
|
|
|
130
132
|
exports.HtmlClassNames = HtmlClassNames;
|
|
131
133
|
_defineProperty(HtmlClassNames, "webChatBannerCloseButton", "webchat__toast__dismissButton");
|
|
132
134
|
_defineProperty(HtmlClassNames, "webChatBannerExpandButton", "webchat__toaster__expandIcon");
|
|
135
|
+
_defineProperty(HtmlClassNames, "webChatHistoryContainer", "webchat__basic-transcript");
|
|
133
136
|
class HtmlElementSelectors {}
|
|
134
137
|
exports.HtmlElementSelectors = HtmlElementSelectors;
|
|
135
138
|
_defineProperty(HtmlElementSelectors, "sendBoxSelector", "textarea[data-id=\"webchat-sendbox-input\"]");
|
package/lib/cjs/common/utils.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.getConversationDetailsCall = exports.getBroadcastChannelName = exports.formatTemplateString = exports.findParentFocusableElementsWithoutChildContainer = exports.findAllFocusableElement = exports.extractPreChatSurveyResponseValues = exports.escapeHtml = exports.debounceLeading = exports.createTimer = exports.createFileAndDownload = exports.checkContactIdError = exports.changeLanguageCodeFormatForWebChat = exports.addDelayInMs = void 0;
|
|
7
|
+
exports.getDeviceType = getDeviceType;
|
|
8
|
+
exports.setTabIndices = exports.setOcUserAgent = exports.setFocusOnSendBox = exports.setFocusOnElement = exports.preventFocusToMoveOutOfElement = exports.parseLowerCaseString = exports.parseAdaptiveCardPayload = exports.newGuid = exports.isUndefinedOrEmpty = exports.isThisSessionPopout = exports.isNullOrUndefined = exports.isNullOrEmptyString = exports.getWidgetEndChatEventName = exports.getWidgetCacheIdfromProps = exports.getWidgetCacheId = exports.getTimestampHourMinute = exports.getStateFromCache = exports.getLocaleDirection = exports.getIconText = exports.getDomain = void 0;
|
|
7
9
|
var _Constants = require("./Constants");
|
|
8
10
|
var _TelemetryConstants = require("./telemetry/TelemetryConstants");
|
|
9
11
|
var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
|
|
@@ -479,4 +481,14 @@ const setOcUserAgent = chatSDK => {
|
|
|
479
481
|
}
|
|
480
482
|
}
|
|
481
483
|
};
|
|
482
|
-
exports.setOcUserAgent = setOcUserAgent;
|
|
484
|
+
exports.setOcUserAgent = setOcUserAgent;
|
|
485
|
+
function getDeviceType() {
|
|
486
|
+
const userAgent = navigator.userAgent.toLowerCase();
|
|
487
|
+
if (/android/.test(userAgent)) {
|
|
488
|
+
return "android";
|
|
489
|
+
} else if (/iphone|ipad|ipod/.test(userAgent)) {
|
|
490
|
+
return "ios";
|
|
491
|
+
} else {
|
|
492
|
+
return "standard";
|
|
493
|
+
}
|
|
494
|
+
}
|
|
@@ -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] =
|
|
50
|
+
tokens[idx].attrs[targetAttrIndex][1] = targetValue;
|
|
50
51
|
} else {
|
|
51
|
-
tokens[idx].attrPush([_Constants.Constants.Target,
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
99
|
-
if ((_props$
|
|
100
|
-
var _props$
|
|
101
|
-
text = (_props$
|
|
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
|
-
|
|
119
|
-
if (
|
|
120
|
-
node.setAttribute(
|
|
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$
|
|
131
|
-
attachmentMiddleware: (_props$
|
|
132
|
-
activityStatusMiddleware: (_props$
|
|
133
|
-
toastMiddleware: (_props$
|
|
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$
|
|
136
|
-
groupActivitiesMiddleware: (_props$
|
|
137
|
-
typingIndicatorMiddleware: (_props$
|
|
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$
|
|
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$
|
|
146
|
+
...((_props$webChatContain26 = props.webChatContainerProps) === null || _props$webChatContain26 === void 0 ? void 0 : _props$webChatContain26.webChatProps)
|
|
142
147
|
};
|
|
143
148
|
return webChatProps;
|
|
144
149
|
};
|
|
@@ -145,11 +145,6 @@ const PreChatSurveyPaneStateful = props => {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
-
// Move focus to the first button
|
|
149
|
-
const firstElement = (0, _utils.findAllFocusableElement)(`#${controlProps.id}`);
|
|
150
|
-
if (firstElement && firstElement[0]) {
|
|
151
|
-
firstElement[0].focus();
|
|
152
|
-
}
|
|
153
148
|
_TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
|
|
154
149
|
Event: _TelemetryConstants.TelemetryEvent.PrechatSurveyLoaded
|
|
155
150
|
});
|
|
@@ -158,6 +153,16 @@ const PreChatSurveyPaneStateful = props => {
|
|
|
158
153
|
ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
|
|
159
154
|
});
|
|
160
155
|
}, []);
|
|
156
|
+
|
|
157
|
+
// Set focus to the first element
|
|
158
|
+
(0, _react.useEffect)(() => {
|
|
159
|
+
if (!state.appStates.isMinimized) {
|
|
160
|
+
const firstElement = (0, _utils.findAllFocusableElement)(`#${controlProps.id}`);
|
|
161
|
+
if (firstElement && firstElement[0]) {
|
|
162
|
+
firstElement[0].focus();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}, [state.appStates.isMinimized]);
|
|
161
166
|
return /*#__PURE__*/_react.default.createElement(_omnichannelChatComponents.PreChatSurveyPane, {
|
|
162
167
|
controlProps: controlProps,
|
|
163
168
|
styleProps: styleProps
|
|
@@ -83,7 +83,12 @@ const WebChatContainerStateful = props => {
|
|
|
83
83
|
};
|
|
84
84
|
(0, _react2.useEffect)(() => {
|
|
85
85
|
var _props$webChatContain, _props$webChatContain2;
|
|
86
|
-
(0, _utils.
|
|
86
|
+
if ((0, _utils.getDeviceType)() !== "standard" && (webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.webChatHistoryMobileAccessibilityLabel) !== undefined) {
|
|
87
|
+
const chatHistoryElement = document.querySelector(`.${_Constants.HtmlClassNames.webChatHistoryContainer}`);
|
|
88
|
+
if (chatHistoryElement) {
|
|
89
|
+
chatHistoryElement.setAttribute(_Constants.HtmlAttributeNames.ariaLabel, webChatContainerProps.webChatHistoryMobileAccessibilityLabel);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
87
92
|
dispatch({
|
|
88
93
|
type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_RENDERING_MIDDLEWARE_PROPS,
|
|
89
94
|
payload: webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.renderingMiddlewareProps
|
|
@@ -164,6 +169,13 @@ const WebChatContainerStateful = props => {
|
|
|
164
169
|
ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
|
|
165
170
|
});
|
|
166
171
|
}, []);
|
|
172
|
+
|
|
173
|
+
// Set focus to the sendbox
|
|
174
|
+
(0, _react2.useEffect)(() => {
|
|
175
|
+
if (!state.appStates.isMinimized) {
|
|
176
|
+
(0, _utils.setFocusOnSendBox)();
|
|
177
|
+
}
|
|
178
|
+
}, [state.appStates.isMinimized]);
|
|
167
179
|
return /*#__PURE__*/_react2.default.createElement(_react2.default.Fragment, null, /*#__PURE__*/_react2.default.createElement("style", null, `
|
|
168
180
|
.webchat__stacked-layout__content .ac-pushButton {
|
|
169
181
|
cursor: pointer;
|
|
@@ -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
|
|
21
|
+
text = _dompurify.default.sanitize(text, {
|
|
22
|
+
ADD_ATTR: ["target"]
|
|
23
|
+
});
|
|
22
24
|
htmlNode.innerHTML = text;
|
|
23
25
|
} catch {
|
|
24
26
|
return htmlNode;
|
|
@@ -31,15 +31,28 @@ const DeliveredTimestamp = _ref => {
|
|
|
31
31
|
timestamp
|
|
32
32
|
}
|
|
33
33
|
} = args;
|
|
34
|
+
const getTimeElement = timestamp => {
|
|
35
|
+
const timeString = (0, _utils.getTimestampHourMinute)(timestamp);
|
|
36
|
+
const isAmPmFormat = timeString.toLowerCase().includes("am") || timeString.toLowerCase().includes("pm");
|
|
37
|
+
|
|
38
|
+
// For clients that use languages that are written right-to-left, but still use AM/PM time format, we need to
|
|
39
|
+
// make sure the "rtl" direction doesn't produce "PM 1:23", but remains "1:23 PM"
|
|
40
|
+
if (dir === "rtl" && isAmPmFormat) {
|
|
41
|
+
return /*#__PURE__*/_react.default.createElement("span", {
|
|
42
|
+
dir: "ltr"
|
|
43
|
+
}, (0, _utils.getTimestampHourMinute)(timestamp));
|
|
44
|
+
}
|
|
45
|
+
return timeString;
|
|
46
|
+
};
|
|
34
47
|
return /*#__PURE__*/_react.default.createElement(_react2.Stack, {
|
|
35
48
|
style: contentStyles,
|
|
36
49
|
dir: dir
|
|
37
50
|
}, role === _DirectLineSenderRole.DirectLineSenderRole.Bot && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
|
|
38
51
|
dir: dir,
|
|
39
52
|
"aria-hidden": "false"
|
|
40
|
-
}, name, " - ", (
|
|
53
|
+
}, name, " - ", getTimeElement(timestamp))), role === _DirectLineSenderRole.DirectLineSenderRole.User && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
|
|
41
54
|
"aria-hidden": "false",
|
|
42
55
|
dir: dir
|
|
43
|
-
}, " ", (
|
|
56
|
+
}, " ", getTimeElement(timestamp), " - ", ((_state$domainStates$m = state.domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_MESSAGE_DELIVERED) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_MESSAGE_DELIVERED)));
|
|
44
57
|
};
|
|
45
58
|
exports.DeliveredTimestamp = DeliveredTimestamp;
|
|
@@ -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
|
-
|
|
26
|
-
|
|
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
|
|
56
|
-
if (!aNode.target ||
|
|
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
|
|
|
@@ -69,9 +70,6 @@ const processHTMLText = (action, text) => {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
|
-
|
|
73
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
74
|
-
action = (0, _simpleUpdateIn.default)(action, [_Constants.Constants.payload, _Constants.Constants.activity, _Constants.Constants.text], () => htmlNode.innerHTML);
|
|
75
73
|
} catch (e) {
|
|
76
74
|
let errorMessage = "Failed to apply action: ";
|
|
77
75
|
try {
|
|
@@ -88,11 +86,12 @@ const processHTMLText = (action, text) => {
|
|
|
88
86
|
});
|
|
89
87
|
}
|
|
90
88
|
}
|
|
89
|
+
action = (0, _simpleUpdateIn.default)(action, [_Constants.Constants.payload, _Constants.Constants.activity, _Constants.Constants.text], () => htmlNode.innerHTML);
|
|
91
90
|
return action;
|
|
92
91
|
};
|
|
93
92
|
|
|
94
93
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
95
|
-
const htmlTextMiddleware = _ref => {
|
|
94
|
+
const htmlTextMiddleware = honorsTargetInHTMLLinks => _ref => {
|
|
96
95
|
let {
|
|
97
96
|
dispatch
|
|
98
97
|
} = _ref;
|
|
@@ -102,7 +101,7 @@ const htmlTextMiddleware = _ref => {
|
|
|
102
101
|
var _action$payload, _action$payload$activ;
|
|
103
102
|
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
103
|
if (text) {
|
|
105
|
-
action = processHTMLText(action, text);
|
|
104
|
+
action = processHTMLText(action, text, honorsTargetInHTMLLinks ?? false);
|
|
106
105
|
}
|
|
107
106
|
} catch (e) {
|
|
108
107
|
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 = {
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _utils = require("../common/utils");
|
|
8
8
|
var _defaultLibraryScripts = _interopRequireDefault(require("../components/footerstateful/downloadtranscriptstateful/common/defaultLibraryScripts"));
|
|
9
|
+
var _dompurify = _interopRequireDefault(require("dompurify"));
|
|
9
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
11
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
11
12
|
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
@@ -674,7 +675,10 @@ const createChatTranscript = async function (transcript, facadeChatSDK) {
|
|
|
674
675
|
reader.readAsDataURL(blob);
|
|
675
676
|
});
|
|
676
677
|
};
|
|
677
|
-
let messages = transcriptMessages
|
|
678
|
+
let messages = transcriptMessages.filter(message => {
|
|
679
|
+
message.content = _dompurify.default.sanitize(message.content);
|
|
680
|
+
return message.content.length > 0;
|
|
681
|
+
});
|
|
678
682
|
if (renderAttachments) {
|
|
679
683
|
messages = await Promise.all(transcriptMessages.map(async message => {
|
|
680
684
|
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
@@ -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
|
|
@@ -120,6 +122,7 @@ _defineProperty(HtmlIdNames, "MSLiveChatWidget", "MSLiveChatWidget");
|
|
|
120
122
|
export class HtmlClassNames {}
|
|
121
123
|
_defineProperty(HtmlClassNames, "webChatBannerCloseButton", "webchat__toast__dismissButton");
|
|
122
124
|
_defineProperty(HtmlClassNames, "webChatBannerExpandButton", "webchat__toaster__expandIcon");
|
|
125
|
+
_defineProperty(HtmlClassNames, "webChatHistoryContainer", "webchat__basic-transcript");
|
|
123
126
|
export class HtmlElementSelectors {}
|
|
124
127
|
_defineProperty(HtmlElementSelectors, "sendBoxSelector", "textarea[data-id=\"webchat-sendbox-input\"]");
|
|
125
128
|
export class HtmlAttributeNames {}
|
package/lib/esm/common/utils.js
CHANGED
|
@@ -440,4 +440,14 @@ export const setOcUserAgent = chatSDK => {
|
|
|
440
440
|
console.warn(error);
|
|
441
441
|
}
|
|
442
442
|
}
|
|
443
|
-
};
|
|
443
|
+
};
|
|
444
|
+
export function getDeviceType() {
|
|
445
|
+
const userAgent = navigator.userAgent.toLowerCase();
|
|
446
|
+
if (/android/.test(userAgent)) {
|
|
447
|
+
return "android";
|
|
448
|
+
} else if (/iphone|ipad|ipod/.test(userAgent)) {
|
|
449
|
+
return "ios";
|
|
450
|
+
} else {
|
|
451
|
+
return "standard";
|
|
452
|
+
}
|
|
453
|
+
}
|
|
@@ -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] =
|
|
44
|
+
tokens[idx].attrs[targetAttrIndex][1] = targetValue;
|
|
44
45
|
} else {
|
|
45
|
-
tokens[idx].attrPush([Constants.Target,
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
93
|
-
if ((_props$
|
|
94
|
-
var _props$
|
|
95
|
-
text = (_props$
|
|
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
|
-
|
|
113
|
-
if (
|
|
114
|
-
node.setAttribute(
|
|
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$
|
|
125
|
-
attachmentMiddleware: (_props$
|
|
126
|
-
activityStatusMiddleware: (_props$
|
|
127
|
-
toastMiddleware: (_props$
|
|
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$
|
|
130
|
-
groupActivitiesMiddleware: (_props$
|
|
131
|
-
typingIndicatorMiddleware: (_props$
|
|
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$
|
|
139
|
+
cardActionMiddleware: createCardActionMiddleware(((_props$webChatContain25 = props.webChatContainerProps) === null || _props$webChatContain25 === void 0 ? void 0 : _props$webChatContain25.botMagicCode) || undefined),
|
|
134
140
|
sendTypingIndicator: true,
|
|
135
|
-
...((_props$
|
|
141
|
+
...((_props$webChatContain26 = props.webChatContainerProps) === null || _props$webChatContain26 === void 0 ? void 0 : _props$webChatContain26.webChatProps)
|
|
136
142
|
};
|
|
137
143
|
return webChatProps;
|
|
138
144
|
};
|
|
@@ -136,11 +136,6 @@ export const PreChatSurveyPaneStateful = props => {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
-
// Move focus to the first button
|
|
140
|
-
const firstElement = findAllFocusableElement(`#${controlProps.id}`);
|
|
141
|
-
if (firstElement && firstElement[0]) {
|
|
142
|
-
firstElement[0].focus();
|
|
143
|
-
}
|
|
144
139
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
145
140
|
Event: TelemetryEvent.PrechatSurveyLoaded
|
|
146
141
|
});
|
|
@@ -149,6 +144,16 @@ export const PreChatSurveyPaneStateful = props => {
|
|
|
149
144
|
ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
|
|
150
145
|
});
|
|
151
146
|
}, []);
|
|
147
|
+
|
|
148
|
+
// Set focus to the first element
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (!state.appStates.isMinimized) {
|
|
151
|
+
const firstElement = findAllFocusableElement(`#${controlProps.id}`);
|
|
152
|
+
if (firstElement && firstElement[0]) {
|
|
153
|
+
firstElement[0].focus();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}, [state.appStates.isMinimized]);
|
|
152
157
|
return /*#__PURE__*/React.createElement(PreChatSurveyPane, {
|
|
153
158
|
controlProps: controlProps,
|
|
154
159
|
styleProps: styleProps
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
import { Stack } from "@fluentui/react";
|
|
4
4
|
import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
|
|
5
5
|
import React, { useEffect } from "react";
|
|
6
|
-
import { createTimer, setFocusOnSendBox } from "../../common/utils";
|
|
6
|
+
import { createTimer, getDeviceType, setFocusOnSendBox } from "../../common/utils";
|
|
7
7
|
import { BotMagicCodeStore } from "./webchatcontroller/BotMagicCodeStore";
|
|
8
8
|
import { Components } from "botframework-webchat";
|
|
9
|
-
import { Constants } from "../../common/Constants";
|
|
9
|
+
import { Constants, HtmlAttributeNames, HtmlClassNames } from "../../common/Constants";
|
|
10
10
|
import { LiveChatWidgetActionType } from "../../contexts/common/LiveChatWidgetActionType";
|
|
11
11
|
import { NotificationHandler } from "./webchatcontroller/notification/NotificationHandler";
|
|
12
12
|
import { NotificationScenarios } from "./webchatcontroller/enums/NotificationScenarios";
|
|
@@ -75,7 +75,12 @@ export const WebChatContainerStateful = props => {
|
|
|
75
75
|
};
|
|
76
76
|
useEffect(() => {
|
|
77
77
|
var _props$webChatContain, _props$webChatContain2;
|
|
78
|
-
|
|
78
|
+
if (getDeviceType() !== "standard" && (webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.webChatHistoryMobileAccessibilityLabel) !== undefined) {
|
|
79
|
+
const chatHistoryElement = document.querySelector(`.${HtmlClassNames.webChatHistoryContainer}`);
|
|
80
|
+
if (chatHistoryElement) {
|
|
81
|
+
chatHistoryElement.setAttribute(HtmlAttributeNames.ariaLabel, webChatContainerProps.webChatHistoryMobileAccessibilityLabel);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
79
84
|
dispatch({
|
|
80
85
|
type: LiveChatWidgetActionType.SET_RENDERING_MIDDLEWARE_PROPS,
|
|
81
86
|
payload: webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.renderingMiddlewareProps
|
|
@@ -156,6 +161,13 @@ export const WebChatContainerStateful = props => {
|
|
|
156
161
|
ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
|
|
157
162
|
});
|
|
158
163
|
}, []);
|
|
164
|
+
|
|
165
|
+
// Set focus to the sendbox
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
if (!state.appStates.isMinimized) {
|
|
168
|
+
setFocusOnSendBox();
|
|
169
|
+
}
|
|
170
|
+
}, [state.appStates.isMinimized]);
|
|
159
171
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, `
|
|
160
172
|
.webchat__stacked-layout__content .ac-pushButton {
|
|
161
173
|
cursor: pointer;
|
|
@@ -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
|
|
14
|
+
text = DOMPurify.sanitize(text, {
|
|
15
|
+
ADD_ATTR: ["target"]
|
|
16
|
+
});
|
|
15
17
|
htmlNode.innerHTML = text;
|
|
16
18
|
} catch {
|
|
17
19
|
return htmlNode;
|
|
@@ -25,14 +25,27 @@ export const DeliveredTimestamp = _ref => {
|
|
|
25
25
|
timestamp
|
|
26
26
|
}
|
|
27
27
|
} = args;
|
|
28
|
+
const getTimeElement = timestamp => {
|
|
29
|
+
const timeString = getTimestampHourMinute(timestamp);
|
|
30
|
+
const isAmPmFormat = timeString.toLowerCase().includes("am") || timeString.toLowerCase().includes("pm");
|
|
31
|
+
|
|
32
|
+
// For clients that use languages that are written right-to-left, but still use AM/PM time format, we need to
|
|
33
|
+
// make sure the "rtl" direction doesn't produce "PM 1:23", but remains "1:23 PM"
|
|
34
|
+
if (dir === "rtl" && isAmPmFormat) {
|
|
35
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
36
|
+
dir: "ltr"
|
|
37
|
+
}, getTimestampHourMinute(timestamp));
|
|
38
|
+
}
|
|
39
|
+
return timeString;
|
|
40
|
+
};
|
|
28
41
|
return /*#__PURE__*/React.createElement(Stack, {
|
|
29
42
|
style: contentStyles,
|
|
30
43
|
dir: dir
|
|
31
44
|
}, role === DirectLineSenderRole.Bot && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
|
32
45
|
dir: dir,
|
|
33
46
|
"aria-hidden": "false"
|
|
34
|
-
}, name, " - ",
|
|
47
|
+
}, name, " - ", getTimeElement(timestamp))), role === DirectLineSenderRole.User && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
|
35
48
|
"aria-hidden": "false",
|
|
36
49
|
dir: dir
|
|
37
|
-
}, " ",
|
|
50
|
+
}, " ", getTimeElement(timestamp), " - ", ((_state$domainStates$m = state.domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_MESSAGE_DELIVERED) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_MESSAGE_DELIVERED)));
|
|
38
51
|
};
|
|
@@ -16,8 +16,9 @@ const convertTextToHtmlNode = text => {
|
|
|
16
16
|
if (!text) return "";
|
|
17
17
|
const element = document.createElement(HtmlAttributeNames.div);
|
|
18
18
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
50
|
-
if (!aNode.target ||
|
|
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
|
|
|
@@ -63,9 +64,6 @@ const processHTMLText = (action, text) => {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
-
action = updateIn(action, [Constants.payload, Constants.activity, Constants.text], () => htmlNode.innerHTML);
|
|
69
67
|
} catch (e) {
|
|
70
68
|
let errorMessage = "Failed to apply action: ";
|
|
71
69
|
try {
|
|
@@ -82,11 +80,12 @@ const processHTMLText = (action, text) => {
|
|
|
82
80
|
});
|
|
83
81
|
}
|
|
84
82
|
}
|
|
83
|
+
action = updateIn(action, [Constants.payload, Constants.activity, Constants.text], () => htmlNode.innerHTML);
|
|
85
84
|
return action;
|
|
86
85
|
};
|
|
87
86
|
|
|
88
87
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
89
|
-
const htmlTextMiddleware = _ref => {
|
|
88
|
+
const htmlTextMiddleware = honorsTargetInHTMLLinks => _ref => {
|
|
90
89
|
let {
|
|
91
90
|
dispatch
|
|
92
91
|
} = _ref;
|
|
@@ -96,7 +95,7 @@ const htmlTextMiddleware = _ref => {
|
|
|
96
95
|
var _action$payload, _action$payload$activ;
|
|
97
96
|
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
97
|
if (text) {
|
|
99
|
-
action = processHTMLText(action, text);
|
|
98
|
+
action = processHTMLText(action, text, honorsTargetInHTMLLinks ?? false);
|
|
100
99
|
}
|
|
101
100
|
} catch (e) {
|
|
102
101
|
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 = {
|
|
@@ -5,6 +5,7 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
|
|
|
5
5
|
|
|
6
6
|
import { createFileAndDownload } from "../common/utils";
|
|
7
7
|
import defaultLibraryScripts from "../components/footerstateful/downloadtranscriptstateful/common/defaultLibraryScripts";
|
|
8
|
+
import DOMPurify from "dompurify";
|
|
8
9
|
class TranscriptHTMLBuilder {
|
|
9
10
|
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
10
11
|
|
|
@@ -669,7 +670,10 @@ const createChatTranscript = async function (transcript, facadeChatSDK) {
|
|
|
669
670
|
reader.readAsDataURL(blob);
|
|
670
671
|
});
|
|
671
672
|
};
|
|
672
|
-
let messages = transcriptMessages
|
|
673
|
+
let messages = transcriptMessages.filter(message => {
|
|
674
|
+
message.content = DOMPurify.sanitize(message.content);
|
|
675
|
+
return message.content.length > 0;
|
|
676
|
+
});
|
|
673
677
|
if (renderAttachments) {
|
|
674
678
|
messages = await Promise.all(transcriptMessages.map(async message => {
|
|
675
679
|
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
@@ -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";
|
|
@@ -102,6 +104,7 @@ export declare class HtmlIdNames {
|
|
|
102
104
|
export declare class HtmlClassNames {
|
|
103
105
|
static readonly webChatBannerCloseButton = "webchat__toast__dismissButton";
|
|
104
106
|
static readonly webChatBannerExpandButton = "webchat__toaster__expandIcon";
|
|
107
|
+
static readonly webChatHistoryContainer = "webchat__basic-transcript";
|
|
105
108
|
}
|
|
106
109
|
export declare class HtmlElementSelectors {
|
|
107
110
|
static readonly sendBoxSelector = "textarea[data-id=\"webchat-sendbox-input\"]";
|
|
@@ -57,7 +57,7 @@ export declare class FacadeChatSDK {
|
|
|
57
57
|
getCallingToken(): Promise<string>;
|
|
58
58
|
getMessages(): Promise<IMessage[] | OmnichannelMessage[] | undefined>;
|
|
59
59
|
getDataMaskingRules(): Promise<MaskingRules>;
|
|
60
|
-
sendMessage(message: ChatSDKMessage): Promise<void>;
|
|
60
|
+
sendMessage(message: ChatSDKMessage): Promise<void | OmnichannelMessage>;
|
|
61
61
|
onNewMessage(onNewMessageCallback: CallableFunction, optionalParams?: OnNewMessageOptionalParams): Promise<void>;
|
|
62
62
|
sendTypingEvent(): Promise<void>;
|
|
63
63
|
onTypingEvent(onTypingEventCallback: CallableFunction): Promise<void>;
|
|
@@ -46,3 +46,4 @@ export declare const createFileAndDownload: (fileName: string, blobData: string,
|
|
|
46
46
|
export declare const formatTemplateString: (templateMessage: string, values: any) => string;
|
|
47
47
|
export declare const parseLowerCaseString: (property: string | boolean | undefined) => string;
|
|
48
48
|
export declare const setOcUserAgent: (chatSDK: any) => void;
|
|
49
|
+
export declare function getDeviceType(): string;
|
|
@@ -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;
|
package/lib/types/components/webchatcontainerstateful/interfaces/IWebChatContainerStatefulProps.d.ts
CHANGED
|
@@ -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;
|
|
@@ -22,4 +24,5 @@ export interface IWebChatContainerStatefulProps {
|
|
|
22
24
|
hyperlinkTextOverride?: boolean;
|
|
23
25
|
adaptiveCardStyles?: IAdaptiveCardStyles;
|
|
24
26
|
sendBoxTextBox?: ISendBox;
|
|
27
|
+
webChatHistoryMobileAccessibilityLabel?: string;
|
|
25
28
|
}
|
|
@@ -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.
|
|
3
|
+
"version": "1.7.7-main.a833758",
|
|
4
4
|
"description": "Microsoft Omnichannel Chat Widget",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@azure/core-tracing": "^1.2.0",
|
|
80
80
|
"@microsoft/omnichannel-chat-components": "1.1.8",
|
|
81
|
-
"@microsoft/omnichannel-chat-sdk": "^1.10.
|
|
81
|
+
"@microsoft/omnichannel-chat-sdk": "^1.10.17",
|
|
82
82
|
"@opentelemetry/api": "^1.9.0",
|
|
83
83
|
"abort-controller-es5": "^2.0.1",
|
|
84
84
|
"dompurify": "^3.2.4",
|