From 645a8dee66bf09f43f1984a372c7037c35bc40ea Mon Sep 17 00:00:00 2001 From: William Wong Date: Fri, 25 Oct 2024 05:51:56 +0000 Subject: [PATCH] Add `micromark-extension-math` --- __tests__/html2/markdown/math.html | 68 +++++++++++++++++++ package-lock.json | 51 ++++++++++++++ packages/bundle/package.json | 1 + .../bundle/src/markdown/renderMarkdown.ts | 44 ++++++++++-- .../src/Styles/StyleSet/RenderMarkdown.ts | 6 ++ 5 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 __tests__/html2/markdown/math.html diff --git a/__tests__/html2/markdown/math.html b/__tests__/html2/markdown/math.html new file mode 100644 index 0000000000..b73e95e8cc --- /dev/null +++ b/__tests__/html2/markdown/math.html @@ -0,0 +1,68 @@ + + + + + + + + + + +
+ + + diff --git a/package-lock.json b/package-lock.json index ca51aa7e1a..a5dd9bac21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4772,6 +4772,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "license": "MIT" + }, "node_modules/@types/math-random": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/math-random/-/math-random-1.0.2.tgz", @@ -15058,6 +15064,31 @@ "node": ">=18" } }, + "node_modules/katex": { + "version": "0.16.11", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz", + "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/keyborg": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz", @@ -16296,6 +16327,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/micromark-factory-destination": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", @@ -23837,6 +23887,7 @@ "memoize-one": "6.0.0", "micromark": "^4.0.0", "micromark-extension-gfm": "^3.0.0", + "micromark-extension-math": "^3.1.0", "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 f26d6476f0..2322b9b220 100644 --- a/packages/bundle/package.json +++ b/packages/bundle/package.json @@ -134,6 +134,7 @@ "memoize-one": "6.0.0", "micromark": "^4.0.0", "micromark-extension-gfm": "^3.0.0", + "micromark-extension-math": "^3.1.0", "microsoft-cognitiveservices-speech-sdk": "1.17.0", "prop-types": "15.8.1", "punycode": "2.3.1", diff --git a/packages/bundle/src/markdown/renderMarkdown.ts b/packages/bundle/src/markdown/renderMarkdown.ts index ab160c48b0..ee687da01c 100644 --- a/packages/bundle/src/markdown/renderMarkdown.ts +++ b/packages/bundle/src/markdown/renderMarkdown.ts @@ -7,9 +7,10 @@ import { } from 'botframework-webchat-component/internal'; import { micromark } from 'micromark'; import { gfm, gfmHtml } from 'micromark-extension-gfm'; -import { pre as respectCRLFPre } from './private/respectCRLF'; +import { math, mathHtml } from 'micromark-extension-math'; import betterLinkDocumentMod, { BetterLinkDocumentModDecoration } from './private/betterLinkDocumentMod'; import iterateLinkDefinitions from './private/iterateLinkDefinitions'; +import { pre as respectCRLFPre } from './private/respectCRLF'; const SANITIZE_HTML_OPTIONS = Object.freeze({ allowedAttributes: { @@ -56,7 +57,38 @@ const SANITIZE_HTML_OPTIONS = Object.freeze({ 'th', 'thead', 'tr', - 'ul' + 'ul', + + // Followings are for MathML elements, from https://developer.mozilla.org/en-US/docs/Web/MathML. + 'annotation-xml', + 'annotation', + 'math', + 'merror', + 'mfrac', + 'mi', + 'mmultiscripts', + 'mn', + 'mo', + 'mover', + 'mpadded', + 'mphantom', + 'mprescripts', + 'mroot', + 'mrow', + 'ms', + 'mspace', + 'msqrt', + 'mstyle', + 'msub', + 'msubsup', + 'msup', + 'mtable', + 'mtd', + 'mtext', + 'mtr', + 'munder', + 'munderover', + 'semantics' ], // Bug of https://github.com/apostrophecms/sanitize-html/issues/633. // They should not remove `alt=""` even though it is empty. @@ -145,8 +177,12 @@ export default function render( // We need to handle links like cite:1 or other URL handlers. // And we will remove dangerous protocol during sanitization. allowDangerousProtocol: true, - extensions: [gfm()], - htmlExtensions: [gfmHtml()] + extensions: [ + gfm(), + // Disabling single dollar inline math block to prevent easy collision. + math({ singleDollarTextMath: false }) + ], + htmlExtensions: [gfmHtml(), mathHtml({ output: 'mathml' })] }); // TODO: [P1] In some future, we should apply "better link" and "sanitization" outside of the Markdown engine. diff --git a/packages/component/src/Styles/StyleSet/RenderMarkdown.ts b/packages/component/src/Styles/StyleSet/RenderMarkdown.ts index cf7d68b723..9b8f2b9cf0 100644 --- a/packages/component/src/Styles/StyleSet/RenderMarkdown.ts +++ b/packages/component/src/Styles/StyleSet/RenderMarkdown.ts @@ -65,6 +65,12 @@ export default function createMarkdownStyle() { '& .webchat__render-markdown__pure-identifier::before': { content: "'['" + }, + + '& math': { + alignItems: 'center', + display: 'flex', + flexDirection: 'column' } } };