From a845eae23779a678703d5a8d9d324e4055179fa9 Mon Sep 17 00:00:00 2001 From: Abbas-Askari Date: Tue, 11 Feb 2025 18:03:23 +0500 Subject: [PATCH 1/3] feat: Add inline katex support --- packages/markups/package.json | 2 + .../markups/src/elements/InlineElements.js | 10 +++++ packages/markups/src/katex/KatexBlock.js | 33 +++++++++++++++ packages/markups/src/katex/KatexElement.js | 26 ++++++++++++ .../markups/src/katex/KatexErrorBoundary.js | 41 +++++++++++++++++++ .../markups/src/katex/PreviewKatexBlock.js | 10 +++++ .../markups/src/katex/PreviewKatexElement.js | 11 +++++ yarn.lock | 24 +++++++++++ 8 files changed, 157 insertions(+) create mode 100644 packages/markups/src/katex/KatexBlock.js create mode 100644 packages/markups/src/katex/KatexElement.js create mode 100644 packages/markups/src/katex/KatexErrorBoundary.js create mode 100644 packages/markups/src/katex/PreviewKatexBlock.js create mode 100644 packages/markups/src/katex/PreviewKatexElement.js diff --git a/packages/markups/package.json b/packages/markups/package.json index ab60f023f7..848a6fac9e 100644 --- a/packages/markups/package.json +++ b/packages/markups/package.json @@ -76,7 +76,9 @@ "@emotion/react": "11.7.1", "@rollup/plugin-json": "^6.0.0", "emoji-toolkit": "^7.0.1", + "katex": "^0.16.21", "prop-types": "^15.8.1", + "react-error-boundary": "^5.0.0", "react-syntax-highlighter": "^15.6.1" } } diff --git a/packages/markups/src/elements/InlineElements.js b/packages/markups/src/elements/InlineElements.js index 0ab5a7fb1e..3a2c2302aa 100644 --- a/packages/markups/src/elements/InlineElements.js +++ b/packages/markups/src/elements/InlineElements.js @@ -10,6 +10,8 @@ import ChannelMention from '../mentions/ChannelMention'; import ColorElement from './ColorElement'; import LinkSpan from './LinkSpan'; import UserMention from '../mentions/UserMention'; +import KatexErrorBoundary from '../katex/KatexErrorBoundary'; +import KatexElement from '../katex/KatexElement'; const InlineElements = ({ contents }) => contents.map((content, index) => { @@ -53,6 +55,14 @@ const InlineElements = ({ contents }) => } /> ); + + case 'INLINE_KATEX': + return ( + + + + ); + default: return null; } diff --git a/packages/markups/src/katex/KatexBlock.js b/packages/markups/src/katex/KatexBlock.js new file mode 100644 index 0000000000..e8860922e3 --- /dev/null +++ b/packages/markups/src/katex/KatexBlock.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import katex from 'katex'; +import React, { useMemo } from 'react'; + +import 'katex/dist/katex.css'; + +const KatexBlock = ({ code }) => { + const html = useMemo( + () => + katex.renderToString(code, { + displayMode: true, + macros: { + '\\href': '\\@secondoftwo', + }, + maxSize: 100, + }), + [code] + ); + + return ( +
+ ); +}; + +export default KatexBlock; +KatexBlock.prototype = { + code: PropTypes.string.isRequired, +}; diff --git a/packages/markups/src/katex/KatexElement.js b/packages/markups/src/katex/KatexElement.js new file mode 100644 index 0000000000..3870540447 --- /dev/null +++ b/packages/markups/src/katex/KatexElement.js @@ -0,0 +1,26 @@ +import katex from 'katex'; +import React, { useMemo } from 'react'; +import PropTypes from 'prop-types'; + +import 'katex/dist/katex.css'; + +const KatexElement = ({ code }) => { + const html = useMemo( + () => + katex.renderToString(code, { + displayMode: false, + macros: { + '\\href': '\\@secondoftwo', + }, + maxSize: 100, + }), + [code] + ); + + return ; +}; + +export default KatexElement; +KatexElement.prototype = { + code: PropTypes.string.isRequired, +}; diff --git a/packages/markups/src/katex/KatexErrorBoundary.js b/packages/markups/src/katex/KatexErrorBoundary.js new file mode 100644 index 0000000000..7a1f295771 --- /dev/null +++ b/packages/markups/src/katex/KatexErrorBoundary.js @@ -0,0 +1,41 @@ +// import colors from '@rocket.chat/fuselage-tokens/colors.json'; +import React, { useState } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; +import PropTypes from 'prop-types'; +import { Box } from '@embeddedchat/ui-elements'; +import { css } from '@emotion/react'; + +// const Fallback = styled('span')` +// text-decoration: underline; +// text-decoration-color: ${colors.r400}; +// `; + +const KatexErrorBoundary = ({ children, code }) => { + const [error, setError] = useState(null); + return ( + + {code} + + } + > + {children} + + ); +}; + +export default KatexErrorBoundary; +KatexErrorBoundary.propTypes = { + code: PropTypes.string.isRequired, + children: PropTypes.node.isRequired, +}; diff --git a/packages/markups/src/katex/PreviewKatexBlock.js b/packages/markups/src/katex/PreviewKatexBlock.js new file mode 100644 index 0000000000..855b5710b8 --- /dev/null +++ b/packages/markups/src/katex/PreviewKatexBlock.js @@ -0,0 +1,10 @@ +import React from 'react'; +import 'katex/dist/katex.css'; +import PropTypes from 'prop-types'; + +const PreviewKatexBlock = ({ code }) => <>{code}; + +export default PreviewKatexBlock; +PreviewKatexBlock.propTypes = { + code: PropTypes.string.isRequired, +}; diff --git a/packages/markups/src/katex/PreviewKatexElement.js b/packages/markups/src/katex/PreviewKatexElement.js new file mode 100644 index 0000000000..9fc1d7e019 --- /dev/null +++ b/packages/markups/src/katex/PreviewKatexElement.js @@ -0,0 +1,11 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import 'katex/dist/katex.css'; + +const PreviewKatexElement = ({ code }) => <>{code}; + +export default PreviewKatexElement; +PreviewKatexElement.propTypes = { + code: PropTypes.string.isRequired, +}; diff --git a/yarn.lock b/yarn.lock index d3dec11bea..4f3a6ab149 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2360,12 +2360,14 @@ __metadata: eslint-plugin-react-hooks: ^4.6.0 identity-obj-proxy: ^3.0.0 jest: ^27.5.1 + katex: ^0.16.21 lint-staged: ^12.4.2 npm-run-all: ^4.1.5 prettier: ^2.8.1 prop-types: ^15.8.1 react: ^17.0.2 react-dom: ^17.0.2 + react-error-boundary: ^5.0.0 react-syntax-highlighter: ^15.6.1 rimraf: ^5.0.1 rollup: ^2.70.1 @@ -21418,6 +21420,17 @@ __metadata: languageName: node linkType: hard +"katex@npm:^0.16.21": + version: 0.16.21 + resolution: "katex@npm:0.16.21" + dependencies: + commander: ^8.3.0 + bin: + katex: cli.js + checksum: 14180322a4e8fe9e4227a08b7d86fde9ee445859ff534e6a540b85eb5022b39ea2be70082776cce8c59b891c247fce3d1c1a090ea7821e005fd8b7bfee714936 + languageName: node + linkType: hard + "keyv@npm:^4.5.3": version: 4.5.4 resolution: "keyv@npm:4.5.4" @@ -26869,6 +26882,17 @@ __metadata: languageName: node linkType: hard +"react-error-boundary@npm:^5.0.0": + version: 5.0.0 + resolution: "react-error-boundary@npm:5.0.0" + dependencies: + "@babel/runtime": ^7.12.5 + peerDependencies: + react: ">=16.13.1" + checksum: 4fa78890bb254fe1f0ee1eed893ac161a27482c4567f7667ef83a8339432eb99e323ee69757f01f4864e0037b01a9b6822735ea122f02e749d0bf7a781d9ea53 + languageName: node + linkType: hard + "react-error-overlay@npm:6.0.9": version: 6.0.9 resolution: "react-error-overlay@npm:6.0.9" From a82cf7227f61cbb87a8eab137b790ed9c707d173 Mon Sep 17 00:00:00 2001 From: Abbas-Askari Date: Wed, 12 Feb 2025 22:09:14 +0500 Subject: [PATCH 2/3] add support for block KaTeX Messages --- packages/markups/src/Markup.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/markups/src/Markup.js b/packages/markups/src/Markup.js index 5f4d2317aa..bc1aafd791 100644 --- a/packages/markups/src/Markup.js +++ b/packages/markups/src/Markup.js @@ -8,6 +8,8 @@ import ParagraphBlock from './blocks/ParagraphBlock'; import UnOrderedListBlock from './blocks/UnOrderedListBlock'; import QuoteBlock from './blocks/QuoteBlock'; import TaskListBlock from './blocks/TaskListBlock'; +import KatexErrorBoundary from './katex/KatexErrorBoundary'; +import KatexBlock from './katex/KatexBlock'; const Markup = ({ tokens }) => tokens.map((token, index) => { @@ -45,6 +47,13 @@ const Markup = ({ tokens }) => case 'LINE_BREAK': return
; + case 'KATEX': + return ( + + + + ); + default: return null; } From b574d6d42e0f09cc7af4db871a8ffe45574e8f60 Mon Sep 17 00:00:00 2001 From: Abbas-Askari Date: Sat, 15 Feb 2025 17:48:51 +0500 Subject: [PATCH 3/3] Add katex error tooltip and fix tooltip overflows --- .../markups/src/katex/KatexErrorBoundary.js | 32 +++++++++---------- .../AttachmentHandler/AudioAttachment.js | 2 +- .../AttachmentHandler/ImageAttachment.js | 2 +- .../AttachmentHandler/VideoAttachment.js | 2 +- .../src/components/Tooltip/Tooltip.styles.js | 5 +-- 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/packages/markups/src/katex/KatexErrorBoundary.js b/packages/markups/src/katex/KatexErrorBoundary.js index 7a1f295771..5b0bea6f64 100644 --- a/packages/markups/src/katex/KatexErrorBoundary.js +++ b/packages/markups/src/katex/KatexErrorBoundary.js @@ -1,32 +1,30 @@ -// import colors from '@rocket.chat/fuselage-tokens/colors.json'; import React, { useState } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import PropTypes from 'prop-types'; -import { Box } from '@embeddedchat/ui-elements'; +import { Box, Tooltip, useTheme } from '@embeddedchat/ui-elements'; import { css } from '@emotion/react'; -// const Fallback = styled('span')` -// text-decoration: underline; -// text-decoration-color: ${colors.r400}; -// `; - const KatexErrorBoundary = ({ children, code }) => { const [error, setError] = useState(null); + const { theme } = useTheme(); return ( - {code} - + + {code} + + } > {children} diff --git a/packages/react/src/views/AttachmentHandler/AudioAttachment.js b/packages/react/src/views/AttachmentHandler/AudioAttachment.js index 867792b4f7..2a4a2cdc13 100644 --- a/packages/react/src/views/AttachmentHandler/AudioAttachment.js +++ b/packages/react/src/views/AttachmentHandler/AudioAttachment.js @@ -32,7 +32,7 @@ const AudioAttachment = ({ { z-index: ${theme.zIndex?.tooltip || 1400}; font-size: 12.5px; font-weight: 500; - white-space: nowrap; + max-width: 160px; + width: max-content; font-family: sans-serif; - top: ${position === 'top' ? 'calc(-100% - 20px)' : 'calc(100% + 10px)'}; + ${position === 'top' ? 'bottom: calc(100% + 10px)' : 'top: calc(100% + 10px)'}; `, tooltipArrow: css` content: '';