diff --git a/openmetadata-ui/src/main/resources/ui/package.json b/openmetadata-ui/src/main/resources/ui/package.json
index e8d3a0cccd5e..e0d5db0f6c6f 100644
--- a/openmetadata-ui/src/main/resources/ui/package.json
+++ b/openmetadata-ui/src/main/resources/ui/package.json
@@ -178,7 +178,6 @@
"react-hook-form": "7.78.0",
"react-i18next": "^15.5.3",
"react-intersection-observer": "^9.16.0",
- "react-latex-next": "^3.0.0",
"react-markdown": "^10.1.0",
"react-oidc": "^1.0.3",
"react-papaparse": "^4.1.0",
diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/BlockEditorMathEquations.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/BlockEditorMathEquations.spec.ts
index c1b3d1bf3af6..410928b78d4a 100644
--- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/BlockEditorMathEquations.spec.ts
+++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/BlockEditorMathEquations.spec.ts
@@ -84,7 +84,7 @@ test.describe('BlockEditor math equations', { tag: ['@Discovery'] }, () => {
await expect(
page
.getByTestId('asset-description-container')
- .locator('.block-math-equation')
+ .locator('.block-math-equation .katex')
).toBeVisible();
});
});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/Extensions/MathEquation/MathEquationComponent.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/Extensions/MathEquation/MathEquationComponent.test.tsx
index 9d8822a1499e..b63f2af618c7 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/Extensions/MathEquation/MathEquationComponent.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/Extensions/MathEquation/MathEquationComponent.test.tsx
@@ -14,17 +14,13 @@ import { fireEvent, render, screen } from '@testing-library/react';
import { NodeViewProps } from '@tiptap/react';
import { MathEquationComponent } from './MathEquationComponent';
-jest.mock('react-latex-next', () =>
- jest.fn().mockImplementation(({ children }) => {children})
-);
-
const updateAttributes = jest.fn();
-const renderComponent = (isEditing: boolean) =>
+const renderComponent = (isEditing: boolean, equation = 'x^2') =>
render(
{
expect(screen.getByRole('textbox')).toHaveValue('x^2');
});
+
+ it('renders delimited math with KaTeX', () => {
+ const { container } = renderComponent(false, '$x^2$');
+
+ expect(container.querySelector('.katex')).toBeInTheDocument();
+ });
+
+ it('renders text outside the delimiters as text, not HTML', () => {
+ const { container } = renderComponent(
+ false,
+ '$x^2$
'
+ );
+
+ expect(container.querySelector('img')).not.toBeInTheDocument();
+ expect(container).toHaveTextContent('
');
+ });
+
+ it('keeps malformed math as its source text', () => {
+ const { container } = renderComponent(false, '$\\frac{1}$');
+
+ expect(container.querySelector('.katex')).not.toBeInTheDocument();
+ expect(container).toHaveTextContent('$\\frac{1}$');
+ });
});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/Extensions/MathEquation/MathEquationComponent.tsx b/openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/Extensions/MathEquation/MathEquationComponent.tsx
index e40d26f60b27..34e60eb7db4b 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/Extensions/MathEquation/MathEquationComponent.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/Extensions/MathEquation/MathEquationComponent.tsx
@@ -19,13 +19,42 @@ import {
import { Check, XClose } from '@openmetadata/ui-core-components/icons';
import { NodeViewProps, NodeViewWrapper } from '@tiptap/react';
import classNames from 'classnames';
+import renderMathInElement from 'katex/contrib/auto-render';
import 'katex/dist/katex.min.css';
-import { FC, useRef, useState } from 'react';
+import { noop } from 'lodash';
+import { FC, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import Latex from 'react-latex-next';
import { ReactComponent as EditIcon } from '../../../../assets/svg/edit-new.svg';
import './math-equation.less';
+// The delimiters react-latex-next used, so stored `$…$` / `$$…$$` equations
+// render as before.
+const LATEX_DELIMITERS = [
+ { left: '$$', right: '$$', display: true },
+ { left: String.raw`\(`, right: String.raw`\)`, display: false },
+ { left: '$', right: '$', display: false },
+ { left: String.raw`\[`, right: String.raw`\]`, display: true },
+];
+
+// auto-render keeps everything outside the delimiters as text nodes, so the
+// stored attribute is never parsed as HTML.
+const RenderedEquation: FC<{ equation: string }> = ({ equation }) => {
+ const ref = useRef(null);
+
+ useEffect(() => {
+ if (ref.current) {
+ ref.current.textContent = equation;
+ renderMathInElement(ref.current, {
+ delimiters: LATEX_DELIMITERS,
+ // Malformed math stays as its source text, without logging per render.
+ errorCallback: noop,
+ });
+ }
+ }, [equation]);
+
+ return ;
+};
+
export const MathEquationComponent: FC = ({
node,
updateAttributes,
@@ -89,7 +118,7 @@ export const MathEquationComponent: FC = ({
) : (
- {equation}
+
)}
{/* Show edit button only when the editor is editable */}
{!isEditing && editor.isEditable && (
diff --git a/openmetadata-ui/src/main/resources/ui/yarn.lock b/openmetadata-ui/src/main/resources/ui/yarn.lock
index 35069dd302ed..9c4d3951dccf 100644
--- a/openmetadata-ui/src/main/resources/ui/yarn.lock
+++ b/openmetadata-ui/src/main/resources/ui/yarn.lock
@@ -6078,11 +6078,6 @@ commander@^2.19.0, commander@^2.20.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
-commander@^8.3.0:
- version "8.3.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
- integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
-
commander@^9.0.0:
version "9.5.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
@@ -9387,13 +9382,6 @@ jwt-decode@^3.1.2:
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==
-katex@^0.16.0:
- version "0.16.45"
- resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.45.tgz#ba60d39c54746b6b8d39ce0e7f6eace07143149c"
- integrity sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA==
- dependencies:
- commander "^8.3.0"
-
katex@^0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/katex/-/katex-0.19.0.tgz#b69c8cbcfc8c331be3f4f6e606b02b7146501ec7"
@@ -11881,13 +11869,6 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
-react-latex-next@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/react-latex-next/-/react-latex-next-3.0.0.tgz#3e347a13b1e701439b5fa52f75201bc86166854e"
- integrity sha512-x70f1b1G7TronVigsRgKHKYYVUNfZk/3bciFyYX1lYLQH2y3/TXku3+5Vap8MDbJhtopePSYBsYWS6jhzIdz+g==
- dependencies:
- katex "^0.16.0"
-
react-markdown@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-10.1.0.tgz#e22bc20faddbc07605c15284255653c0f3bad5ca"