From 5e9d6d9dac82b00f00a4909c6aab274371c061d6 Mon Sep 17 00:00:00 2001 From: patniko Date: Mon, 16 Mar 2020 18:51:36 -0700 Subject: [PATCH 1/3] Support for aria-labels on link using [link](url){aria-label="Screen reader description"} format. --- packages/bundle/package-lock.json | 5 +++ packages/bundle/package.json | 1 + .../src/__tests__/renderMarkdown.spec.js | 7 ++++ packages/bundle/src/renderMarkdown.js | 37 ++++++++++--------- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/packages/bundle/package-lock.json b/packages/bundle/package-lock.json index ac22bc93a9..4499500329 100644 --- a/packages/bundle/package-lock.json +++ b/packages/bundle/package-lock.json @@ -7223,6 +7223,11 @@ "uc.micro": "^1.0.5" } }, + "markdown-it-attrs": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/markdown-it-attrs/-/markdown-it-attrs-3.0.2.tgz", + "integrity": "sha512-q45vdXU9TSWaHgFkWEFM97YHEoCmOyG9csLLdv3oVC6ARjT77u4wfng9rRtSOMb5UpxzT7zTX5GBbwm15H40dw==" + }, "markdown-it-for-inline": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/markdown-it-for-inline/-/markdown-it-for-inline-0.1.1.tgz", diff --git a/packages/bundle/package.json b/packages/bundle/package.json index 13bea222de..d0cda420b6 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -37,6 +37,7 @@ "botframework-webchat-core": "0.0.0-0", "core-js": "^3.6.4", "markdown-it": "^10.0.0", + "markdown-it-attrs": "^3.0.2", "markdown-it-for-inline": "^0.1.1", "memoize-one": "^5.1.1", "microsoft-cognitiveservices-speech-sdk": "1.6.0", diff --git a/packages/bundle/src/__tests__/renderMarkdown.spec.js b/packages/bundle/src/__tests__/renderMarkdown.spec.js index d32a30361f..78c34c613e 100644 --- a/packages/bundle/src/__tests__/renderMarkdown.spec.js +++ b/packages/bundle/src/__tests__/renderMarkdown.spec.js @@ -43,6 +43,13 @@ describe('renderMarkdown', () => { ); }); + it('should render aria-labels', () => { + const options = { markdownRespectCRLF: true }; + expect(renderMarkdown('[example](sample.com){aria-label="Sample label"}', options)).toBe( + '

example

\n' + ); + }); + it('should render sip protocol links correctly', () => { const options = { markdownRespectCRLF: true }; expect(renderMarkdown(`[example@test.com](sip:example@test.com)`, options)).toBe( diff --git a/packages/bundle/src/renderMarkdown.js b/packages/bundle/src/renderMarkdown.js index 2f88a71f29..d721b6dcae 100644 --- a/packages/bundle/src/renderMarkdown.js +++ b/packages/bundle/src/renderMarkdown.js @@ -2,11 +2,12 @@ import iterator from 'markdown-it-for-inline'; import MarkdownIt from 'markdown-it'; +import markdownItAttrs from 'markdown-it-attrs'; import sanitizeHTML from 'sanitize-html'; const SANITIZE_HTML_OPTIONS = { allowedAttributes: { - a: ['href', 'name', 'target', 'title'], + a: ['href', 'name', 'target', 'title', 'aria-label'], img: ['alt', 'src'] }, allowedSchemes: ['data', 'http', 'https', 'ftp', 'mailto', 'sip', 'tel'], @@ -53,25 +54,27 @@ const customMarkdownIt = new MarkdownIt({ linkify: true, typographer: true, xhtmlOut: true -}).use(iterator, 'url_new_win', 'link_open', (tokens, index) => { - // TODO: [P4] This is copied from v3 and looks clunky - // We should refactor this code - const targetAttrIndex = tokens[index].attrIndex('target'); +}) + .use(markdownItAttrs) + .use(iterator, 'url_new_win', 'link_open', (tokens, index) => { + // TODO: [P4] This is copied from v3 and looks clunky + // We should refactor this code + const targetAttrIndex = tokens[index].attrIndex('target'); - if (~targetAttrIndex) { - tokens[index].attrs[targetAttrIndex][1] = '_blank'; - } else { - tokens[index].attrPush(['target', '_blank']); - } + if (~targetAttrIndex) { + tokens[index].attrs[targetAttrIndex][1] = '_blank'; + } else { + tokens[index].attrPush(['target', '_blank']); + } - const relAttrIndex = tokens[index].attrIndex('rel'); + const relAttrIndex = tokens[index].attrIndex('rel'); - if (~relAttrIndex) { - tokens[index].attrs[relAttrIndex][1] = 'noopener noreferrer'; - } else { - tokens[index].attrPush(['target', 'noopener noreferrer']); - } -}); + if (~relAttrIndex) { + tokens[index].attrs[relAttrIndex][1] = 'noopener noreferrer'; + } else { + tokens[index].attrPush(['target', 'noopener noreferrer']); + } + }); export default function render(markdown, { markdownRespectCRLF }) { if (markdownRespectCRLF) { From 6348d4dc44d20dda8298679d5b62e38ec3aa5541 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 16 Mar 2020 23:43:33 -0700 Subject: [PATCH 2/3] Added doc --- CHANGELOG.md | 1 + docs/HOOKS.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c3240aa75..d991966775 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Resolves [#2897](https://github.com/microsoft/BotFramework-WebChat/issues/2897). Moved from JUnit to VSTest reporter with file attachments, by [@compulim](https://github.com/compulim) in PR [#2990](https://github.com/microsoft/BotFramework-WebChat/pull/2990) +- Added `aria-label` attribute support for built-in Markdown engine, by [@patniko](https://github.com/patniko) in PR [#3022](https://github.com/microsoft/BotFramework-WebChat/pull/3022) ### Fixed diff --git a/docs/HOOKS.md b/docs/HOOKS.md index 90366cec52..6f1e992b3e 100644 --- a/docs/HOOKS.md +++ b/docs/HOOKS.md @@ -571,7 +571,7 @@ const renderMarkdown = useRenderMarkdown(); renderMarkdown('Hello, World!') === '

Hello, World!

\n'; ``` -To modify this value, change the value in the style options prop passed to Web Chat. +The Markdown engine can be reconfigured by passing `renderMarkdown` prop to Web Chat. The default engine is a customized [Markdown-It](https://npmjs.com/package/markdown-it) with [HTML sanitizer](https://npmjs.com/package/sanitize-html) and [support `aria-label` attribute](https://npmjs.com/package/markdown-it-attrs). The customization can be found in [bundle/src/renderMarkdown.js](https://github.com/microsoft/BotFramework-WebChat/tree/master/packages/bundle/src/renderMarkdown.js). ## `useRenderToast` From b696e60bbbbad5fa3a66287bb1420cbdf6af3774 Mon Sep 17 00:00:00 2001 From: William Wong Date: Mon, 16 Mar 2020 23:43:53 -0700 Subject: [PATCH 3/3] Sort --- packages/bundle/src/renderMarkdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bundle/src/renderMarkdown.js b/packages/bundle/src/renderMarkdown.js index d721b6dcae..f2d74bff23 100644 --- a/packages/bundle/src/renderMarkdown.js +++ b/packages/bundle/src/renderMarkdown.js @@ -7,7 +7,7 @@ import sanitizeHTML from 'sanitize-html'; const SANITIZE_HTML_OPTIONS = { allowedAttributes: { - a: ['href', 'name', 'target', 'title', 'aria-label'], + a: ['aria-label', 'href', 'name', 'target', 'title'], img: ['alt', 'src'] }, allowedSchemes: ['data', 'http', 'https', 'ftp', 'mailto', 'sip', 'tel'],