diff --git a/CHANGELOG.md b/CHANGELOG.md index e69e1f177c..69b6742b51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -319,6 +319,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/ by [@lexi-taylor](https://github.com/lexi-taylor) - Fixed `npm start` may fail subsequently as builds are not fully flushed to `/dist/`, in PR [#5599](https://github.com/microsoft/BotFramework-WebChat/pull/5599), by [@compulim](https://github.com/compulim) - Fixed published package types containing internal package references, in PR [#5610](https://github.com/microsoft/BotFramework-WebChat/pull/5610), by [@OEvgeny](https://github.com/OEvgeny) +- Fixed citation links are not properly matched against markdown links, in PR [#5614](https://github.com/microsoft/BotFramework-WebChat/pull/5614), by [@OEvgeny](https://github.com/OEvgeny) ### Removed diff --git a/__tests__/html2/citation/url.fluent.html b/__tests__/html2/citation/url.fluent.html new file mode 100644 index 0000000000..628206af79 --- /dev/null +++ b/__tests__/html2/citation/url.fluent.html @@ -0,0 +1,10 @@ + + + + Citation URL (fluent) + + + + diff --git a/__tests__/html2/citation/url.fluent.html.snap-1.png b/__tests__/html2/citation/url.fluent.html.snap-1.png new file mode 100644 index 0000000000..91bb35821b Binary files /dev/null and b/__tests__/html2/citation/url.fluent.html.snap-1.png differ diff --git a/__tests__/html2/citation/url.html b/__tests__/html2/citation/url.html new file mode 100644 index 0000000000..1279961be9 --- /dev/null +++ b/__tests__/html2/citation/url.html @@ -0,0 +1,343 @@ + + + + + Citation URL + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/__tests__/html2/citation/url.html.snap-1.png b/__tests__/html2/citation/url.html.snap-1.png new file mode 100644 index 0000000000..04233b7d60 Binary files /dev/null and b/__tests__/html2/citation/url.html.snap-1.png differ diff --git a/package-lock.json b/package-lock.json index dee9274e47..e1157a5367 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13202,7 +13202,9 @@ } }, "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "funding": [ { "type": "GitHub Sponsors", @@ -19038,6 +19040,7 @@ "micromark": "4.0.2", "micromark-extension-gfm": "3.0.0", "micromark-util-character": "2.1.1", + "micromark-util-sanitize-uri": "^2.0.1", "microsoft-cognitiveservices-speech-sdk": "1.17.0", "prop-types": "15.8.1", "punycode": "2.3.1", diff --git a/packages/bundle/package.json b/packages/bundle/package.json index e155d31ac3..c7c4259c60 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -188,6 +188,7 @@ "micromark": "4.0.2", "micromark-extension-gfm": "3.0.0", "micromark-util-character": "2.1.1", + "micromark-util-sanitize-uri": "^2.0.1", "microsoft-cognitiveservices-speech-sdk": "1.17.0", "prop-types": "15.8.1", "punycode": "2.3.1", @@ -240,8 +241,8 @@ }, "peerDependencies": { "@types/react": "^16.14.65", - "react-chain-of-responsibility": "0.4.0-main.c2f17da", "react": ">= 16.8.6", + "react-chain-of-responsibility": "0.4.0-main.c2f17da", "react-dom": ">= 16.8.6" } } diff --git a/packages/bundle/src/markdown/renderMarkdown.ts b/packages/bundle/src/markdown/renderMarkdown.ts index 3bb9a182ba..a4c7d49089 100644 --- a/packages/bundle/src/markdown/renderMarkdown.ts +++ b/packages/bundle/src/markdown/renderMarkdown.ts @@ -7,6 +7,7 @@ import { onErrorResumeNext } from 'botframework-webchat-core'; import katex from 'katex'; import { micromark } from 'micromark'; import { gfm, gfmHtml } from 'micromark-extension-gfm'; +import { sanitizeUri } from 'micromark-util-sanitize-uri'; import { math, mathHtml } from './mathExtension'; import betterLinkDocumentMod, { BetterLinkDocumentModDecoration } from './private/betterLinkDocumentMod'; @@ -26,7 +27,13 @@ export default function render( { markdownRespectCRLF, markdownRenderHTML }: Readonly<{ markdownRespectCRLF: boolean; markdownRenderHTML?: boolean }>, { externalLinkAlt }: RenderInit ): string { - const linkDefinitions = Array.from(iterateLinkDefinitions(markdown)); + const linkDefinitions = Array.from(iterateLinkDefinitions(markdown)).map(definition => + Object.freeze({ + ...definition, + markupUrl: sanitizeUri(definition.url), + parsedUrl: onErrorResumeNext(() => new URL(definition.url)) + }) + ); if (markdownRespectCRLF) { markdown = respectCRLFPre(markdown); @@ -41,13 +48,11 @@ export default function render( const ariaLabelSegments: string[] = [textContent]; const classes: Set = new Set(); - const linkDefinition = linkDefinitions.find(({ url }) => url === href); + const linkDefinition = linkDefinitions.find(({ url, markupUrl }) => url === href || (href && markupUrl === href)); const protocol = onErrorResumeNext(() => new URL(href).protocol); if (linkDefinition) { - ariaLabelSegments.push( - linkDefinition.title || onErrorResumeNext(() => new URL(linkDefinition.url).host) || linkDefinition.url - ); + ariaLabelSegments.push(linkDefinition.title || linkDefinition?.parsedUrl?.host || linkDefinition.url); // linkDefinition.identifier is uppercase, while linkDefinition.label is as-is. linkDefinition.label === textContent && classes.add('webchat__render-markdown__pure-identifier');