diff --git a/.changeset/mighty-news-repair.md b/.changeset/mighty-news-repair.md new file mode 100644 index 0000000000..a47f377b06 --- /dev/null +++ b/.changeset/mighty-news-repair.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus": minor +--- + +Drop katex dependency - no longer used diff --git a/packages/perseus/package.json b/packages/perseus/package.json index 2dbd184bae..d71e3435b3 100644 --- a/packages/perseus/package.json +++ b/packages/perseus/package.json @@ -75,7 +75,6 @@ "create-react-class": "15.6.3", "intersection-observer": "^0.12.0", "jquery": "^2.1.1", - "katex": "0.11.1", "lodash.debounce": "^4.0.8", "perseus-build-settings": "^0.4.1", "prop-types": "15.6.1", diff --git a/packages/perseus/src/__tests__/renderer.test.tsx b/packages/perseus/src/__tests__/renderer.test.tsx index ff96164499..6f4c980d7c 100644 --- a/packages/perseus/src/__tests__/renderer.test.tsx +++ b/packages/perseus/src/__tests__/renderer.test.tsx @@ -713,6 +713,29 @@ describe("renderer", () => { it("should replace deprecated alignment tags in inline math", async () => { // Arrange const question = { + content: + "Hello $\\begin{align}\n2\\text{HCl}(\\text{aq})+\\text{Ca}(\\text{OH})_2(\\text{aq})\\rightarrow\\text{Ca}(\\text{s})+2\\text H_2\\text O(\\text l)+\\text{Cl}_2(\\text g)\n\\end{align}$", + images: {}, + widgets: {}, + } as const; + + // Act + renderQuestion(question); + + // Assert + await waitFor(() => { + expect( + screen.getByText(/\\begin\{aligned\}.*\\end\{aligned\}/), + ).toBeInTheDocument(); + }); + }); + + it("should replace deprecated alignment tags in block math", async () => { + // Arrange + const question = { + // Math that exists by itself in a paragraph is considered + // block math, even if it isn't surrounded by the block math + // delimeters (`$$$...$$$`). content: "$\\begin{align}\n2\\text{HCl}(\\text{aq})+\\text{Ca}(\\text{OH})_2(\\text{aq})\\rightarrow\\text{Ca}(\\text{s})+2\\text H_2\\text O(\\text l)+\\text{Cl}_2(\\text g)\n\\end{align}$", images: {}, @@ -723,9 +746,11 @@ describe("renderer", () => { renderQuestion(question); // Assert - expect( - screen.getByText(/\\begin\{aligned\}.*\\end\{aligned\}/), - ).toBeInTheDocument(); + await waitFor(() => { + expect( + screen.getByText(/\\begin\{aligned\}.*\\end\{aligned\}/), + ).toBeInTheDocument(); + }); }); }); diff --git a/packages/perseus/src/components/__stories__/graph.stories.tsx b/packages/perseus/src/components/__stories__/graph.stories.tsx index c18c8f453b..92ed37d60f 100644 --- a/packages/perseus/src/components/__stories__/graph.stories.tsx +++ b/packages/perseus/src/components/__stories__/graph.stories.tsx @@ -1,7 +1,6 @@ import * as React from "react"; import Graph from "../graph"; -// TODO(scottgrant): Katex is unavailable here. Fix! type StoryArgs = Record; diff --git a/packages/perseus/src/components/__stories__/zoomable-tex.stories.tsx b/packages/perseus/src/components/__stories__/zoomable-tex.stories.tsx index fa5e4be01b..1992575501 100644 --- a/packages/perseus/src/components/__stories__/zoomable-tex.stories.tsx +++ b/packages/perseus/src/components/__stories__/zoomable-tex.stories.tsx @@ -23,7 +23,7 @@ const ForceZoomWrapper = ({children}: Props): React.ReactElement => ( ); -export const KaTeX = (args: StoryArgs): React.ReactElement => { +export const Tex = (args: StoryArgs): React.ReactElement => { return ( @@ -31,7 +31,7 @@ export const KaTeX = (args: StoryArgs): React.ReactElement => { ); }; -export const ComplexKaTeX = (args: StoryArgs): React.ReactElement => { +export const ComplexTex = (args: StoryArgs): React.ReactElement => { return ( {" "} diff --git a/packages/perseus/src/index.ts b/packages/perseus/src/index.ts index 71f94e6af2..775d13241b 100644 --- a/packages/perseus/src/index.ts +++ b/packages/perseus/src/index.ts @@ -84,7 +84,7 @@ export { */ export {default as Util} from "./util"; export {default as KhanColors} from "./util/colors"; -export {default as preprocessTex} from "./util/katex-preprocess"; +export {default as preprocessTex} from "./util/tex-preprocess"; export {registerAllWidgetsForTesting} from "./util/register-all-widgets-for-testing"; export * as SizingUtils from "./util/sizing-utils"; export { diff --git a/packages/perseus/src/interactive2/movable-point.tsx b/packages/perseus/src/interactive2/movable-point.tsx index 0748595628..689ae26444 100644 --- a/packages/perseus/src/interactive2/movable-point.tsx +++ b/packages/perseus/src/interactive2/movable-point.tsx @@ -521,9 +521,9 @@ export class MovablePoint { * Displays a tooltip above the point, replacing any previous contents. If * there is no tooltip initialized, adds the tooltip. * - * If the type of contents is string, the contents will be rendered with - * KaTeX. Otherwise, the content will be assumed to be a DOM node and will - * be appended inside the tooltip. + * If the type of contents is string, the contents will be rendered as TeX + * Otherwise, the content will be assumed to be a DOM node and will be + * appended inside the tooltip. */ _showTooltip(contents) { if (!this._tooltip) { diff --git a/packages/perseus/src/perseus-types.ts b/packages/perseus/src/perseus-types.ts index daa04041ec..c398326d1a 100644 --- a/packages/perseus/src/perseus-types.ts +++ b/packages/perseus/src/perseus-types.ts @@ -436,7 +436,7 @@ export const PerseusExpressionAnswerFormConsidered = [ ] as const; export type PerseusExpressionAnswerForm = { - // The Katex form of the expression. e.g. "x\\cdot3=y" + // The TeX form of the expression. e.g. "x\\cdot3=y" value: string; // The Answer expression must have the same form form: boolean; @@ -889,7 +889,7 @@ export type PerseusGraphTypeRay = { } & PerseusGraphTypeCommon; export type PerseusLabelImageWidgetOptions = { - // Translatable Text; Katex representation of choices + // Translatable Text; Tex representation of choices choices: ReadonlyArray; // The URL of the image imageUrl: string; diff --git a/packages/perseus/src/renderer.tsx b/packages/perseus/src/renderer.tsx index 8565d8ac89..f84f5bbf04 100644 --- a/packages/perseus/src/renderer.tsx +++ b/packages/perseus/src/renderer.tsx @@ -26,7 +26,7 @@ import PerseusMarkdown from "./perseus-markdown"; import QuestionParagraph from "./question-paragraph"; import TranslationLinter from "./translation-linter"; import Util from "./util"; -import preprocessTex from "./util/katex-preprocess"; +import preprocessTex from "./util/tex-preprocess"; import WidgetContainer from "./widget-container"; import * as Widgets from "./widgets"; @@ -1303,6 +1303,9 @@ class Renderer extends React.Component { // support (yet) with \begin{aligned}...\end{aligned} which renders // the same is supported by KaTeX. It does the same for align*. // TODO(kevinb) update content to use aligned instead of align. + // TODO(LEMS-1608) Remove this replacement as MathJax supports the + // "align" macro correctly (and, in fact, it is not synonymous with + // "aligned"). const tex = node.content.replace(/\{align[*]?\}/g, "{aligned}"); // We render math here instead of in perseus-markdown.jsx diff --git a/packages/perseus/src/types.ts b/packages/perseus/src/types.ts index bd10b01dfc..99c491aa75 100644 --- a/packages/perseus/src/types.ts +++ b/packages/perseus/src/types.ts @@ -318,7 +318,6 @@ export type APIOptions = Readonly<{ type TeXProps = { children: string; - katexOptions?: any; onClick?: () => unknown; onRender?: (root?: any) => unknown; style?: any; diff --git a/packages/perseus/src/util/katex-preprocess.ts b/packages/perseus/src/util/tex-preprocess.ts similarity index 67% rename from packages/perseus/src/util/katex-preprocess.ts rename to packages/perseus/src/util/tex-preprocess.ts index 8dd702928b..5450afbcec 100644 --- a/packages/perseus/src/util/katex-preprocess.ts +++ b/packages/perseus/src/util/tex-preprocess.ts @@ -1,14 +1,16 @@ /** - * Preprocess TeX code to convert things that KaTeX doesn't know how to handle + * Preprocess TeX code to convert things that MathJax doesn't know how to handle * to things is does. */ - export default (texCode: string): string => texCode // Replace uses of \begin{align}...\end{align} which KaTeX doesn't // support (yet) with \begin{aligned}...\end{aligned} which renders // the same is supported by KaTeX. It does the same for align*. // TODO(kevinb) update content to use aligned instead of align. + // TODO(LEMS-1608) Remove this replacement as MathJax supports the + // "align" macro correctly (and, in fact, it is not synonymous with + // "aligned"). .replace(/\{align[*]?\}/g, "{aligned}") // Replace non-breaking spaces with regular spaces. .replace(/[\u00a0]/g, " "); diff --git a/packages/perseus/src/util/tex.ts b/packages/perseus/src/util/tex.ts index 3d69cdb0d7..1a2c23bd65 100644 --- a/packages/perseus/src/util/tex.ts +++ b/packages/perseus/src/util/tex.ts @@ -16,8 +16,8 @@ function findChildOrAdd(elem: any, className: string) { } export default { - // Process a node and add math inside of it. This attempts to use KaTeX to - // format the math, and if that fails it falls back to MathJax. + // Process a node and add math inside of it. This uses MathJax to + // format the math. // // elem: The element which the math should be added to. // diff --git a/packages/perseus/src/widgets/label-image/answer-choices.tsx b/packages/perseus/src/widgets/label-image/answer-choices.tsx index 6b70d0e6ab..916861b90a 100644 --- a/packages/perseus/src/widgets/label-image/answer-choices.tsx +++ b/packages/perseus/src/widgets/label-image/answer-choices.tsx @@ -14,7 +14,7 @@ import {usePerseusI18n} from "../../components/i18n-context"; import Renderer from "../../renderer"; export type AnswerType = { - // The answer string, can be plain text or a KaTeX expression. + // The answer string, can be plain text or a TeX expression. content: string; // Whether the answer is selected. checked: boolean;