From eb9f3f9c064e6b6260bd667222f7370aae263715 Mon Sep 17 00:00:00 2001 From: Jeremy Wiebe Date: Thu, 1 Aug 2024 15:33:05 -0700 Subject: [PATCH] Remove 'katex' from @khanacademy/perseus (#1428) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary: KaTeX was retired from use in Perseus in 2023. Today, I noticed that we still reference the `katex` package in the perseus `package.json`, but we never import it anywhere in the code. So I'm removing that dependency. I've also updated some code comments and storybook references to not mention KaTeX anymore. I've left some references to CSS classes and the KaTeX_Main font ref. I'm unsure if they might be important somewhere (especially if host applications may still set it outside of Perseus). So this doesn't fully remove all references to katex, but it moves us another step closer. Issue: "none" ## Test plan: `yarn tsc` `yarn lint` I ran storybook and opened the `ZoomableTex` stories and played with them. Note(jeremy): I've restored the code that swaps `\begin{align}` to `\begin{aligned}` and noted LEMS-1608 based on comments from Ben (thanks!). ~I also went to the `EditorPage` story and pasted in the following Tex into the **Question** field (which uses the macro that we used to have to replace for KaTeX, but MathJax supports properly: switching `\begin{align}` to `\begin{aligned}`).~ Author: jeremywiebe Reviewers: jeremywiebe, benchristel, Myranae, nicolecomputer Required Reviewers: Approved By: benchristel Checks: ✅ codecov/project, ✅ codecov/patch, ✅ Upload Coverage (ubuntu-latest, 20.x), ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Jest Coverage (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald Pull Request URL: https://github.com/Khan/perseus/pull/1428 --- .changeset/mighty-news-repair.md | 5 +++ packages/perseus/package.json | 1 - .../perseus/src/__tests__/renderer.test.tsx | 31 +++++++++++++++++-- .../components/__stories__/graph.stories.tsx | 1 - .../__stories__/zoomable-tex.stories.tsx | 4 +-- packages/perseus/src/index.ts | 2 +- .../src/interactive2/movable-point.tsx | 6 ++-- packages/perseus/src/perseus-types.ts | 4 +-- packages/perseus/src/renderer.tsx | 5 ++- packages/perseus/src/types.ts | 1 - ...{katex-preprocess.ts => tex-preprocess.ts} | 6 ++-- packages/perseus/src/util/tex.ts | 4 +-- .../widgets/label-image/answer-choices.tsx | 2 +- 13 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 .changeset/mighty-news-repair.md rename packages/perseus/src/util/{katex-preprocess.ts => tex-preprocess.ts} (67%) 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;