botframework-webchat 4.15.10-main.20230908.de79e0e → 4.15.10-main.20230915.bb5898e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/webchat-es5.js +1 -1
  2. package/dist/webchat-minimal.js +1 -1
  3. package/dist/webchat.js +1 -1
  4. package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.d.ts.map +1 -1
  5. package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.js +5 -4
  6. package/lib/adaptiveCards/Attachment/AnimationCardContent.js +4 -3
  7. package/lib/adaptiveCards/Attachment/AudioCardContent.js +4 -3
  8. package/lib/adaptiveCards/Attachment/SignInCardContent.d.ts.map +1 -1
  9. package/lib/adaptiveCards/Attachment/SignInCardContent.js +3 -5
  10. package/lib/adaptiveCards/Attachment/VideoCardContent.js +4 -3
  11. package/lib/addVersion.js +1 -1
  12. package/lib/createFullStyleSet.d.ts +531 -233
  13. package/lib/createFullStyleSet.d.ts.map +1 -1
  14. package/lib/hooks/useStyleSet.d.ts +6 -0
  15. package/lib/hooks/useStyleSet.d.ts.map +1 -0
  16. package/lib/hooks/useStyleSet.js +23 -0
  17. package/lib/index.d.ts +3 -2
  18. package/lib/index.d.ts.map +1 -1
  19. package/lib/index.js +6 -3
  20. package/lib/markdown/markdownItPlugins/ariaLabel.d.ts +6 -0
  21. package/lib/markdown/markdownItPlugins/ariaLabel.d.ts.map +1 -0
  22. package/lib/markdown/markdownItPlugins/ariaLabel.js +64 -0
  23. package/lib/markdown/markdownItPlugins/betterLink.d.ts +22 -0
  24. package/lib/markdown/markdownItPlugins/betterLink.d.ts.map +1 -0
  25. package/lib/markdown/markdownItPlugins/betterLink.js +114 -0
  26. package/lib/markdown/markdownItPlugins/respectCRLF.d.ts +3 -0
  27. package/lib/markdown/markdownItPlugins/respectCRLF.d.ts.map +1 -0
  28. package/lib/markdown/markdownItPlugins/respectCRLF.js +19 -0
  29. package/lib/markdown/private/iterateLinkDefinitions.d.ts +3 -0
  30. package/lib/markdown/private/iterateLinkDefinitions.d.ts.map +1 -0
  31. package/lib/markdown/private/iterateLinkDefinitions.js +84 -0
  32. package/lib/markdown/renderMarkdown.d.ts +8 -0
  33. package/lib/markdown/renderMarkdown.d.ts.map +1 -0
  34. package/lib/markdown/renderMarkdown.js +119 -0
  35. package/lib/useComposerProps.js +2 -2
  36. package/package.json +9 -7
  37. package/src/__tests__/renderMarkdown.spec.js +3 -3
  38. package/src/adaptiveCards/Attachment/AdaptiveCardRenderer.tsx +2 -1
  39. package/src/adaptiveCards/Attachment/AnimationCardContent.tsx +2 -2
  40. package/src/adaptiveCards/Attachment/AudioCardContent.tsx +2 -2
  41. package/src/adaptiveCards/Attachment/SignInCardContent.tsx +1 -3
  42. package/src/adaptiveCards/Attachment/VideoCardContent.tsx +2 -2
  43. package/src/hooks/useStyleSet.ts +13 -0
  44. package/src/index.ts +4 -2
  45. package/src/markdown/markdownItPlugins/ariaLabel.spec.ts +27 -0
  46. package/src/markdown/markdownItPlugins/ariaLabel.ts +52 -0
  47. package/src/markdown/markdownItPlugins/betterLink.spec.ts +80 -0
  48. package/src/markdown/markdownItPlugins/betterLink.ts +113 -0
  49. package/src/markdown/markdownItPlugins/respectCRLF.ts +7 -0
  50. package/src/markdown/private/iterateLinkDefinitions.ts +14 -0
  51. package/src/markdown/renderMarkdown.ts +146 -0
  52. package/src/useComposerProps.ts +1 -1
  53. package/lib/renderMarkdown.d.ts +0 -6
  54. package/lib/renderMarkdown.d.ts.map +0 -1
  55. package/lib/renderMarkdown.js +0 -115
  56. package/src/renderMarkdown.ts +0 -140
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ exports.default = render;
11
+
12
+ var _botframeworkWebchatCore = require("botframework-webchat-core");
13
+
14
+ var _markdownIt = _interopRequireDefault(require("markdown-it"));
15
+
16
+ var _sanitizeHtml = _interopRequireDefault(require("sanitize-html"));
17
+
18
+ var _respectCRLF = require("./markdownItPlugins/respectCRLF");
19
+
20
+ var _ariaLabel = _interopRequireWildcard(require("./markdownItPlugins/ariaLabel"));
21
+
22
+ var _betterLink = _interopRequireDefault(require("./markdownItPlugins/betterLink"));
23
+
24
+ var _iterateLinkDefinitions = _interopRequireDefault(require("./private/iterateLinkDefinitions"));
25
+
26
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
27
+
28
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
29
+
30
+ var SANITIZE_HTML_OPTIONS = Object.freeze({
31
+ allowedAttributes: {
32
+ a: ['aria-label', 'class', 'href', 'name', 'rel', 'target'],
33
+ button: ['aria-label', 'class', 'type', 'value'],
34
+ img: ['alt', 'class', 'src', 'title'],
35
+ span: ['aria-label']
36
+ },
37
+ allowedSchemes: ['data', 'http', 'https', 'ftp', 'mailto', 'sip', 'tel'],
38
+ allowedTags: ['a', 'b', 'blockquote', 'br', 'button', 'caption', 'code', 'del', 'div', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', 'li', 'nl', 'ol', 'p', 'pre', 's', 'span', 'strike', 'strong', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul']
39
+ });
40
+ var MARKDOWN_IT_INIT = Object.freeze({
41
+ breaks: false,
42
+ html: false,
43
+ linkify: true,
44
+ typographer: true,
45
+ xhtmlOut: true
46
+ });
47
+
48
+ function render(markdown, _ref) {
49
+ var markdownRespectCRLF = _ref.markdownRespectCRLF;
50
+
51
+ var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Object.freeze({}),
52
+ _ref2$externalLinkAlt = _ref2.externalLinkAlt,
53
+ externalLinkAlt = _ref2$externalLinkAlt === void 0 ? '' : _ref2$externalLinkAlt;
54
+
55
+ var linkDefinitions = Array.from((0, _iterateLinkDefinitions.default)(markdown));
56
+
57
+ if (markdownRespectCRLF) {
58
+ markdown = (0, _respectCRLF.pre)(markdown);
59
+ }
60
+
61
+ markdown = (0, _ariaLabel.pre)(markdown);
62
+ var markdownIt = new _markdownIt.default(MARKDOWN_IT_INIT).use(_ariaLabel.default).use(_betterLink.default, function (href, textContent) {
63
+ var decoration = {
64
+ rel: 'noopener noreferrer',
65
+ target: '_blank'
66
+ };
67
+ var ariaLabelSegments = [textContent];
68
+ var classes = new Set();
69
+ var linkDefinition = linkDefinitions.find(function (_ref3) {
70
+ var url = _ref3.url;
71
+ return url === href;
72
+ });
73
+ var protocol = (0, _botframeworkWebchatCore.onErrorResumeNext)(function () {
74
+ return new URL(href).protocol;
75
+ });
76
+
77
+ if (linkDefinition) {
78
+ ariaLabelSegments.push(linkDefinition.title || (0, _botframeworkWebchatCore.onErrorResumeNext)(function () {
79
+ return new URL(linkDefinition.url).host;
80
+ }) || linkDefinition.url);
81
+ linkDefinition.identifier === textContent && classes.add('webchat__render-markdown__pure-identifier');
82
+ }
83
+
84
+ if (protocol === 'cite:') {
85
+ decoration.asButton = true;
86
+ classes.add('webchat__render-markdown__citation');
87
+ } else if (protocol === 'http:' || protocol === 'https:') {
88
+ decoration.iconAlt = externalLinkAlt;
89
+ decoration.iconClassName = 'webchat__render-markdown__external-link-icon';
90
+ ariaLabelSegments.push(externalLinkAlt);
91
+ } // The first segment is textContent. Putting textContent is aria-label is useless.
92
+
93
+
94
+ if (ariaLabelSegments.length > 1) {
95
+ // If "aria-label" is already applied, do not overwrite it.
96
+ decoration.ariaLabel = function (value) {
97
+ return value || ariaLabelSegments.join(' ');
98
+ };
99
+ }
100
+
101
+ decoration.className = Array.from(classes).join(' '); // By default, Markdown-It will set "title" to the link title in link definition.
102
+ // However, "title" may be narrated by screen reader:
103
+ // - Edge
104
+ // - <a> will narrate "aria-label" but not "title"
105
+ // - <button> will narrate both "aria-label" and "title"
106
+ // - NVDA
107
+ // - <a> will narrate both "aria-label" and "title"
108
+ // - <button> will narrate both "aria-label" and "title"
109
+ // Title makes it very difficult to control narrations by the screen reader. Thus, we are disabling it in favor of "aria-label".
110
+ // This will not affect our accessibility compliance but UX. We could use a non-native tooltip or other forms of visual hint.
111
+
112
+ decoration.title = false;
113
+ return decoration;
114
+ });
115
+ var html = markdownIt.render(markdown);
116
+ html = (0, _ariaLabel.post)(html);
117
+ return (0, _sanitizeHtml.default)(html, SANITIZE_HTML_OPTIONS);
118
+ }
119
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJTQU5JVElaRV9IVE1MX09QVElPTlMiLCJPYmplY3QiLCJmcmVlemUiLCJhbGxvd2VkQXR0cmlidXRlcyIsImEiLCJidXR0b24iLCJpbWciLCJzcGFuIiwiYWxsb3dlZFNjaGVtZXMiLCJhbGxvd2VkVGFncyIsIk1BUktET1dOX0lUX0lOSVQiLCJicmVha3MiLCJodG1sIiwibGlua2lmeSIsInR5cG9ncmFwaGVyIiwieGh0bWxPdXQiLCJyZW5kZXIiLCJtYXJrZG93biIsIm1hcmtkb3duUmVzcGVjdENSTEYiLCJleHRlcm5hbExpbmtBbHQiLCJsaW5rRGVmaW5pdGlvbnMiLCJBcnJheSIsImZyb20iLCJpdGVyYXRlTGlua0RlZmluaXRpb25zIiwicmVzcGVjdENSTEZQcmUiLCJhcmlhTGFiZWxQcmUiLCJtYXJrZG93bkl0IiwiTWFya2Rvd25JdCIsInVzZSIsImFyaWFMYWJlbCIsImJldHRlckxpbmsiLCJocmVmIiwidGV4dENvbnRlbnQiLCJkZWNvcmF0aW9uIiwicmVsIiwidGFyZ2V0IiwiYXJpYUxhYmVsU2VnbWVudHMiLCJjbGFzc2VzIiwiU2V0IiwibGlua0RlZmluaXRpb24iLCJmaW5kIiwidXJsIiwicHJvdG9jb2wiLCJvbkVycm9yUmVzdW1lTmV4dCIsIlVSTCIsInB1c2giLCJ0aXRsZSIsImhvc3QiLCJpZGVudGlmaWVyIiwiYWRkIiwiYXNCdXR0b24iLCJpY29uQWx0IiwiaWNvbkNsYXNzTmFtZSIsImxlbmd0aCIsInZhbHVlIiwiam9pbiIsImNsYXNzTmFtZSIsImFyaWFMYWJlbFBvc3QiLCJzYW5pdGl6ZUhUTUwiXSwic291cmNlUm9vdCI6ImJ1bmRsZTovLy8iLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tYXJrZG93bi9yZW5kZXJNYXJrZG93bi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBvbkVycm9yUmVzdW1lTmV4dCB9IGZyb20gJ2JvdGZyYW1ld29yay13ZWJjaGF0LWNvcmUnO1xuaW1wb3J0IE1hcmtkb3duSXQgZnJvbSAnbWFya2Rvd24taXQnO1xuaW1wb3J0IHNhbml0aXplSFRNTCBmcm9tICdzYW5pdGl6ZS1odG1sJztcblxuaW1wb3J0IHsgcHJlIGFzIHJlc3BlY3RDUkxGUHJlIH0gZnJvbSAnLi9tYXJrZG93bkl0UGx1Z2lucy9yZXNwZWN0Q1JMRic7XG5pbXBvcnQgYXJpYUxhYmVsLCB7IHBvc3QgYXMgYXJpYUxhYmVsUG9zdCwgcHJlIGFzIGFyaWFMYWJlbFByZSB9IGZyb20gJy4vbWFya2Rvd25JdFBsdWdpbnMvYXJpYUxhYmVsJztcbmltcG9ydCBiZXR0ZXJMaW5rIGZyb20gJy4vbWFya2Rvd25JdFBsdWdpbnMvYmV0dGVyTGluayc7XG5pbXBvcnQgaXRlcmF0ZUxpbmtEZWZpbml0aW9ucyBmcm9tICcuL3ByaXZhdGUvaXRlcmF0ZUxpbmtEZWZpbml0aW9ucyc7XG5cbmNvbnN0IFNBTklUSVpFX0hUTUxfT1BUSU9OUyA9IE9iamVjdC5mcmVlemUoe1xuICBhbGxvd2VkQXR0cmlidXRlczoge1xuICAgIGE6IFsnYXJpYS1sYWJlbCcsICdjbGFzcycsICdocmVmJywgJ25hbWUnLCAncmVsJywgJ3RhcmdldCddLFxuICAgIGJ1dHRvbjogWydhcmlhLWxhYmVsJywgJ2NsYXNzJywgJ3R5cGUnLCAndmFsdWUnXSxcbiAgICBpbWc6IFsnYWx0JywgJ2NsYXNzJywgJ3NyYycsICd0aXRsZSddLFxuICAgIHNwYW46IFsnYXJpYS1sYWJlbCddXG4gIH0sXG4gIGFsbG93ZWRTY2hlbWVzOiBbJ2RhdGEnLCAnaHR0cCcsICdodHRwcycsICdmdHAnLCAnbWFpbHRvJywgJ3NpcCcsICd0ZWwnXSxcbiAgYWxsb3dlZFRhZ3M6IFtcbiAgICAnYScsXG4gICAgJ2InLFxuICAgICdibG9ja3F1b3RlJyxcbiAgICAnYnInLFxuICAgICdidXR0b24nLFxuICAgICdjYXB0aW9uJyxcbiAgICAnY29kZScsXG4gICAgJ2RlbCcsXG4gICAgJ2RpdicsXG4gICAgJ2VtJyxcbiAgICAnaDEnLFxuICAgICdoMicsXG4gICAgJ2gzJyxcbiAgICAnaDQnLFxuICAgICdoNScsXG4gICAgJ2g2JyxcbiAgICAnaHInLFxuICAgICdpJyxcbiAgICAnaW1nJyxcbiAgICAnaW5zJyxcbiAgICAnbGknLFxuICAgICdubCcsXG4gICAgJ29sJyxcbiAgICAncCcsXG4gICAgJ3ByZScsXG4gICAgJ3MnLFxuICAgICdzcGFuJyxcbiAgICAnc3RyaWtlJyxcbiAgICAnc3Ryb25nJyxcbiAgICAndGFibGUnLFxuICAgICd0Ym9keScsXG4gICAgJ3RkJyxcbiAgICAndGZvb3QnLFxuICAgICd0aCcsXG4gICAgJ3RoZWFkJyxcbiAgICAndHInLFxuICAgICd1bCdcbiAgXVxufSk7XG5cbmNvbnN0IE1BUktET1dOX0lUX0lOSVQgPSBPYmplY3QuZnJlZXplKHtcbiAgYnJlYWtzOiBmYWxzZSxcbiAgaHRtbDogZmFsc2UsXG4gIGxpbmtpZnk6IHRydWUsXG4gIHR5cG9ncmFwaGVyOiB0cnVlLFxuICB4aHRtbE91dDogdHJ1ZVxufSk7XG5cbnR5cGUgQmV0dGVyTGlua0RlY29yYXRpb24gPSBFeGNsdWRlPFJldHVyblR5cGU8UGFyYW1ldGVyczx0eXBlb2YgYmV0dGVyTGluaz5bMV0+LCB1bmRlZmluZWQ+O1xudHlwZSBSZW5kZXJJbml0ID0geyBleHRlcm5hbExpbmtBbHQ/OiBzdHJpbmcgfTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gcmVuZGVyKFxuICBtYXJrZG93bjogc3RyaW5nLFxuICB7IG1hcmtkb3duUmVzcGVjdENSTEYgfTogUmVhZG9ubHk8eyBtYXJrZG93blJlc3BlY3RDUkxGOiBib29sZWFuIH0+LFxuICB7IGV4dGVybmFsTGlua0FsdCA9ICcnIH06IFJlYWRvbmx5PFJlbmRlckluaXQ+ID0gT2JqZWN0LmZyZWV6ZSh7fSlcbik6IHN0cmluZyB7XG4gIGNvbnN0IGxpbmtEZWZpbml0aW9ucyA9IEFycmF5LmZyb20oaXRlcmF0ZUxpbmtEZWZpbml0aW9ucyhtYXJrZG93bikpO1xuXG4gIGlmIChtYXJrZG93blJlc3BlY3RDUkxGKSB7XG4gICAgbWFya2Rvd24gPSByZXNwZWN0Q1JMRlByZShtYXJrZG93bik7XG4gIH1cblxuICBtYXJrZG93biA9IGFyaWFMYWJlbFByZShtYXJrZG93bik7XG5cbiAgY29uc3QgbWFya2Rvd25JdCA9IG5ldyBNYXJrZG93bkl0KE1BUktET1dOX0lUX0lOSVQpXG4gICAgLnVzZShhcmlhTGFiZWwpXG4gICAgLnVzZShiZXR0ZXJMaW5rLCAoaHJlZjogc3RyaW5nLCB0ZXh0Q29udGVudDogc3RyaW5nKTogQmV0dGVyTGlua0RlY29yYXRpb24gfCB1bmRlZmluZWQgPT4ge1xuICAgICAgY29uc3QgZGVjb3JhdGlvbjogQmV0dGVyTGlua0RlY29yYXRpb24gPSB7XG4gICAgICAgIHJlbDogJ25vb3BlbmVyIG5vcmVmZXJyZXInLFxuICAgICAgICB0YXJnZXQ6ICdfYmxhbmsnXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBhcmlhTGFiZWxTZWdtZW50czogc3RyaW5nW10gPSBbdGV4dENvbnRlbnRdO1xuICAgICAgY29uc3QgY2xhc3NlczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG4gICAgICBjb25zdCBsaW5rRGVmaW5pdGlvbiA9IGxpbmtEZWZpbml0aW9ucy5maW5kKCh7IHVybCB9KSA9PiB1cmwgPT09IGhyZWYpO1xuICAgICAgY29uc3QgcHJvdG9jb2wgPSBvbkVycm9yUmVzdW1lTmV4dCgoKSA9PiBuZXcgVVJMKGhyZWYpLnByb3RvY29sKTtcblxuICAgICAgaWYgKGxpbmtEZWZpbml0aW9uKSB7XG4gICAgICAgIGFyaWFMYWJlbFNlZ21lbnRzLnB1c2goXG4gICAgICAgICAgbGlua0RlZmluaXRpb24udGl0bGUgfHwgb25FcnJvclJlc3VtZU5leHQoKCkgPT4gbmV3IFVSTChsaW5rRGVmaW5pdGlvbi51cmwpLmhvc3QpIHx8IGxpbmtEZWZpbml0aW9uLnVybFxuICAgICAgICApO1xuXG4gICAgICAgIGxpbmtEZWZpbml0aW9uLmlkZW50aWZpZXIgPT09IHRleHRDb250ZW50ICYmIGNsYXNzZXMuYWRkKCd3ZWJjaGF0X19yZW5kZXItbWFya2Rvd25fX3B1cmUtaWRlbnRpZmllcicpO1xuICAgICAgfVxuXG4gICAgICBpZiAocHJvdG9jb2wgPT09ICdjaXRlOicpIHtcbiAgICAgICAgZGVjb3JhdGlvbi5hc0J1dHRvbiA9IHRydWU7XG5cbiAgICAgICAgY2xhc3Nlcy5hZGQoJ3dlYmNoYXRfX3JlbmRlci1tYXJrZG93bl9fY2l0YXRpb24nKTtcbiAgICAgIH0gZWxzZSBpZiAocHJvdG9jb2wgPT09ICdodHRwOicgfHwgcHJvdG9jb2wgPT09ICdodHRwczonKSB7XG4gICAgICAgIGRlY29yYXRpb24uaWNvbkFsdCA9IGV4dGVybmFsTGlua0FsdDtcbiAgICAgICAgZGVjb3JhdGlvbi5pY29uQ2xhc3NOYW1lID0gJ3dlYmNoYXRfX3JlbmRlci1tYXJrZG93bl9fZXh0ZXJuYWwtbGluay1pY29uJztcblxuICAgICAgICBhcmlhTGFiZWxTZWdtZW50cy5wdXNoKGV4dGVybmFsTGlua0FsdCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFRoZSBmaXJzdCBzZWdtZW50IGlzIHRleHRDb250ZW50LiBQdXR0aW5nIHRleHRDb250ZW50IGlzIGFyaWEtbGFiZWwgaXMgdXNlbGVzcy5cbiAgICAgIGlmIChhcmlhTGFiZWxTZWdtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIC8vIElmIFwiYXJpYS1sYWJlbFwiIGlzIGFscmVhZHkgYXBwbGllZCwgZG8gbm90IG92ZXJ3cml0ZSBpdC5cbiAgICAgICAgZGVjb3JhdGlvbi5hcmlhTGFiZWwgPSAodmFsdWU6IHN0cmluZykgPT4gdmFsdWUgfHwgYXJpYUxhYmVsU2VnbWVudHMuam9pbignICcpO1xuICAgICAgfVxuXG4gICAgICBkZWNvcmF0aW9uLmNsYXNzTmFtZSA9IEFycmF5LmZyb20oY2xhc3Nlcykuam9pbignICcpO1xuXG4gICAgICAvLyBCeSBkZWZhdWx0LCBNYXJrZG93bi1JdCB3aWxsIHNldCBcInRpdGxlXCIgdG8gdGhlIGxpbmsgdGl0bGUgaW4gbGluayBkZWZpbml0aW9uLlxuXG4gICAgICAvLyBIb3dldmVyLCBcInRpdGxlXCIgbWF5IGJlIG5hcnJhdGVkIGJ5IHNjcmVlbiByZWFkZXI6XG4gICAgICAvLyAtIEVkZ2VcbiAgICAgIC8vICAgLSA8YT4gd2lsbCBuYXJyYXRlIFwiYXJpYS1sYWJlbFwiIGJ1dCBub3QgXCJ0aXRsZVwiXG4gICAgICAvLyAgIC0gPGJ1dHRvbj4gd2lsbCBuYXJyYXRlIGJvdGggXCJhcmlhLWxhYmVsXCIgYW5kIFwidGl0bGVcIlxuICAgICAgLy8gLSBOVkRBXG4gICAgICAvLyAgIC0gPGE+IHdpbGwgbmFycmF0ZSBib3RoIFwiYXJpYS1sYWJlbFwiIGFuZCBcInRpdGxlXCJcbiAgICAgIC8vICAgLSA8YnV0dG9uPiB3aWxsIG5hcnJhdGUgYm90aCBcImFyaWEtbGFiZWxcIiBhbmQgXCJ0aXRsZVwiXG5cbiAgICAgIC8vIFRpdGxlIG1ha2VzIGl0IHZlcnkgZGlmZmljdWx0IHRvIGNvbnRyb2wgbmFycmF0aW9ucyBieSB0aGUgc2NyZWVuIHJlYWRlci4gVGh1cywgd2UgYXJlIGRpc2FibGluZyBpdCBpbiBmYXZvciBvZiBcImFyaWEtbGFiZWxcIi5cbiAgICAgIC8vIFRoaXMgd2lsbCBub3QgYWZmZWN0IG91ciBhY2Nlc3NpYmlsaXR5IGNvbXBsaWFuY2UgYnV0IFVYLiBXZSBjb3VsZCB1c2UgYSBub24tbmF0aXZlIHRvb2x0aXAgb3Igb3RoZXIgZm9ybXMgb2YgdmlzdWFsIGhpbnQuXG5cbiAgICAgIGRlY29yYXRpb24udGl0bGUgPSBmYWxzZTtcblxuICAgICAgcmV0dXJuIGRlY29yYXRpb247XG4gICAgfSk7XG5cbiAgbGV0IGh0bWwgPSBtYXJrZG93bkl0LnJlbmRlcihtYXJrZG93bik7XG5cbiAgaHRtbCA9IGFyaWFMYWJlbFBvc3QoaHRtbCk7XG5cbiAgcmV0dXJuIHNhbml0aXplSFRNTChodG1sLCBTQU5JVElaRV9IVE1MX09QVElPTlMpO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztB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
@@ -17,7 +17,7 @@ var _createAdaptiveCardsAttachmentMiddleware = _interopRequireDefault(require(".
17
17
 
18
18
  var _createAdaptiveCardsStyleSet = _interopRequireDefault(require("./adaptiveCards/Styles/createAdaptiveCardsStyleSet"));
19
19
 
20
- var _renderMarkdown = _interopRequireDefault(require("./renderMarkdown"));
20
+ var _renderMarkdown = _interopRequireDefault(require("./markdown/renderMarkdown"));
21
21
 
22
22
  function useComposerProps(_ref) {
23
23
  var attachmentForScreenReaderMiddleware = _ref.attachmentForScreenReaderMiddleware,
@@ -45,4 +45,4 @@ function useComposerProps(_ref) {
45
45
  renderMarkdown: patchedRenderMarkdown
46
46
  };
47
47
  }
48
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ1c2VDb21wb3NlclByb3BzIiwiYXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUiLCJhdHRhY2htZW50TWlkZGxld2FyZSIsInJlbmRlck1hcmtkb3duIiwic3R5bGVPcHRpb25zIiwic3R5bGVTZXQiLCJwYXRjaGVkQXR0YWNobWVudE1pZGRsZXdhcmUiLCJ1c2VNZW1vIiwiY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRNaWRkbGV3YXJlIiwicGF0Y2hlZEF0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlIiwiY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlIiwiZXh0cmFTdHlsZVNldCIsInVuZGVmaW5lZCIsImNyZWF0ZUFkYXB0aXZlQ2FyZHNTdHlsZVNldCIsInBhdGNoZWRSZW5kZXJNYXJrZG93biIsImRlZmF1bHRSZW5kZXJNYXJrZG93biJdLCJzb3VyY2VSb290IjoiYnVuZGxlOi8vLyIsInNvdXJjZXMiOlsiLi4vc3JjL3VzZUNvbXBvc2VyUHJvcHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUsIEF0dGFjaG1lbnRNaWRkbGV3YXJlIH0gZnJvbSAnYm90ZnJhbWV3b3JrLXdlYmNoYXQtYXBpJztcbmltcG9ydCB7IHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XG5cbmltcG9ydCBjcmVhdGVBZGFwdGl2ZUNhcmRzQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUgZnJvbSAnLi9hZGFwdGl2ZUNhcmRzL2NyZWF0ZUFkYXB0aXZlQ2FyZHNBdHRhY2htZW50Rm9yU2NyZWVuUmVhZGVyTWlkZGxld2FyZSc7XG5pbXBvcnQgY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRNaWRkbGV3YXJlIGZyb20gJy4vYWRhcHRpdmVDYXJkcy9jcmVhdGVBZGFwdGl2ZUNhcmRzQXR0YWNobWVudE1pZGRsZXdhcmUnO1xuaW1wb3J0IGNyZWF0ZUFkYXB0aXZlQ2FyZHNTdHlsZVNldCBmcm9tICcuL2FkYXB0aXZlQ2FyZHMvU3R5bGVzL2NyZWF0ZUFkYXB0aXZlQ2FyZHNTdHlsZVNldCc7XG5pbXBvcnQgZGVmYXVsdFJlbmRlck1hcmtkb3duIGZyb20gJy4vcmVuZGVyTWFya2Rvd24nO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiB1c2VDb21wb3NlclByb3BzKHtcbiAgYXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUsXG4gIGF0dGFjaG1lbnRNaWRkbGV3YXJlLFxuICByZW5kZXJNYXJrZG93bixcbiAgc3R5bGVPcHRpb25zLFxuICBzdHlsZVNldFxufToge1xuICBhdHRhY2htZW50Rm9yU2NyZWVuUmVhZGVyTWlkZGxld2FyZTogQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmVbXTtcbiAgYXR0YWNobWVudE1pZGRsZXdhcmU6IEF0dGFjaG1lbnRNaWRkbGV3YXJlW107XG4gIHJlbmRlck1hcmtkb3duPzogKFxuICAgIG1hcmtkb3duOiBzdHJpbmcsXG4gICAgbmV3TGluZU9wdGlvbnM6IHsgbWFya2Rvd25SZXNwZWN0Q1JMRjogYm9vbGVhbiB9LFxuICAgIGxpbmtPcHRpb25zOiB7IGV4dGVybmFsTGlua0FsdDogc3RyaW5nIH1cbiAgKSA9PiBzdHJpbmc7XG4gIHN0eWxlT3B0aW9uczogYW55O1xuICBzdHlsZVNldDogYW55O1xufSk6IHtcbiAgYXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmU6IEF0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlW107XG4gIGF0dGFjaG1lbnRNaWRkbGV3YXJlOiBBdHRhY2htZW50TWlkZGxld2FyZVtdO1xuICByZW5kZXJNYXJrZG93bjogKFxuICAgIG1hcmtkb3duOiBzdHJpbmcsXG4gICAgbmV3TGluZU9wdGlvbnM6IHsgbWFya2Rvd25SZXNwZWN0Q1JMRjogYm9vbGVhbiB9LFxuICAgIGxpbmtPcHRpb25zOiB7IGV4dGVybmFsTGlua0FsdDogc3RyaW5nIH1cbiAgKSA9PiBzdHJpbmc7XG4gIGV4dHJhU3R5bGVTZXQ6IGFueTtcbn0ge1xuICBjb25zdCBwYXRjaGVkQXR0YWNobWVudE1pZGRsZXdhcmUgPSB1c2VNZW1vKFxuICAgICgpID0+IFsuLi5hdHRhY2htZW50TWlkZGxld2FyZSwgY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRNaWRkbGV3YXJlKCldLFxuICAgIFthdHRhY2htZW50TWlkZGxld2FyZV1cbiAgKTtcblxuICBjb25zdCBwYXRjaGVkQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUgPSB1c2VNZW1vKFxuICAgICgpID0+IFsuLi5hdHRhY2htZW50Rm9yU2NyZWVuUmVhZGVyTWlkZGxld2FyZSwgY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlKCldLFxuICAgIFthdHRhY2htZW50Rm9yU2NyZWVuUmVhZGVyTWlkZGxld2FyZV1cbiAgKTtcblxuICAvLyBXaGVuIHN0eWxlU2V0IGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBzdHlsZU9wdGlvbnMgd2lsbCBiZSB1c2VkIHRvIGNyZWF0ZSBBZGFwdGl2ZSBDYXJkcyBzdHlsZVNldCBhbmQgbWVyZ2VkIGludG8gdXNlU3R5bGVTZXQuXG4gIGNvbnN0IGV4dHJhU3R5bGVTZXQgPSB1c2VNZW1vKFxuICAgICgpID0+IChzdHlsZVNldCA/IHVuZGVmaW5lZCA6IGNyZWF0ZUFkYXB0aXZlQ2FyZHNTdHlsZVNldChzdHlsZU9wdGlvbnMpKSxcbiAgICBbc3R5bGVPcHRpb25zLCBzdHlsZVNldF1cbiAgKTtcblxuICBjb25zdCBwYXRjaGVkUmVuZGVyTWFya2Rvd24gPSB1c2VNZW1vKFxuICAgICgpID0+ICh0eXBlb2YgcmVuZGVyTWFya2Rvd24gPT09ICd1bmRlZmluZWQnID8gZGVmYXVsdFJlbmRlck1hcmtkb3duIDogcmVuZGVyTWFya2Rvd24pLFxuICAgIFtyZW5kZXJNYXJrZG93bl1cbiAgKTtcblxuICByZXR1cm4ge1xuICAgIGF0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlOiBwYXRjaGVkQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUsXG4gICAgYXR0YWNobWVudE1pZGRsZXdhcmU6IHBhdGNoZWRBdHRhY2htZW50TWlkZGxld2FyZSxcbiAgICBleHRyYVN0eWxlU2V0LFxuICAgIHJlbmRlck1hcmtkb3duOiBwYXRjaGVkUmVuZGVyTWFya2Rvd25cbiAgfTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFDQTs7QUFFQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFZSxTQUFTQSxnQkFBVCxPQXlCYjtFQUFBLElBeEJBQyxtQ0F3QkEsUUF4QkFBLG1DQXdCQTtFQUFBLElBdkJBQyxvQkF1QkEsUUF2QkFBLG9CQXVCQTtFQUFBLElBdEJBQyxjQXNCQSxRQXRCQUEsY0FzQkE7RUFBQSxJQXJCQUMsWUFxQkEsUUFyQkFBLFlBcUJBO0VBQUEsSUFwQkFDLFFBb0JBLFFBcEJBQSxRQW9CQTtFQUNBLElBQU1DLDJCQUEyQixHQUFHLElBQUFDLGNBQUEsRUFDbEM7SUFBQSxrREFBVUwsb0JBQVYsSUFBZ0MsSUFBQU0sZ0RBQUEsR0FBaEM7RUFBQSxDQURrQyxFQUVsQyxDQUFDTixvQkFBRCxDQUZrQyxDQUFwQztFQUtBLElBQU1PLDBDQUEwQyxHQUFHLElBQUFGLGNBQUEsRUFDakQ7SUFBQSxrREFBVU4sbUNBQVYsSUFBK0MsSUFBQVMsK0RBQUEsR0FBL0M7RUFBQSxDQURpRCxFQUVqRCxDQUFDVCxtQ0FBRCxDQUZpRCxDQUFuRCxDQU5BLENBV0E7O0VBQ0EsSUFBTVUsYUFBYSxHQUFHLElBQUFKLGNBQUEsRUFDcEI7SUFBQSxPQUFPRixRQUFRLEdBQUdPLFNBQUgsR0FBZSxJQUFBQyxvQ0FBQSxFQUE0QlQsWUFBNUIsQ0FBOUI7RUFBQSxDQURvQixFQUVwQixDQUFDQSxZQUFELEVBQWVDLFFBQWYsQ0FGb0IsQ0FBdEI7RUFLQSxJQUFNUyxxQkFBcUIsR0FBRyxJQUFBUCxjQUFBLEVBQzVCO0lBQUEsT0FBTyxPQUFPSixjQUFQLEtBQTBCLFdBQTFCLEdBQXdDWSx1QkFBeEMsR0FBZ0VaLGNBQXZFO0VBQUEsQ0FENEIsRUFFNUIsQ0FBQ0EsY0FBRCxDQUY0QixDQUE5QjtFQUtBLE9BQU87SUFDTEYsbUNBQW1DLEVBQUVRLDBDQURoQztJQUVMUCxvQkFBb0IsRUFBRUksMkJBRmpCO0lBR0xLLGFBQWEsRUFBYkEsYUFISztJQUlMUixjQUFjLEVBQUVXO0VBSlgsQ0FBUDtBQU1EIn0=
48
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ1c2VDb21wb3NlclByb3BzIiwiYXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUiLCJhdHRhY2htZW50TWlkZGxld2FyZSIsInJlbmRlck1hcmtkb3duIiwic3R5bGVPcHRpb25zIiwic3R5bGVTZXQiLCJwYXRjaGVkQXR0YWNobWVudE1pZGRsZXdhcmUiLCJ1c2VNZW1vIiwiY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRNaWRkbGV3YXJlIiwicGF0Y2hlZEF0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlIiwiY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlIiwiZXh0cmFTdHlsZVNldCIsInVuZGVmaW5lZCIsImNyZWF0ZUFkYXB0aXZlQ2FyZHNTdHlsZVNldCIsInBhdGNoZWRSZW5kZXJNYXJrZG93biIsImRlZmF1bHRSZW5kZXJNYXJrZG93biJdLCJzb3VyY2VSb290IjoiYnVuZGxlOi8vLyIsInNvdXJjZXMiOlsiLi4vc3JjL3VzZUNvbXBvc2VyUHJvcHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUsIEF0dGFjaG1lbnRNaWRkbGV3YXJlIH0gZnJvbSAnYm90ZnJhbWV3b3JrLXdlYmNoYXQtYXBpJztcbmltcG9ydCB7IHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XG5cbmltcG9ydCBjcmVhdGVBZGFwdGl2ZUNhcmRzQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUgZnJvbSAnLi9hZGFwdGl2ZUNhcmRzL2NyZWF0ZUFkYXB0aXZlQ2FyZHNBdHRhY2htZW50Rm9yU2NyZWVuUmVhZGVyTWlkZGxld2FyZSc7XG5pbXBvcnQgY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRNaWRkbGV3YXJlIGZyb20gJy4vYWRhcHRpdmVDYXJkcy9jcmVhdGVBZGFwdGl2ZUNhcmRzQXR0YWNobWVudE1pZGRsZXdhcmUnO1xuaW1wb3J0IGNyZWF0ZUFkYXB0aXZlQ2FyZHNTdHlsZVNldCBmcm9tICcuL2FkYXB0aXZlQ2FyZHMvU3R5bGVzL2NyZWF0ZUFkYXB0aXZlQ2FyZHNTdHlsZVNldCc7XG5pbXBvcnQgZGVmYXVsdFJlbmRlck1hcmtkb3duIGZyb20gJy4vbWFya2Rvd24vcmVuZGVyTWFya2Rvd24nO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiB1c2VDb21wb3NlclByb3BzKHtcbiAgYXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUsXG4gIGF0dGFjaG1lbnRNaWRkbGV3YXJlLFxuICByZW5kZXJNYXJrZG93bixcbiAgc3R5bGVPcHRpb25zLFxuICBzdHlsZVNldFxufToge1xuICBhdHRhY2htZW50Rm9yU2NyZWVuUmVhZGVyTWlkZGxld2FyZTogQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmVbXTtcbiAgYXR0YWNobWVudE1pZGRsZXdhcmU6IEF0dGFjaG1lbnRNaWRkbGV3YXJlW107XG4gIHJlbmRlck1hcmtkb3duPzogKFxuICAgIG1hcmtkb3duOiBzdHJpbmcsXG4gICAgbmV3TGluZU9wdGlvbnM6IHsgbWFya2Rvd25SZXNwZWN0Q1JMRjogYm9vbGVhbiB9LFxuICAgIGxpbmtPcHRpb25zOiB7IGV4dGVybmFsTGlua0FsdDogc3RyaW5nIH1cbiAgKSA9PiBzdHJpbmc7XG4gIHN0eWxlT3B0aW9uczogYW55O1xuICBzdHlsZVNldDogYW55O1xufSk6IHtcbiAgYXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmU6IEF0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlW107XG4gIGF0dGFjaG1lbnRNaWRkbGV3YXJlOiBBdHRhY2htZW50TWlkZGxld2FyZVtdO1xuICByZW5kZXJNYXJrZG93bjogKFxuICAgIG1hcmtkb3duOiBzdHJpbmcsXG4gICAgbmV3TGluZU9wdGlvbnM6IHsgbWFya2Rvd25SZXNwZWN0Q1JMRjogYm9vbGVhbiB9LFxuICAgIGxpbmtPcHRpb25zOiB7IGV4dGVybmFsTGlua0FsdDogc3RyaW5nIH1cbiAgKSA9PiBzdHJpbmc7XG4gIGV4dHJhU3R5bGVTZXQ6IGFueTtcbn0ge1xuICBjb25zdCBwYXRjaGVkQXR0YWNobWVudE1pZGRsZXdhcmUgPSB1c2VNZW1vKFxuICAgICgpID0+IFsuLi5hdHRhY2htZW50TWlkZGxld2FyZSwgY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRNaWRkbGV3YXJlKCldLFxuICAgIFthdHRhY2htZW50TWlkZGxld2FyZV1cbiAgKTtcblxuICBjb25zdCBwYXRjaGVkQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUgPSB1c2VNZW1vKFxuICAgICgpID0+IFsuLi5hdHRhY2htZW50Rm9yU2NyZWVuUmVhZGVyTWlkZGxld2FyZSwgY3JlYXRlQWRhcHRpdmVDYXJkc0F0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlKCldLFxuICAgIFthdHRhY2htZW50Rm9yU2NyZWVuUmVhZGVyTWlkZGxld2FyZV1cbiAgKTtcblxuICAvLyBXaGVuIHN0eWxlU2V0IGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBzdHlsZU9wdGlvbnMgd2lsbCBiZSB1c2VkIHRvIGNyZWF0ZSBBZGFwdGl2ZSBDYXJkcyBzdHlsZVNldCBhbmQgbWVyZ2VkIGludG8gdXNlU3R5bGVTZXQuXG4gIGNvbnN0IGV4dHJhU3R5bGVTZXQgPSB1c2VNZW1vKFxuICAgICgpID0+IChzdHlsZVNldCA/IHVuZGVmaW5lZCA6IGNyZWF0ZUFkYXB0aXZlQ2FyZHNTdHlsZVNldChzdHlsZU9wdGlvbnMpKSxcbiAgICBbc3R5bGVPcHRpb25zLCBzdHlsZVNldF1cbiAgKTtcblxuICBjb25zdCBwYXRjaGVkUmVuZGVyTWFya2Rvd24gPSB1c2VNZW1vKFxuICAgICgpID0+ICh0eXBlb2YgcmVuZGVyTWFya2Rvd24gPT09ICd1bmRlZmluZWQnID8gZGVmYXVsdFJlbmRlck1hcmtkb3duIDogcmVuZGVyTWFya2Rvd24pLFxuICAgIFtyZW5kZXJNYXJrZG93bl1cbiAgKTtcblxuICByZXR1cm4ge1xuICAgIGF0dGFjaG1lbnRGb3JTY3JlZW5SZWFkZXJNaWRkbGV3YXJlOiBwYXRjaGVkQXR0YWNobWVudEZvclNjcmVlblJlYWRlck1pZGRsZXdhcmUsXG4gICAgYXR0YWNobWVudE1pZGRsZXdhcmU6IHBhdGNoZWRBdHRhY2htZW50TWlkZGxld2FyZSxcbiAgICBleHRyYVN0eWxlU2V0LFxuICAgIHJlbmRlck1hcmtkb3duOiBwYXRjaGVkUmVuZGVyTWFya2Rvd25cbiAgfTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFDQTs7QUFFQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFZSxTQUFTQSxnQkFBVCxPQXlCYjtFQUFBLElBeEJBQyxtQ0F3QkEsUUF4QkFBLG1DQXdCQTtFQUFBLElBdkJBQyxvQkF1QkEsUUF2QkFBLG9CQXVCQTtFQUFBLElBdEJBQyxjQXNCQSxRQXRCQUEsY0FzQkE7RUFBQSxJQXJCQUMsWUFxQkEsUUFyQkFBLFlBcUJBO0VBQUEsSUFwQkFDLFFBb0JBLFFBcEJBQSxRQW9CQTtFQUNBLElBQU1DLDJCQUEyQixHQUFHLElBQUFDLGNBQUEsRUFDbEM7SUFBQSxrREFBVUwsb0JBQVYsSUFBZ0MsSUFBQU0sZ0RBQUEsR0FBaEM7RUFBQSxDQURrQyxFQUVsQyxDQUFDTixvQkFBRCxDQUZrQyxDQUFwQztFQUtBLElBQU1PLDBDQUEwQyxHQUFHLElBQUFGLGNBQUEsRUFDakQ7SUFBQSxrREFBVU4sbUNBQVYsSUFBK0MsSUFBQVMsK0RBQUEsR0FBL0M7RUFBQSxDQURpRCxFQUVqRCxDQUFDVCxtQ0FBRCxDQUZpRCxDQUFuRCxDQU5BLENBV0E7O0VBQ0EsSUFBTVUsYUFBYSxHQUFHLElBQUFKLGNBQUEsRUFDcEI7SUFBQSxPQUFPRixRQUFRLEdBQUdPLFNBQUgsR0FBZSxJQUFBQyxvQ0FBQSxFQUE0QlQsWUFBNUIsQ0FBOUI7RUFBQSxDQURvQixFQUVwQixDQUFDQSxZQUFELEVBQWVDLFFBQWYsQ0FGb0IsQ0FBdEI7RUFLQSxJQUFNUyxxQkFBcUIsR0FBRyxJQUFBUCxjQUFBLEVBQzVCO0lBQUEsT0FBTyxPQUFPSixjQUFQLEtBQTBCLFdBQTFCLEdBQXdDWSx1QkFBeEMsR0FBZ0VaLGNBQXZFO0VBQUEsQ0FENEIsRUFFNUIsQ0FBQ0EsY0FBRCxDQUY0QixDQUE5QjtFQUtBLE9BQU87SUFDTEYsbUNBQW1DLEVBQUVRLDBDQURoQztJQUVMUCxvQkFBb0IsRUFBRUksMkJBRmpCO0lBR0xLLGFBQWEsRUFBYkEsYUFISztJQUlMUixjQUFjLEVBQUVXO0VBSlgsQ0FBUDtBQU1EIn0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botframework-webchat",
3
- "version": "4.15.10-main.20230908.de79e0e",
3
+ "version": "4.15.10-main.20230915.bb5898e",
4
4
  "description": "A highly-customizable web-based chat client for Azure Bot Services.",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -92,10 +92,10 @@
92
92
  "@babel/runtime": "7.19.0",
93
93
  "adaptivecards": "2.11.1",
94
94
  "botframework-directlinejs": "0.15.4",
95
- "botframework-directlinespeech-sdk": "4.15.10-main.20230908.de79e0e",
96
- "botframework-webchat-api": "4.15.10-main.20230908.de79e0e",
97
- "botframework-webchat-component": "4.15.10-main.20230908.de79e0e",
98
- "botframework-webchat-core": "4.15.10-main.20230908.de79e0e",
95
+ "botframework-directlinespeech-sdk": "4.15.10-main.20230915.bb5898e",
96
+ "botframework-webchat-api": "4.15.10-main.20230915.bb5898e",
97
+ "botframework-webchat-component": "4.15.10-main.20230915.bb5898e",
98
+ "botframework-webchat-core": "4.15.10-main.20230915.bb5898e",
99
99
  "classnames": "2.3.2",
100
100
  "core-js": "3.28.0",
101
101
  "markdown-it": "13.0.1",
@@ -103,6 +103,8 @@
103
103
  "markdown-it-attrs-es5": "2.0.2",
104
104
  "markdown-it-for-inline": "0.1.1",
105
105
  "math-random": "2.0.1",
106
+ "mdast": "3.0.0",
107
+ "mdast-util-from-markdown": "2.0.0",
106
108
  "memoize-one": "6.0.0",
107
109
  "microsoft-cognitiveservices-speech-sdk": "1.17.0",
108
110
  "prop-types": "15.8.1",
@@ -126,8 +128,8 @@
126
128
  "babel-plugin-transform-inline-environment-variables": "^0.4.4",
127
129
  "concurrently": "^7.6.0",
128
130
  "esbuild": "^0.17.10",
129
- "isomorphic-react": "4.15.10-main.20230908.de79e0e",
130
- "isomorphic-react-dom": "4.15.10-main.20230908.de79e0e",
131
+ "isomorphic-react": "4.15.10-main.20230915.bb5898e",
132
+ "isomorphic-react-dom": "4.15.10-main.20230915.bb5898e",
131
133
  "source-map-loader": "^4.0.1",
132
134
  "terser-webpack-plugin": "^5.3.6",
133
135
  "typescript": "^4.9.5",
@@ -1,6 +1,6 @@
1
1
  /* eslint no-magic-numbers: ["error", { "ignore": [2] }] */
2
2
 
3
- import renderMarkdown from '../renderMarkdown';
3
+ import renderMarkdown from '../markdown/renderMarkdown';
4
4
 
5
5
  describe('renderMarkdown', () => {
6
6
  it('should render markdown', () => {
@@ -54,7 +54,7 @@ describe('renderMarkdown', () => {
54
54
 
55
55
  expect(renderMarkdown('[example](https://sample.com){aria-label="Sample label"}', styleOptions))
56
56
  .toMatchInlineSnapshot(`
57
- "<p><a href=\\"https://sample.com\\" aria-label=\\"Sample label\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\">example<img src=\\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\\" alt class=\\"webchat__markdown__external-link-icon\\" /></a></p>
57
+ "<p><a href=\\"https://sample.com\\" aria-label=\\"Sample label\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\">example<img src=\\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\\" alt class=\\"webchat__render-markdown__external-link-icon\\" title /></a></p>
58
58
  "
59
59
  `);
60
60
  });
@@ -65,7 +65,7 @@ describe('renderMarkdown', () => {
65
65
 
66
66
  expect(renderMarkdown('[example](https://sample.com){aria-label="Sample label"}', styleOptions, options))
67
67
  .toMatchInlineSnapshot(`
68
- "<p><a href=\\"https://sample.com\\" aria-label=\\"Sample label\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\" title=\\"Opens in a new window, external.\\">example<img src=\\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\\" alt=\\"Opens in a new window, external.\\" class=\\"webchat__markdown__external-link-icon\\" /></a></p>
68
+ "<p><a href=\\"https://sample.com\\" aria-label=\\"Sample label\\" rel=\\"noopener noreferrer\\" target=\\"_blank\\">example<img src=\\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\\" alt class=\\"webchat__render-markdown__external-link-icon\\" title=\\"Opens in a new window, external.\\" /></a></p>
69
69
  "
70
70
  `);
71
71
  });
@@ -25,10 +25,11 @@ import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
25
25
  import useDisabledModEffect from './AdaptiveCardHacks/useDisabledModEffect';
26
26
  import usePersistValuesModEffect from './AdaptiveCardHacks/usePersistValuesModEffect';
27
27
  import useRoleModEffect from './AdaptiveCardHacks/useRoleModEffect';
28
+ import useStyleSet from '../../hooks/useStyleSet';
28
29
  import useValueRef from './AdaptiveCardHacks/private/useValueRef';
29
30
 
30
31
  const { ErrorBox } = Components;
31
- const { useDisabled, useLocalizer, usePerformCardAction, useRenderMarkdownAsHTML, useScrollToEnd, useStyleSet } = hooks;
32
+ const { useDisabled, useLocalizer, usePerformCardAction, useRenderMarkdownAsHTML, useScrollToEnd } = hooks;
32
33
 
33
34
  const node_env = process.env.node_env || process.env.NODE_ENV;
34
35
 
@@ -1,14 +1,14 @@
1
1
  /* eslint react/no-array-index-key: "off" */
2
2
 
3
- import { Components, hooks } from 'botframework-webchat-component';
3
+ import { Components } from 'botframework-webchat-component';
4
4
  import PropTypes from 'prop-types';
5
5
  import React, { FC } from 'react';
6
6
  import type { DirectLineAnimationCard } from 'botframework-webchat-core';
7
7
 
8
8
  import CommonCard from './CommonCard';
9
+ import useStyleSet from '../../hooks/useStyleSet';
9
10
 
10
11
  const { ImageContent, VideoContent } = Components;
11
- const { useStyleSet } = hooks;
12
12
 
13
13
  type AnimationCardContentProps = {
14
14
  actionPerformedClassName?: string;
@@ -1,14 +1,14 @@
1
1
  /* eslint react/no-array-index-key: "off" */
2
2
 
3
- import { Components, hooks } from 'botframework-webchat-component';
3
+ import { Components } from 'botframework-webchat-component';
4
4
  import PropTypes from 'prop-types';
5
5
  import React, { FC } from 'react';
6
6
  import type { DirectLineAudioCard } from 'botframework-webchat-core';
7
7
 
8
8
  import CommonCard from './CommonCard';
9
+ import useStyleSet from '../../hooks/useStyleSet';
9
10
 
10
11
  const { AudioContent } = Components;
11
- const { useStyleSet } = hooks;
12
12
 
13
13
  type AudioCardContentProps = {
14
14
  actionPerformedClassName?: string;
@@ -1,11 +1,9 @@
1
- import { hooks } from 'botframework-webchat-component';
2
1
  import PropTypes from 'prop-types';
3
2
  import React, { FC } from 'react';
4
3
  import type { DirectLineSignInCard } from 'botframework-webchat-core';
5
4
 
6
5
  import CommonCard from './CommonCard';
7
-
8
- const { useStyleSet } = hooks;
6
+ import useStyleSet from '../../hooks/useStyleSet';
9
7
 
10
8
  type SignInCardContentProps = {
11
9
  actionPerformedClassName?: string;
@@ -1,13 +1,13 @@
1
1
  /* eslint react/no-array-index-key: "off" */
2
2
 
3
- import { Components, hooks } from 'botframework-webchat-component';
3
+ import { Components } from 'botframework-webchat-component';
4
4
  import PropTypes from 'prop-types';
5
5
  import React, { FC } from 'react';
6
6
  import type { DirectLineVideoCard } from 'botframework-webchat-core';
7
7
 
8
8
  import CommonCard from './CommonCard';
9
+ import useStyleSet from '../../hooks/useStyleSet';
9
10
 
10
- const { useStyleSet } = hooks;
11
11
  const { VideoContent } = Components;
12
12
 
13
13
  type VideoCardContentProps = {
@@ -0,0 +1,13 @@
1
+ import { hooks } from 'botframework-webchat-component';
2
+
3
+ import type AdaptiveCardsStyleSet from '../adaptiveCards/AdaptiveCardsStyleSet';
4
+
5
+ const useMinimalStyleSet = hooks.useStyleSet;
6
+
7
+ type MinimalStyleSet = ReturnType<typeof useMinimalStyleSet>[0];
8
+
9
+ export default function useStyleSet(): readonly [MinimalStyleSet & AdaptiveCardsStyleSet] {
10
+ const [styleOptions] = useMinimalStyleSet();
11
+
12
+ return Object.freeze([styleOptions as MinimalStyleSet & AdaptiveCardsStyleSet] as const);
13
+ }
package/src/index.ts CHANGED
@@ -22,12 +22,13 @@ import HeroCardContent from './adaptiveCards/Attachment/HeroCardContent';
22
22
  import OAuthCardContent from './adaptiveCards/Attachment/OAuthCardContent';
23
23
  import ReactWebChat from './FullReactWebChat';
24
24
  import ReceiptCardContent from './adaptiveCards/Attachment/ReceiptCardContent';
25
- import renderMarkdown from './renderMarkdown';
25
+ import renderMarkdown from './markdown/renderMarkdown';
26
26
  import SignInCardContent from './adaptiveCards/Attachment/SignInCardContent';
27
27
  import ThumbnailCardContent from './adaptiveCards/Attachment/ThumbnailCardContent';
28
28
  import useAdaptiveCardsHostConfig from './adaptiveCards/hooks/useAdaptiveCardsHostConfig';
29
29
  import useAdaptiveCardsPackage from './adaptiveCards/hooks/useAdaptiveCardsPackage';
30
30
  import useStyleOptions from './hooks/useStyleOptions';
31
+ import useStyleSet from './hooks/useStyleSet';
31
32
  import VideoCardContent from './adaptiveCards/Attachment/VideoCardContent';
32
33
 
33
34
  const renderWebChat = coreRenderWebChat.bind(null, ReactWebChat);
@@ -56,7 +57,8 @@ const patchedHooks = {
56
57
  ...hooks,
57
58
  useAdaptiveCardsHostConfig,
58
59
  useAdaptiveCardsPackage,
59
- useStyleOptions
60
+ useStyleOptions,
61
+ useStyleSet
60
62
  };
61
63
 
62
64
  const AdditionalComponents = {
@@ -0,0 +1,27 @@
1
+ import MarkdownIt from 'markdown-it';
2
+
3
+ import ariaLabel, { pre, post } from './ariaLabel';
4
+
5
+ test('should render {aria-label="Bing search"}', () => {
6
+ const markdown = 'Visit [Bing](https://bing.com/){aria-label="Bing search"} to start.';
7
+
8
+ const html = post(new MarkdownIt().use(ariaLabel).render(pre(markdown)));
9
+
10
+ expect(html).toBe('<p>Visit <a href="https://bing.com/" aria-label="Bing search">Bing</a> to start.</p>\n');
11
+ });
12
+
13
+ test('should render {1} as-is', () => {
14
+ const markdown = 'This is number {1}.';
15
+
16
+ const html = post(new MarkdownIt().use(ariaLabel).render(pre(markdown)));
17
+
18
+ expect(html).toBe('<p>This is number {1}.</p>\n');
19
+ });
20
+
21
+ test('should render {title="abc"} as-is', () => {
22
+ const markdown = 'Visit [Bing](https://bing.com/){title="abc"} to start.';
23
+
24
+ const html = post(new MarkdownIt().use(ariaLabel).render(pre(markdown)));
25
+
26
+ expect(html).toBe('<p>Visit <a href="https://bing.com/">Bing</a>{title=&quot;abc&quot;} to start.</p>\n');
27
+ });
@@ -0,0 +1,52 @@
1
+ import MarkdownIt from 'markdown-it';
2
+ import markdownItAttrs from 'markdown-it-attrs-es5';
3
+
4
+ const MARKDOWN_ATTRS_LEFT_DELIMITER = '⟬';
5
+ // Make sure the delimiter is free from any RegExp characters, such as *, ?, etc.
6
+ // IE11 does not support "u" flag and Babel could not remove it. We intentionally omitting the "u" flag here.
7
+ // eslint-disable-next-line require-unicode-regexp
8
+ const MARKDOWN_ATTRS_LEFT_DELIMITER_PATTERN = new RegExp(MARKDOWN_ATTRS_LEFT_DELIMITER, 'g');
9
+
10
+ const MARKDOWN_ATTRS_RIGHT_DELIMITER = '⟭';
11
+ // Make sure the delimiter is free from any RegExp characters, such as *, ?, etc.
12
+ // IE11 does not support "u" flag and Babel could not remove it. We intentionally omitting the "u" flag here.
13
+ // eslint-disable-next-line require-unicode-regexp
14
+ const MARKDOWN_ATTRS_RIGHT_DELIMITER_PATTERN = new RegExp(MARKDOWN_ATTRS_RIGHT_DELIMITER, 'g');
15
+
16
+ const ariaLabel = (markdown: typeof MarkdownIt): typeof MarkdownIt =>
17
+ markdown.use(markdownItAttrs, {
18
+ // `markdown-it-attrs` is added for accessibility and allow bot developers to specify `aria-label`.
19
+ // We are allowlisting `aria-label` only as it is allowlisted in `sanitize-html`.
20
+ // Other `aria-*` will be sanitized even we allowlisted here.
21
+ allowedAttributes: ['aria-label'],
22
+ leftDelimiter: MARKDOWN_ATTRS_LEFT_DELIMITER,
23
+ rightDelimiter: MARKDOWN_ATTRS_RIGHT_DELIMITER
24
+ });
25
+
26
+ // TODO: We should fold pre/post back into the plugin.
27
+ const pre = (markdown: string): string =>
28
+ // Related to #3165.
29
+ // We only support attributes "aria-label" and should leave other attributes as-is.
30
+ // However, `markdown-it-attrs` remove unrecognized attributes, such as {hello}.
31
+ // Before passing to `markdown-it-attrs`, we will convert known attributes from {aria-label="..."} into ⟬aria-label="..."⟭ (using white tortoise shell brackets).
32
+ // Then, we ask `markdown-it-attrs` to only process the new brackets, so it should only try to process things that we allowlisted.
33
+ // Lastly, we revert tortoise shell brackets back to curly brackets, for unprocessed attributes.
34
+ markdown
35
+ // IE11 does not support "u" flag and Babel could not remove it. We intentionally omitting the "u" flag here.
36
+ // eslint-disable-next-line require-unicode-regexp
37
+ .replace(/\{\s*aria-label()\s*\}/gi, `${MARKDOWN_ATTRS_LEFT_DELIMITER}aria-label${MARKDOWN_ATTRS_RIGHT_DELIMITER}`)
38
+ .replace(
39
+ // IE11 does not support "u" flag and Babel could not remove it. We intentionally omitting the "u" flag here.
40
+ // eslint-disable-next-line require-unicode-regexp
41
+ /\{\s*aria-label=("[^"]*"|[^\s}]*)\s*\}/gi,
42
+ (_, valueInsideQuotes) =>
43
+ `${MARKDOWN_ATTRS_LEFT_DELIMITER}aria-label=${valueInsideQuotes}${MARKDOWN_ATTRS_RIGHT_DELIMITER}`
44
+ );
45
+
46
+ const post = (html: string): string =>
47
+ // Restore attributes not processed by `markdown-it-attrs`.
48
+ // TODO: [P2] #2511 After we fixed our polyfill story, we should use "String.prototype.replaceAll" instead of RegExp for replace all occurrences.
49
+ html.replace(MARKDOWN_ATTRS_LEFT_DELIMITER_PATTERN, '{').replace(MARKDOWN_ATTRS_RIGHT_DELIMITER_PATTERN, '}');
50
+
51
+ export default ariaLabel;
52
+ export { pre, post };
@@ -0,0 +1,80 @@
1
+ import MarkdownIt from 'markdown-it';
2
+
3
+ import betterLink from './betterLink';
4
+
5
+ // ariaLabel?: false | string;
6
+ // asButton?: boolean;
7
+ // iconAlt?: string;
8
+ // iconClassName?: string;
9
+ // className?: false | string;
10
+ // rel?: false | string;
11
+ // target?: false | string;
12
+ // title?: false | string;
13
+
14
+ test('should render "ariaLabel"', () => {
15
+ const html = new MarkdownIt()
16
+ .use(betterLink, () => ({ ariaLabel: 'Hello, World!' }))
17
+ .render('This is a [link](https://bing.com/).');
18
+
19
+ expect(html).toBe('<p>This is a <a href="https://bing.com/" aria-label="Hello, World!">link</a>.</p>\n');
20
+ });
21
+
22
+ test('should render "asButton"', () => {
23
+ const html = new MarkdownIt()
24
+ .use(betterLink, () => ({ asButton: true }))
25
+ .render('This is a [link](https://bing.com/).');
26
+
27
+ expect(html).toBe('<p>This is a <button type="button" value="https://bing.com/">link</button>.</p>\n');
28
+ });
29
+
30
+ test('should render "className"', () => {
31
+ const html = new MarkdownIt()
32
+ .use(betterLink, () => ({ className: 'link' }))
33
+ .render('This is a [link](https://bing.com/).');
34
+
35
+ expect(html).toBe('<p>This is a <a href="https://bing.com/" class="link">link</a>.</p>\n');
36
+ });
37
+
38
+ test('should render "iconClassName"', () => {
39
+ const html = new MarkdownIt()
40
+ .use(betterLink, () => ({ iconClassName: 'icon' }))
41
+ .render('This is a [link](https://bing.com/).');
42
+
43
+ expect(html).toBe(
44
+ '<p>This is a <a href="https://bing.com/">link<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="" class="icon"></a>.</p>\n'
45
+ );
46
+ });
47
+
48
+ test('should render "iconClassName" with "iconAlt"', () => {
49
+ const html = new MarkdownIt()
50
+ .use(betterLink, () => ({ iconAlt: 'open in new window', iconClassName: 'icon' }))
51
+ .render('This is a [link](https://bing.com/).');
52
+
53
+ expect(html).toBe(
54
+ '<p>This is a <a href="https://bing.com/">link<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="" class="icon" title="open in new window"></a>.</p>\n'
55
+ );
56
+ });
57
+
58
+ test('should render "rel"', () => {
59
+ const html = new MarkdownIt()
60
+ .use(betterLink, () => ({ rel: 'noopener noreferrer' }))
61
+ .render('This is a [link](https://bing.com/).');
62
+
63
+ expect(html).toBe('<p>This is a <a href="https://bing.com/" rel="noopener noreferrer">link</a>.</p>\n');
64
+ });
65
+
66
+ test('should render "target"', () => {
67
+ const html = new MarkdownIt()
68
+ .use(betterLink, () => ({ target: '_blank' }))
69
+ .render('This is a [link](https://bing.com/).');
70
+
71
+ expect(html).toBe('<p>This is a <a href="https://bing.com/" target="_blank">link</a>.</p>\n');
72
+ });
73
+
74
+ test('should render "title"', () => {
75
+ const html = new MarkdownIt()
76
+ .use(betterLink, () => ({ title: 'Hello, World!' }))
77
+ .render('This is a [link](https://bing.com/).');
78
+
79
+ expect(html).toBe('<p>This is a <a href="https://bing.com/" title="Hello, World!">link</a>.</p>\n');
80
+ });
@@ -0,0 +1,113 @@
1
+ import iterator from 'markdown-it-for-inline';
2
+ import MarkdownIt from 'markdown-it';
3
+
4
+ // Put a transparent pixel instead of the "open in new window" icon, so developers can easily modify the icon in CSS.
5
+ const TRANSPARENT_GIF = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
6
+
7
+ type AttributeSetter = false | string | ((value?: string) => string);
8
+
9
+ type Decoration = {
10
+ /** Value of "aria-label" attribute of the link. If set to `false`, remove existing attribute. */
11
+ ariaLabel?: AttributeSetter;
12
+
13
+ /** Turns this link into a <button> with "value" attribute instead of "href". */
14
+ asButton?: boolean;
15
+
16
+ /** Value of "class" attribute of the link. If set to `false`, remove existing attribute. */
17
+ className?: AttributeSetter;
18
+
19
+ /** Alternate text of the image icon appended to the link. */
20
+ iconAlt?: string;
21
+
22
+ /** Class name of the image icon appended to the link. */
23
+ iconClassName?: string;
24
+
25
+ /** Value of "rel" attribute of the link. If set to `false`, remove existing attribute. */
26
+ rel?: AttributeSetter;
27
+
28
+ /** Value of "target" attribute of the link. If set to `false`, remove existing attribute. */
29
+ target?: AttributeSetter;
30
+
31
+ /** Value of "title" attribute of the link. If set to `false`, remove existing attribute. */
32
+ title?: AttributeSetter;
33
+ };
34
+
35
+ // This is used for parsing Markdown for external links.
36
+ const internalMarkdownIt = new MarkdownIt();
37
+
38
+ function setTokenAttribute(attrs: Array<[string, string]>, name: string, value?: AttributeSetter) {
39
+ const index = attrs.findIndex(entry => entry[0] === name);
40
+
41
+ if (value === false) {
42
+ ~index && attrs.splice(index, 1);
43
+ } else if (typeof value === 'string') {
44
+ if (~index) {
45
+ attrs[+index][1] = value;
46
+ } else {
47
+ attrs.push([name, value]);
48
+ }
49
+ } else if (typeof value === 'function') {
50
+ if (~index) {
51
+ attrs[+index][1] = value(attrs[+index][1]);
52
+ } else {
53
+ attrs.push([name, value()]);
54
+ }
55
+ }
56
+ }
57
+
58
+ const betterLink = (
59
+ markdown: typeof MarkdownIt,
60
+ decorate: (href: string, textContent: string) => Decoration | undefined
61
+ ): typeof MarkdownIt =>
62
+ markdown.use(iterator, 'url_new_win', 'link_open', (tokens, index) => {
63
+ const indexOfLinkCloseToken = tokens.indexOf(tokens.slice(index + 1).find(({ type }) => type === 'link_close'));
64
+ const token = tokens[+index];
65
+
66
+ const [, href] = token.attrs.find(([name]) => name === 'href');
67
+ const nodesInLink = tokens.slice(index + 1, indexOfLinkCloseToken);
68
+
69
+ const textContent = nodesInLink
70
+ .filter(({ type }) => type === 'text')
71
+ .map(({ content }) => content)
72
+ .join(' ');
73
+
74
+ const decoration = decorate(href, textContent);
75
+
76
+ if (!decoration) {
77
+ return;
78
+ }
79
+
80
+ const { ariaLabel, asButton, className, iconAlt, iconClassName, rel, target, title } = decoration;
81
+
82
+ setTokenAttribute(token.attrs, 'aria-label', ariaLabel);
83
+ setTokenAttribute(token.attrs, 'class', className);
84
+ setTokenAttribute(token.attrs, 'title', title);
85
+
86
+ if (iconClassName) {
87
+ const iconTokens = internalMarkdownIt.parseInline(`![](${TRANSPARENT_GIF})`)[0].children;
88
+
89
+ setTokenAttribute(iconTokens[0].attrs, 'class', iconClassName);
90
+ setTokenAttribute(iconTokens[0].attrs, 'title', iconAlt);
91
+
92
+ // Add an icon before </a>.
93
+ ~indexOfLinkCloseToken && tokens.splice(indexOfLinkCloseToken, 0, ...iconTokens);
94
+ }
95
+
96
+ if (asButton) {
97
+ setTokenAttribute(token.attrs, 'href', false);
98
+
99
+ token.tag = 'button';
100
+
101
+ setTokenAttribute(token.attrs, 'type', 'button');
102
+ setTokenAttribute(token.attrs, 'value', href);
103
+
104
+ if (~indexOfLinkCloseToken) {
105
+ tokens[+indexOfLinkCloseToken].tag = 'button';
106
+ }
107
+ } else {
108
+ setTokenAttribute(token.attrs, 'rel', rel);
109
+ setTokenAttribute(token.attrs, 'target', target);
110
+ }
111
+ });
112
+
113
+ export default betterLink;