botframework-webchat 4.14.1 → 4.15.2-main.20220413.af6e8a3

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 (108) hide show
  1. package/.eslintrc.yml +5 -109
  2. package/.prettierrc.yml +1 -1
  3. package/README.md +1 -1
  4. package/lib/AddFullBundle.d.ts.map +1 -1
  5. package/lib/AddFullBundle.js +1 -2
  6. package/lib/FullComposer.d.ts.map +1 -1
  7. package/lib/FullComposer.js +3 -3
  8. package/lib/FullReactWebChat.js +2 -2
  9. package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.d.ts +1 -1
  10. package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.d.ts.map +1 -1
  11. package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.js +3 -1
  12. package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.d.ts +1 -1
  13. package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.d.ts.map +1 -1
  14. package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.js +10 -3
  15. package/lib/adaptiveCards/Attachment/AdaptiveCardContent.js +2 -2
  16. package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.d.ts +3 -2
  17. package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.d.ts.map +1 -1
  18. package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.js +138 -74
  19. package/lib/adaptiveCards/Attachment/AnimationCardContent.d.ts +1 -1
  20. package/lib/adaptiveCards/Attachment/AnimationCardContent.d.ts.map +1 -1
  21. package/lib/adaptiveCards/Attachment/AnimationCardContent.js +3 -1
  22. package/lib/adaptiveCards/Attachment/AudioCardContent.d.ts +1 -1
  23. package/lib/adaptiveCards/Attachment/AudioCardContent.d.ts.map +1 -1
  24. package/lib/adaptiveCards/Attachment/AudioCardContent.js +3 -1
  25. package/lib/adaptiveCards/Attachment/HeroCardContent.d.ts +1 -1
  26. package/lib/adaptiveCards/Attachment/HeroCardContent.d.ts.map +1 -1
  27. package/lib/adaptiveCards/Attachment/HeroCardContent.js +4 -2
  28. package/lib/adaptiveCards/Attachment/OAuthCardContent.d.ts +1 -1
  29. package/lib/adaptiveCards/Attachment/OAuthCardContent.d.ts.map +1 -1
  30. package/lib/adaptiveCards/Attachment/OAuthCardContent.js +3 -1
  31. package/lib/adaptiveCards/Attachment/ReceiptCardContent.d.ts +1 -1
  32. package/lib/adaptiveCards/Attachment/ReceiptCardContent.d.ts.map +1 -1
  33. package/lib/adaptiveCards/Attachment/ReceiptCardContent.js +3 -1
  34. package/lib/adaptiveCards/Attachment/SignInCardContent.d.ts +1 -1
  35. package/lib/adaptiveCards/Attachment/SignInCardContent.d.ts.map +1 -1
  36. package/lib/adaptiveCards/Attachment/SignInCardContent.js +1 -1
  37. package/lib/adaptiveCards/Attachment/ThumbnailCardContent.d.ts +1 -1
  38. package/lib/adaptiveCards/Attachment/ThumbnailCardContent.d.ts.map +1 -1
  39. package/lib/adaptiveCards/Attachment/ThumbnailCardContent.js +3 -1
  40. package/lib/adaptiveCards/Attachment/VideoCardContent.d.ts +1 -1
  41. package/lib/adaptiveCards/Attachment/VideoCardContent.d.ts.map +1 -1
  42. package/lib/adaptiveCards/Attachment/VideoCardContent.js +5 -3
  43. package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.d.ts +3 -0
  44. package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.d.ts.map +1 -1
  45. package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.js +8 -1
  46. package/lib/adaptiveCards/Styles/adaptiveCardHostConfig.js +2 -2
  47. package/lib/adaptiveCards/Styles/createAdaptiveCardsStyleSet.js +2 -2
  48. package/lib/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.d.ts.map +1 -1
  49. package/lib/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js +26 -29
  50. package/lib/adaptiveCards/normalizeStyleOptions.js +2 -2
  51. package/lib/addVersion.js +2 -2
  52. package/lib/createDirectLineSpeechAdapters.d.ts +1 -1
  53. package/lib/createDirectLineSpeechAdapters.d.ts.map +1 -1
  54. package/lib/createDirectLineSpeechAdapters.js +1 -1
  55. package/lib/createFullStyleSet.d.ts +325 -56
  56. package/lib/createFullStyleSet.d.ts.map +1 -1
  57. package/lib/createFullStyleSet.js +2 -2
  58. package/lib/fullBundleDefaultStyleOptions.js +2 -2
  59. package/lib/index-es5.d.ts +1 -21
  60. package/lib/index-es5.d.ts.map +1 -1
  61. package/lib/index-es5.js +4 -44
  62. package/lib/index-minimal.js +22 -20
  63. package/lib/index.d.ts +30 -8
  64. package/lib/index.d.ts.map +1 -1
  65. package/lib/index.js +11 -8
  66. package/lib/polyfill.d.ts +23 -0
  67. package/lib/polyfill.d.ts.map +1 -0
  68. package/lib/polyfill.js +46 -0
  69. package/lib/renderMarkdown.d.ts.map +1 -1
  70. package/lib/renderMarkdown.js +34 -6
  71. package/lib/speech/CustomAudioInputStream.d.ts.map +1 -1
  72. package/lib/speech/CustomAudioInputStream.js +40 -15
  73. package/lib/speech/bytesPerSample.d.ts.map +1 -1
  74. package/lib/speech/bytesPerSample.js +3 -1
  75. package/lib/speech/createAudioConfig.d.ts.map +1 -1
  76. package/lib/speech/createAudioConfig.js +9 -3
  77. package/lib/speech/createMicrophoneAudioConfigAndAudioContext.d.ts.map +1 -1
  78. package/lib/speech/createMicrophoneAudioConfigAndAudioContext.js +3 -1
  79. package/lib/speech/getUserMedia.d.ts.map +1 -1
  80. package/lib/speech/getUserMedia.js +5 -2
  81. package/package.json +43 -43
  82. package/src/AddFullBundle.tsx +0 -1
  83. package/src/FullComposer.tsx +2 -0
  84. package/src/adaptiveCards/Attachment/AdaptiveCardAttachment.tsx +3 -1
  85. package/src/adaptiveCards/Attachment/AdaptiveCardBuilder.ts +8 -3
  86. package/src/adaptiveCards/Attachment/AdaptiveCardRenderer.tsx +183 -89
  87. package/src/adaptiveCards/Attachment/AnimationCardContent.tsx +3 -1
  88. package/src/adaptiveCards/Attachment/AudioCardContent.tsx +3 -1
  89. package/src/adaptiveCards/Attachment/HeroCardContent.tsx +4 -2
  90. package/src/adaptiveCards/Attachment/OAuthCardContent.tsx +3 -1
  91. package/src/adaptiveCards/Attachment/ReceiptCardContent.tsx +28 -48
  92. package/src/adaptiveCards/Attachment/SignInCardContent.tsx +1 -1
  93. package/src/adaptiveCards/Attachment/ThumbnailCardContent.tsx +3 -1
  94. package/src/adaptiveCards/Attachment/VideoCardContent.tsx +5 -3
  95. package/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.ts +8 -0
  96. package/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.tsx +0 -1
  97. package/src/createCognitiveServicesSpeechServicesPonyfillFactory.spec.js +2 -3
  98. package/src/createDirectLineSpeechAdapters.ts +1 -1
  99. package/src/index-es5.ts +3 -26
  100. package/src/polyfill.ts +29 -0
  101. package/src/renderMarkdown.ts +40 -4
  102. package/src/speech/CustomAudioInputStream.ts +38 -7
  103. package/src/speech/bytesPerSample.ts +2 -0
  104. package/src/speech/createAudioConfig.spec.js +1 -1
  105. package/src/speech/createAudioConfig.ts +7 -0
  106. package/src/speech/createMicrophoneAudioConfigAndAudioContext.ts +2 -0
  107. package/src/speech/getUserMedia.ts +4 -1
  108. package/.eslintignore +0 -1
@@ -1,9 +1,9 @@
1
1
  /* eslint no-magic-numbers: ["error", { "ignore": [0, 1, 10, 15, 25, 50, 75] }] */
2
2
 
3
- import { DirectLineReceiptCard } from 'botframework-webchat-core';
4
3
  import { hooks } from 'botframework-webchat-component';
5
4
  import PropTypes from 'prop-types';
6
5
  import React, { FC, useMemo } from 'react';
6
+ import type { DirectLineReceiptCard } from 'botframework-webchat-core';
7
7
 
8
8
  import AdaptiveCardBuilder from './AdaptiveCardBuilder';
9
9
  import AdaptiveCardRenderer from './AdaptiveCardRenderer';
@@ -55,54 +55,32 @@ const ReceiptCardContent: FC<ReceiptCardContentProps> = ({ actionPerformedClassN
55
55
  }
56
56
 
57
57
  items &&
58
- items.map(
59
- ({
60
- image: { alt, tap: imageTap, url } = {},
61
- price,
62
- quantity,
63
- subtitle,
64
- tap,
65
- text,
66
- title
67
- }: {
68
- image: {
69
- alt?: string;
70
- tap?: any;
71
- url?: string;
72
- };
73
- price: string;
74
- quantity: string;
75
- subtitle: string;
76
- tap: any;
77
- text: string;
78
- title: string;
79
- }) => {
80
- let itemColumns;
81
-
82
- if (url) {
83
- const [itemImageColumn, ...columns] = builder.addColumnSet([15, 75, 10]);
84
-
85
- itemColumns = columns;
86
- builder.addImage(url, itemImageColumn, imageTap, alt);
87
- } else {
88
- itemColumns = builder.addColumnSet([75, 25], undefined, tap && tap);
89
- }
90
-
91
- const [itemTitleColumn, itemPriceColumn] = itemColumns;
92
-
93
- builder.addTextBlock(
94
- quantity ? `${title} &times; ${quantity}` : title,
95
- { size: TextSize.Medium, weight: TextWeight.Bolder, wrap: richCardWrapTitle },
96
- itemTitleColumn
97
- );
98
- builder.addTextBlock(subtitle, { size: TextSize.Medium, wrap: richCardWrapTitle }, itemTitleColumn);
99
- builder.addTextBlock(price, { horizontalAlignment: HorizontalAlignment.Right }, itemPriceColumn);
100
-
101
- if (text) {
102
- builder.addTextBlock(text, { size: TextSize.Medium, wrap: richCardWrapTitle }, itemTitleColumn);
103
- }
58
+ items.map(({ image: { alt, tap: imageTap, url } = {}, price, quantity, subtitle, tap, text, title }) => {
59
+ let itemColumns;
60
+
61
+ if (url) {
62
+ const [itemImageColumn, ...columns] = builder.addColumnSet([15, 75, 10]);
63
+
64
+ itemColumns = columns;
65
+ builder.addImage(url, itemImageColumn, imageTap, alt);
66
+ } else {
67
+ itemColumns = builder.addColumnSet([75, 25], undefined, tap && tap);
104
68
  }
105
- );
69
+
70
+ const [itemTitleColumn, itemPriceColumn] = itemColumns;
71
+
72
+ builder.addTextBlock(
73
+ quantity ? `${title} &times; ${quantity}` : title,
74
+ { size: TextSize.Medium, weight: TextWeight.Bolder, wrap: richCardWrapTitle },
75
+ itemTitleColumn
76
+ );
77
+ builder.addTextBlock(subtitle, { size: TextSize.Medium, wrap: richCardWrapTitle }, itemTitleColumn);
78
+ builder.addTextBlock(price, { horizontalAlignment: HorizontalAlignment.Right }, itemPriceColumn);
79
+
80
+ if (text) {
81
+ builder.addTextBlock(text, { size: TextSize.Medium, wrap: richCardWrapTitle }, itemTitleColumn);
82
+ }
83
+ });
106
84
 
107
85
  if (!nullOrUndefined(vat)) {
108
86
  const vatCol = builder.addColumnSet([75, 25]);
@@ -152,6 +130,8 @@ ReceiptCardContent.defaultProps = {
152
130
 
153
131
  ReceiptCardContent.propTypes = {
154
132
  actionPerformedClassName: PropTypes.string,
133
+ // PropTypes cannot fully capture TypeScript types.
134
+ // @ts-ignore
155
135
  content: PropTypes.shape({
156
136
  buttons: PropTypes.array,
157
137
  facts: PropTypes.arrayOf(
@@ -1,7 +1,7 @@
1
- import { DirectLineSignInCard } from 'botframework-webchat-core';
2
1
  import { hooks } from 'botframework-webchat-component';
3
2
  import PropTypes from 'prop-types';
4
3
  import React, { FC } from 'react';
4
+ import type { DirectLineSignInCard } from 'botframework-webchat-core';
5
5
 
6
6
  import CommonCard from './CommonCard';
7
7
 
@@ -1,9 +1,9 @@
1
1
  /* eslint no-magic-numbers: ["error", { "ignore": [25, 75] }] */
2
2
 
3
- import { DirectLineThumbnailCard } from 'botframework-webchat-core';
4
3
  import { hooks } from 'botframework-webchat-component';
5
4
  import PropTypes from 'prop-types';
6
5
  import React, { FC, useMemo } from 'react';
6
+ import type { DirectLineThumbnailCard } from 'botframework-webchat-core';
7
7
 
8
8
  import AdaptiveCardBuilder from './AdaptiveCardBuilder';
9
9
  import AdaptiveCardRenderer from './AdaptiveCardRenderer';
@@ -68,6 +68,8 @@ ThumbnailCardContent.defaultProps = {
68
68
 
69
69
  ThumbnailCardContent.propTypes = {
70
70
  actionPerformedClassName: PropTypes.string,
71
+ // PropTypes cannot fully capture TypeScript types.
72
+ // @ts-ignore
71
73
  content: PropTypes.shape({
72
74
  buttons: PropTypes.array,
73
75
  images: PropTypes.arrayOf(
@@ -1,9 +1,9 @@
1
1
  /* eslint react/no-array-index-key: "off" */
2
2
 
3
- import { DirectLineVideoCard } from 'botframework-webchat-core';
4
3
  import { Components, hooks } from 'botframework-webchat-component';
5
4
  import PropTypes from 'prop-types';
6
5
  import React, { FC } from 'react';
6
+ import type { DirectLineVideoCard } from 'botframework-webchat-core';
7
7
 
8
8
  import CommonCard from './CommonCard';
9
9
 
@@ -46,6 +46,8 @@ VideoCardContent.defaultProps = {
46
46
 
47
47
  VideoCardContent.propTypes = {
48
48
  actionPerformedClassName: PropTypes.string,
49
+ // PropTypes cannot fully capture TypeScript types.
50
+ // @ts-ignore
49
51
  content: PropTypes.shape({
50
52
  autoloop: PropTypes.bool,
51
53
  autostart: PropTypes.bool,
@@ -54,10 +56,10 @@ VideoCardContent.propTypes = {
54
56
  }),
55
57
  media: PropTypes.arrayOf(
56
58
  PropTypes.shape({
57
- profile: PropTypes.string.isRequired,
59
+ profile: PropTypes.string,
58
60
  url: PropTypes.string.isRequired
59
61
  })
60
- )
62
+ ).isRequired
61
63
  }).isRequired,
62
64
  disabled: PropTypes.bool
63
65
  };
@@ -9,6 +9,14 @@ export default function ({
9
9
  }: FullBundleStyleOptions) {
10
10
  return {
11
11
  '&.webchat__adaptive-card-renderer': {
12
+ // Related to #4075.
13
+ // Adaptive Cards assume its host is in "forced border-box" mode.
14
+ // In CSS, the default is "content-box" mode.
15
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing#values
16
+ '& *': {
17
+ boxSizing: 'border-box'
18
+ },
19
+
12
20
  '& .ac-input, & .ac-inlineActionButton, & .ac-quickActionButton': {
13
21
  fontFamily: primaryFont
14
22
  },
@@ -16,7 +16,6 @@ export default function createAdaptiveCardsAttachmentMiddleware(): AttachmentMid
16
16
  // This is not returning a React component, but a render function.
17
17
  return () =>
18
18
  next =>
19
- /* eslint-disable-next-line react/display-name */
20
19
  (...args) => {
21
20
  const [{ attachment }] = args;
22
21
 
@@ -19,19 +19,18 @@ beforeEach(() => {
19
19
 
20
20
  createPonyfill = require('web-speech-cognitive-services/lib/SpeechServices');
21
21
  createCognitiveServicesSpeechServicesPonyfillFactory =
22
- // eslint-disable-next-line @typescript-eslint/no-var-requires
23
22
  require('./createCognitiveServicesSpeechServicesPonyfillFactory').default;
24
23
 
25
24
  window.AudioContext = class MockAudioContext {
26
25
  // eslint-disable-next-line class-methods-use-this
27
26
  createMediaStreamSource() {
28
- // eslint-disable-next-line @typescript-eslint/no-empty-function
27
+ // eslint-disable-next-line no-empty-function
29
28
  return { connect: () => {} };
30
29
  }
31
30
 
32
31
  // eslint-disable-next-line class-methods-use-this
33
32
  createScriptProcessor() {
34
- // eslint-disable-next-line @typescript-eslint/no-empty-function
33
+ // eslint-disable-next-line no-empty-function
35
34
  return { connect: () => {} };
36
35
  }
37
36
  };
@@ -1,7 +1,7 @@
1
1
  import { AudioConfig } from 'microsoft-cognitiveservices-speech-sdk';
2
2
  import { createAdapters } from 'botframework-directlinespeech-sdk';
3
- import { DirectLineJSBotConnection } from 'botframework-webchat-core';
4
3
  import { WebSpeechPonyfill } from 'botframework-webchat-api';
4
+ import type { DirectLineJSBotConnection } from 'botframework-webchat-core';
5
5
 
6
6
  import CognitiveServicesAudioOutputFormat from './types/CognitiveServicesAudioOutputFormat';
7
7
  import CognitiveServicesCredentials from './types/CognitiveServicesCredentials';
package/src/index-es5.ts CHANGED
@@ -1,32 +1,9 @@
1
1
  /* eslint dot-notation: ["error", { "allowPattern": "^WebChat$" }] */
2
2
  // window['WebChat'] is required for TypeScript
3
3
 
4
- // Polyfills for IE11 and other ES5 browsers
5
- // To maintain quality, we prefer polyfills without additives
6
- // For example, we prefer Promise implementation from "core-js" than "bluebird"
7
-
8
- import 'core-js/features/array/find-index';
9
- import 'core-js/features/array/find';
10
- import 'core-js/features/array/from';
11
- import 'core-js/features/array/includes';
12
- import 'core-js/features/array/iterator';
13
- import 'core-js/features/dom-collections';
14
- import 'core-js/features/math/sign';
15
- import 'core-js/features/number/is-finite';
16
- import 'core-js/features/object/assign';
17
- import 'core-js/features/object/entries';
18
- import 'core-js/features/object/from-entries';
19
- import 'core-js/features/object/is';
20
- import 'core-js/features/object/values';
21
- import 'core-js/features/promise';
22
- import 'core-js/features/promise/finally';
23
- import 'core-js/features/set';
24
- import 'core-js/features/string/ends-with';
25
- import 'core-js/features/string/starts-with';
26
- import 'core-js/features/symbol';
27
-
28
- import 'url-search-params-polyfill';
29
- import 'whatwg-fetch';
4
+ // Importing polyfills required for IE11/ES5.
5
+ import './polyfill';
6
+
30
7
  import { version } from './index-minimal';
31
8
  import addVersion from './addVersion';
32
9
  import defaultCreateDirectLine from './createDirectLine';
@@ -0,0 +1,29 @@
1
+ // Polyfills for IE11 and other ES5 browsers
2
+ // To maintain quality, we prefer polyfills without additives
3
+ // For example, we prefer Promise implementation from "core-js" than "bluebird"
4
+
5
+ // To reduce conflicts with hosting app, we should consider using
6
+ // @babel/plugin-transform-runtime to polyfill in transpiled code directly.
7
+
8
+ import 'core-js/features/array/find-index';
9
+ import 'core-js/features/array/find';
10
+ import 'core-js/features/array/from';
11
+ import 'core-js/features/array/includes';
12
+ import 'core-js/features/array/iterator';
13
+ import 'core-js/features/dom-collections';
14
+ import 'core-js/features/map';
15
+ import 'core-js/features/math/sign';
16
+ import 'core-js/features/number/is-finite';
17
+ import 'core-js/features/object/assign';
18
+ import 'core-js/features/object/entries';
19
+ import 'core-js/features/object/from-entries';
20
+ import 'core-js/features/object/is';
21
+ import 'core-js/features/object/values';
22
+ import 'core-js/features/promise';
23
+ import 'core-js/features/promise/finally';
24
+ import 'core-js/features/set';
25
+ import 'core-js/features/string/ends-with';
26
+ import 'core-js/features/string/starts-with';
27
+ import 'core-js/features/symbol';
28
+ import 'url-search-params-polyfill';
29
+ import 'whatwg-fetch';
@@ -57,6 +57,18 @@ const TRANSPARENT_GIF = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAA
57
57
  // This is used for parsing Markdown for external links.
58
58
  const internalMarkdownIt = new MarkdownIt();
59
59
 
60
+ const MARKDOWN_ATTRS_LEFT_DELIMITER = '⟬';
61
+ // Make sure the delimiter is free from any RegExp characters, such as *, ?, etc.
62
+ // IE11 does not support "u" flag and Babel could not remove it. We intentionally omitting the "u" flag here.
63
+ // eslint-disable-next-line security/detect-non-literal-regexp, require-unicode-regexp
64
+ const MARKDOWN_ATTRS_LEFT_DELIMITER_PATTERN = new RegExp(MARKDOWN_ATTRS_LEFT_DELIMITER, 'g');
65
+
66
+ const MARKDOWN_ATTRS_RIGHT_DELIMITER = '⟭';
67
+ // Make sure the delimiter is free from any RegExp characters, such as *, ?, etc.
68
+ // IE11 does not support "u" flag and Babel could not remove it. We intentionally omitting the "u" flag here.
69
+ // eslint-disable-next-line security/detect-non-literal-regexp, require-unicode-regexp
70
+ const MARKDOWN_ATTRS_RIGHT_DELIMITER_PATTERN = new RegExp(MARKDOWN_ATTRS_RIGHT_DELIMITER, 'g');
71
+
60
72
  export default function render(
61
73
  markdown: string,
62
74
  { markdownRespectCRLF }: { markdownRespectCRLF: boolean },
@@ -66,16 +78,37 @@ export default function render(
66
78
  markdown = markdown.replace(/\n\r|\r\n/gu, carriageReturn => (carriageReturn === '\n\r' ? '\r\n' : '\n\r'));
67
79
  }
68
80
 
69
- const html = new MarkdownIt({
81
+ // Related to #3165.
82
+ // We only support attributes "aria-label" and should leave other attributes as-is.
83
+ // However, `markdown-it-attrs` remove unrecognized attributes, such as {hello}.
84
+ // Before passing to `markdown-it-attrs`, we will convert known attributes from {aria-label="..."} into ⟬aria-label="..."⟭ (using white tortoise shell brackets).
85
+ // Then, we ask `markdown-it-attrs` to only process the new brackets, so it should only try to process things that we allowlisted.
86
+ // Lastly, we revert tortoise shell brackets back to curly brackets, for unprocessed attributes.
87
+ markdown = markdown
88
+ .replace(/\{\s*aria-label()\s*\}/giu, `${MARKDOWN_ATTRS_LEFT_DELIMITER}aria-label${MARKDOWN_ATTRS_RIGHT_DELIMITER}`)
89
+ .replace(
90
+ /\{\s*aria-label=("[^"]*"|[^\s}]*)\s*\}/giu,
91
+ (_, valueInsideQuotes) =>
92
+ `${MARKDOWN_ATTRS_LEFT_DELIMITER}aria-label=${valueInsideQuotes}${MARKDOWN_ATTRS_RIGHT_DELIMITER}`
93
+ );
94
+
95
+ let html = new MarkdownIt({
70
96
  breaks: false,
71
97
  html: false,
72
98
  linkify: true,
73
99
  typographer: true,
74
100
  xhtmlOut: true
75
101
  })
76
- .use(markdownItAttrs)
102
+ .use(markdownItAttrs, {
103
+ // `markdown-it-attrs` is added for accessibility and allow bot developers to specify `aria-label`.
104
+ // We are allowlisting `aria-label` only as it is allowlisted in `sanitize-html`.
105
+ // Other `aria-*` will be sanitized even we allowlisted here.
106
+ allowedAttributes: ['aria-label'],
107
+ leftDelimiter: MARKDOWN_ATTRS_LEFT_DELIMITER,
108
+ rightDelimiter: MARKDOWN_ATTRS_RIGHT_DELIMITER
109
+ })
77
110
  .use(iterator, 'url_new_win', 'link_open', (tokens, index) => {
78
- const token = tokens[index];
111
+ const token = tokens[+index];
79
112
 
80
113
  token.attrSet('rel', 'noopener noreferrer');
81
114
  token.attrSet('target', '_blank');
@@ -97,8 +130,11 @@ export default function render(
97
130
  })
98
131
  .render(markdown);
99
132
 
133
+ // Restore attributes not processed by `markdown-it-attrs`.
134
+ // TODO: [P2] #2511 After we fixed our polyfill story, we should use "String.prototype.replaceAll" instead of RegExp for replace all occurrences.
135
+ html = html.replace(MARKDOWN_ATTRS_LEFT_DELIMITER_PATTERN, '{').replace(MARKDOWN_ATTRS_RIGHT_DELIMITER_PATTERN, '}');
136
+
100
137
  // The signature from "sanitize-html" module is not correct.
101
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
102
138
  // @ts-ignore
103
139
  return sanitizeHTML(html, SANITIZE_HTML_OPTIONS);
104
140
  }
@@ -22,6 +22,7 @@ import {
22
22
  type as Type
23
23
  } from 'microsoft-cognitiveservices-speech-sdk/distrib/lib/src/common.speech/Exports';
24
24
 
25
+ import { isForbiddenPropertyName } from 'botframework-webchat-core';
25
26
  import { v4 } from 'uuid';
26
27
  import createDeferred, { DeferredPromise } from 'p-defer-es5';
27
28
 
@@ -88,9 +89,20 @@ abstract class CustomAudioInputStream extends AudioInputStream {
88
89
  id: options.id || v4().replace(/-/gu, '')
89
90
  };
90
91
 
92
+ // False alarm: indexer is a constant of type Symbol.
93
+ // eslint-disable-next-line security/detect-object-injection
91
94
  this[SYMBOL_DEVICE_INFO_DEFERRED] = createDeferred<DeviceInfo>();
95
+
96
+ // False alarm: indexer is a constant of type Symbol.
97
+ // eslint-disable-next-line security/detect-object-injection
92
98
  this[SYMBOL_EVENTS] = new EventSource<AudioSourceEvent>();
99
+
100
+ // False alarm: indexer is a constant of type Symbol.
101
+ // eslint-disable-next-line security/detect-object-injection
93
102
  this[SYMBOL_FORMAT_DEFERRED] = createDeferred<AudioStreamFormatImpl>();
103
+
104
+ // False alarm: indexer is a constant of type Symbol.
105
+ // eslint-disable-next-line security/detect-object-injection
94
106
  this[SYMBOL_OPTIONS] = normalizedOptions;
95
107
  }
96
108
 
@@ -101,9 +113,10 @@ abstract class CustomAudioInputStream extends AudioInputStream {
101
113
 
102
114
  /** Gets the event source for listening to events. */
103
115
  // ESLint: This code will only works in browsers other than IE11. Only works in ES5 is okay.
104
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
105
116
  // @ts-ignore Accessors are only available when targeting ECMAScript 5 and higher.ts(1056)
106
117
  get events(): EventSource<AudioSourceEvent> {
118
+ // False alarm: indexer is a constant of type Symbol.
119
+ // eslint-disable-next-line security/detect-object-injection
107
120
  return this[SYMBOL_EVENTS];
108
121
  }
109
122
 
@@ -114,16 +127,19 @@ abstract class CustomAudioInputStream extends AudioInputStream {
114
127
  // Speech SDK quirks: In normal speech recognition, getter of "format" is called only after "attach".
115
128
  // But in Direct Line Speech, it is called before "attach".
116
129
  // ESLint: This code will only works in browsers other than IE11. Only works in ES5 is okay.
117
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
118
130
  // @ts-ignore Accessors are only available when targeting ECMAScript 5 and higher.ts(1056)
119
131
  get format(): Promise<AudioStreamFormatImpl> {
120
132
  this.debug('Getting "format".');
121
133
 
134
+ // False alarm: indexer is a constant of type Symbol.
135
+ // eslint-disable-next-line security/detect-object-injection
122
136
  return this[SYMBOL_FORMAT_DEFERRED].promise;
123
137
  }
124
138
 
125
139
  /** Gets the ID of this audio stream. */
126
140
  id(): string {
141
+ // False alarm: indexer is a constant of type Symbol.
142
+ // eslint-disable-next-line security/detect-object-injection
127
143
  return this[SYMBOL_OPTIONS].id;
128
144
  }
129
145
 
@@ -131,6 +147,8 @@ abstract class CustomAudioInputStream extends AudioInputStream {
131
147
  // Speech SDK quirks: In JavaScript, onXxx means "listen to event XXX".
132
148
  // Instead, in Speech SDK, it means "emit event XXX".
133
149
  protected onEvent(event: AudioSourceEvent): void {
150
+ // False alarm: indexer is a constant of type Symbol.
151
+ // eslint-disable-next-line security/detect-object-injection
134
152
  this[SYMBOL_EVENTS].onEvent(event);
135
153
  Events.instance.onEvent(event);
136
154
  }
@@ -191,7 +209,6 @@ abstract class CustomAudioInputStream extends AudioInputStream {
191
209
 
192
210
  // Speech SDK quirks: Although "close" is marked as abstract, it is never called in our observations.
193
211
  // ESLint: Speech SDK requires this function, but we are not implementing it.
194
- // eslint-disable-next-line class-methods-use-this
195
212
  close(): void {
196
213
  this.debug('Callback for "close".');
197
214
 
@@ -215,7 +232,8 @@ abstract class CustomAudioInputStream extends AudioInputStream {
215
232
  /** Log the message to console if `debug` is set to `true`. */
216
233
  private debug(message, ...args) {
217
234
  // ESLint: For debugging, will only log when "debug" is set to "true".
218
- // eslint-disable-next-line no-console
235
+ // False alarm: indexer is a constant of type Symbol.
236
+ // eslint-disable-next-line no-console, security/detect-object-injection
219
237
  this[SYMBOL_OPTIONS].debug && console.info(`CustomAudioInputStream: ${message}`, ...args);
220
238
  }
221
239
 
@@ -240,7 +258,13 @@ abstract class CustomAudioInputStream extends AudioInputStream {
240
258
 
241
259
  // Although only getter of "format" is called before "attach" (in Direct Line Speech),
242
260
  // we are handling both "deviceInfo" and "format" in similar way for uniformity.
261
+
262
+ // False alarm: indexer is a constant of type Symbol.
263
+ // eslint-disable-next-line security/detect-object-injection
243
264
  this[SYMBOL_DEVICE_INFO_DEFERRED].resolve(deviceInfo);
265
+
266
+ // False alarm: indexer is a constant of type Symbol.
267
+ // eslint-disable-next-line security/detect-object-injection
244
268
  this[SYMBOL_FORMAT_DEFERRED].resolve(
245
269
  new AudioStreamFormatImpl(format.samplesPerSec, format.bitsPerSample, format.channels)
246
270
  );
@@ -300,21 +324,28 @@ abstract class CustomAudioInputStream extends AudioInputStream {
300
324
 
301
325
  /** Gets the device information. */
302
326
  // ESLint: This code will only works in browsers other than IE11. Only works in ES5 is okay.
303
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
304
327
  // @ts-ignore Accessors are only available when targeting ECMAScript 5 and higher.ts(1056)
305
328
  get deviceInfo(): Promise<ISpeechConfigAudioDevice> {
306
329
  this.debug(`Getting "deviceInfo".`);
307
330
 
331
+ // False alarm: indexer is a constant of type Symbol.
332
+ // eslint-disable-next-line security/detect-object-injection
308
333
  return Promise.all([this[SYMBOL_DEVICE_INFO_DEFERRED].promise, this[SYMBOL_FORMAT_DEFERRED].promise]).then(
309
334
  ([{ connectivity, manufacturer, model, type }, { bitsPerSample, channels, samplesPerSec }]) => ({
310
335
  bitspersample: bitsPerSample,
311
336
  channelcount: channels,
312
337
  connectivity:
313
- typeof connectivity === 'string' ? Connectivity[connectivity] : connectivity || Connectivity.Unknown,
338
+ typeof connectivity === 'string' && !isForbiddenPropertyName(connectivity)
339
+ ? // Mitigated through denylisting.
340
+ // eslint-disable-next-line security/detect-object-injection
341
+ Connectivity[connectivity]
342
+ : connectivity || Connectivity.Unknown,
314
343
  manufacturer: manufacturer || '',
315
344
  model: model || '',
316
345
  samplerate: samplesPerSec,
317
- type: typeof type === 'string' ? Type[type] : type || Type.Unknown
346
+ // Mitigated through denylisting.
347
+ // eslint-disable-next-line security/detect-object-injection
348
+ type: typeof type === 'string' && !isForbiddenPropertyName(type) ? Type[type] : type || Type.Unknown
318
349
  })
319
350
  );
320
351
  }
@@ -1,4 +1,6 @@
1
1
  export default function bytesPerSample(settings: MediaTrackSettings) {
2
+ // `channelCount` is not on @types/web@0.0.54 yet, related to https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1290.
3
+ // @ts-ignore
2
4
  // eslint-disable-next-line no-magic-numbers
3
5
  return ((settings.sampleSize as number) >> 3) * (settings.channelCount as number) * (settings.sampleRate as number);
4
6
  }
@@ -1,4 +1,4 @@
1
- /* eslint @typescript-eslint/no-empty-function: "off" */
1
+ /* eslint no-empty-function: "off" */
2
2
 
3
3
  import createAudioConfig from './createAudioConfig';
4
4
 
@@ -43,7 +43,12 @@ class CreateAudioConfigAudioInputStream extends CustomAudioInputStream {
43
43
 
44
44
  super({ debug });
45
45
 
46
+ // False alarm: indexer is a constant of type Symbol.
47
+ // eslint-disable-next-line security/detect-object-injection
46
48
  this[SYMBOL_ATTACH] = attach;
49
+
50
+ // False alarm: indexer is a constant of type Symbol.
51
+ // eslint-disable-next-line security/detect-object-injection
47
52
  this[SYMBOL_TURN_OFF] = turnOff;
48
53
  }
49
54
 
@@ -55,6 +60,8 @@ class CreateAudioConfigAudioInputStream extends CustomAudioInputStream {
55
60
  deviceInfo: DeviceInfo;
56
61
  format: Format;
57
62
  }> {
63
+ // False alarm: indexer is a constant of type Symbol.
64
+ // eslint-disable-next-line security/detect-object-injection
58
65
  return this[SYMBOL_ATTACH](audioNodeId);
59
66
  }
60
67
 
@@ -22,6 +22,8 @@ const PCM_RECORDER_HARDCODED_SETTINGS: MediaTrackSettings = Object.freeze({
22
22
 
23
23
  const PCM_RECORDER_HARDCODED_FORMAT: Format = Object.freeze({
24
24
  bitsPerSample: PCM_RECORDER_HARDCODED_SETTINGS.sampleSize,
25
+ // `channelCount` is not on @types/web@0.0.54 yet, related to https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1290.
26
+ // @ts-ignore
25
27
  channels: PCM_RECORDER_HARDCODED_SETTINGS.channelCount,
26
28
  samplesPerSec: PCM_RECORDER_HARDCODED_SETTINGS.sampleRate
27
29
  });
@@ -5,8 +5,11 @@ export default function getUserMedia(constraints: MediaStreamConstraints): Promi
5
5
  return navigator.mediaDevices.getUserMedia(constraints);
6
6
  }
7
7
 
8
- // Although getUserMedia has vendor prefix, they are only used in very old version of browsers.
8
+ // We are intentionally using the deprecated `navigator.getUserMedia` to make sure backward compatibility.
9
+ // @ts-ignore
9
10
  if (typeof navigator.getUserMedia !== 'undefined') {
11
+ // We are intentionally using the deprecated `navigator.getUserMedia` to make sure backward compatibility.
12
+ // @ts-ignore
10
13
  return new Promise((resolve, reject) => navigator.getUserMedia(constraints, resolve, reject));
11
14
  }
12
15
 
package/.eslintignore DELETED
@@ -1 +0,0 @@
1
- /src/tsconfig.json