diff --git a/deploy.py b/deploy.py index be3bef28bc..4183d6e9ab 100644 --- a/deploy.py +++ b/deploy.py @@ -98,7 +98,7 @@ def ask_to_run_command(command, stdout_data.append(decoded_chunk) # Store for later return_code = proc.wait() - output = ''.join(stdout_data) + output = ''.join(stdout_data).strip() if return_code == 0: return output elif expected_nonzero_exit_codes and return_code in expected_nonzero_exit_codes: diff --git a/package.json b/package.json index c0ed8ab722..92e6e26274 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "html-to-text": "^9.0.5", "identity-obj-proxy": "3.0.0", "immer": "^9.0.21", - "inequality": "^1.2.2", + "inequality": "^1.2.3", "inequality-grammar": "1.3.5", "isaac-graph-sketcher": "0.13.7", "js-cookie": "^3.0.5", diff --git a/src/IsaacAppTypes.tsx b/src/IsaacAppTypes.tsx index 716fe7317e..34438024a2 100644 --- a/src/IsaacAppTypes.tsx +++ b/src/IsaacAppTypes.tsx @@ -243,6 +243,7 @@ export interface BooleanNotation { export interface DisplaySettings { HIDE_QUESTION_ATTEMPTS?: boolean; + PREFER_MATHML?: boolean; } export interface UserConsent { diff --git a/src/app/components/elements/markup/latexRendering.ts b/src/app/components/elements/markup/latexRendering.ts index 2a005a8227..6dccff0304 100644 --- a/src/app/components/elements/markup/latexRendering.ts +++ b/src/app/components/elements/markup/latexRendering.ts @@ -1,11 +1,10 @@ import {useContext} from "react"; -import {selectors, useAppSelector, useGetSegueEnvironmentQuery} from "../../../state"; -import {FigureNumberingContext, FigureNumbersById, PotentialUser} from "../../../../IsaacAppTypes"; +import {useGetSegueEnvironmentQuery} from "../../../state"; +import {FigureNumberingContext, FigureNumbersById} from "../../../../IsaacAppTypes"; import he from "he"; -import {dropZoneRegex, renderA11yString, BOOLEAN_NOTATION, isAda, useUserPreferences} from "../../../services"; +import {BOOLEAN_NOTATION, dropZoneRegex, isAda, renderA11yString, useUserPreferences} from "../../../services"; import katex, {KatexOptions} from "katex"; import 'katex/dist/contrib/mhchem.mjs'; -import {Immutable} from "immer"; type MathJaxMacro = string|[string, number]; @@ -220,7 +219,13 @@ const ENDREF = "==ENDREF=="; const REF_REGEXP = new RegExp(REF + "(.*?)" + ENDREF, "g"); const SR_REF_REGEXP = new RegExp("start text, " + REF_REGEXP.source + ", end text,", "g"); -export function katexify(html: string, user: Immutable | null, booleanNotation : BOOLEAN_NOTATION | undefined, showScreenReaderHoverText: boolean, figureNumbers: FigureNumbersById) { +export function katexify( + html: string, + booleanNotation : BOOLEAN_NOTATION | undefined, + showScreenReaderHoverText: boolean, + preferMathML: boolean, + figureNumbers: FigureNumbersById +) { start.lastIndex = 0; let match: RegExpExecArray | null; let output = ""; @@ -287,8 +292,8 @@ export function katexify(html: string, user: Immutable | null, bo // Until https://github.com/KaTeX/KaTeX/issues/3668 is resolved, apply suggested fix ourselves, awfully: katexRenderResult = katexRenderResult.replaceAll("color:transparent;", "color:transparent;visibility:hidden;"); - // If katex-a11y fails, generate MathML using KaTeX for accessibility - if (screenReaderText) { + // If katex-a11y fails, or MathML preferred, generate MathML using KaTeX for accessibility: + if (!preferMathML && screenReaderText) { katexRenderResult = katexRenderResult.replace('', ``); } else { @@ -333,10 +338,9 @@ export function katexify(html: string, user: Immutable | null, bo // A hook wrapper around katexify that gets its required parameters from the current redux state and existing figure numbering context export const useRenderKatex = () => { - const user = useAppSelector(selectors.user.orNull); const {data: segueEnvironment} = useGetSegueEnvironmentQuery(); - const {preferredBooleanNotation} = useUserPreferences(); + const {preferredBooleanNotation, preferMathML} = useUserPreferences(); const figureNumbers = useContext(FigureNumberingContext); - return (markup: string) => katexify(markup, user, preferredBooleanNotation && BOOLEAN_NOTATION[preferredBooleanNotation], segueEnvironment === "DEV", figureNumbers); + return (markup: string) => katexify(markup, preferredBooleanNotation && BOOLEAN_NOTATION[preferredBooleanNotation], segueEnvironment === "DEV", preferMathML ?? false, figureNumbers); }; diff --git a/src/app/components/elements/modals/inequality/InequalityModal.tsx b/src/app/components/elements/modals/inequality/InequalityModal.tsx index a491ec5565..27228832aa 100644 --- a/src/app/components/elements/modals/inequality/InequalityModal.tsx +++ b/src/app/components/elements/modals/inequality/InequalityModal.tsx @@ -68,8 +68,8 @@ const InequalityMenuTab = ({menu, latexTitle, subMenu, className, isSubMenu = fa if (!menuContext) return null; const {activeMenu: [activeMenu, activeSubMenu], openNewMenuTab} = menuContext; - const navigate = () => openNewMenuTab([menu, subMenu ?? null]); const active = activeMenu === menu && (isSubMenu ? activeSubMenu === subMenu : true); + const navigate = () => openNewMenuTab([menu, (!active || isSubMenu) && subMenu ? subMenu : null]); return
  • {isSubMenu ? : }{`$${latexTitle}$`} diff --git a/src/app/components/elements/panels/UserBetaFeatures.tsx b/src/app/components/elements/panels/UserBetaFeatures.tsx index 58e8ec0ce1..aee0424fed 100644 --- a/src/app/components/elements/panels/UserBetaFeatures.tsx +++ b/src/app/components/elements/panels/UserBetaFeatures.tsx @@ -18,7 +18,7 @@ export const RevisionModeInput = ({displaySettings, setDisplaySettings}: Revisio return { setDisplaySettings((oldDs) => ({...oldDs, HIDE_QUESTION_ATTEMPTS: e.target.checked})); - }} + }} color={siteSpecific("primary", "")} label={

    Hide previous question attempts

    } id={"hide-previous-q-attempts"} @@ -36,6 +36,17 @@ export const UserBetaFeatures = ({ displaySettings, setDisplaySettings, consentS

    {`This feature lets you answer questions ${siteSpecific("that you have answered before, without seeing your old answer.", "again, even if you've answered them before.")} It's useful if you are reviewing a topic before a test or exam.`}

    + <> + { + setDisplaySettings((oldDs) => ({...oldDs, PREFER_MATHML: e.target.checked})); + }} + color={siteSpecific("primary", "")} + label={

    Use MathML for accessible maths

    } + id={"prefer-mathml"} + />
    +

    {`With this setting you can toggle between using alternative text or MathML for mathematical equations.`}

    + {isAda && <> { diff --git a/src/app/services/userPreferences.ts b/src/app/services/userPreferences.ts index 1647035484..419006926c 100644 --- a/src/app/services/userPreferences.ts +++ b/src/app/services/userPreferences.ts @@ -4,12 +4,13 @@ import { AppState, useAppSelector } from '../state'; interface UseUserPreferencesReturnType { preferredProgrammingLanguage?: PROGRAMMING_LANGUAGE; preferredBooleanNotation?: BOOLEAN_NOTATION; + preferMathML?: boolean; } export function useUserPreferences(): UseUserPreferencesReturnType { const {examBoard} = useUserViewingContext(); - const {PROGRAMMING_LANGUAGE: programmingLanguage, BOOLEAN_NOTATION: booleanNotation} = + const {PROGRAMMING_LANGUAGE: programmingLanguage, BOOLEAN_NOTATION: booleanNotation, DISPLAY_SETTING: displaySettings} = useAppSelector((state: AppState) => state?.userPreferences) || {}; // Programming language preference - @@ -28,8 +29,12 @@ export function useUserPreferences(): UseUserPreferencesReturnType { preferredBooleanNotation = examBoardBooleanNotationMap[examBoard]; } + // Accessibility preferences: + const preferMathML = displaySettings?.PREFER_MATHML; + return { preferredProgrammingLanguage, - preferredBooleanNotation + preferredBooleanNotation, + preferMathML }; -} \ No newline at end of file +} diff --git a/src/app/state/slices/api/segueInfoApi.ts b/src/app/state/slices/api/segueInfoApi.ts index 56d4a73bba..a8e151bffb 100644 --- a/src/app/state/slices/api/segueInfoApi.ts +++ b/src/app/state/slices/api/segueInfoApi.ts @@ -7,7 +7,7 @@ const updatedIsaacApi = isaacApi.injectEndpoints({ getContentVersion: build.query({ query: () => ({ - url: "/info/content_versions/live_version", + url: "/admin/live_version", method: "GET", }), onQueryStarted: onQueryLifecycleEvents({ diff --git a/src/test/components/TrustedHtml.test.tsx b/src/test/components/TrustedHtml.test.tsx index ab859d2ba8..c8ffc0aab4 100644 --- a/src/test/components/TrustedHtml.test.tsx +++ b/src/test/components/TrustedHtml.test.tsx @@ -31,7 +31,7 @@ describe('TrustedHtml LaTeX locator', () => { it('can find basic delimiters', () => { delimiters.forEach(([open, displayMode, close]) => { const testcase = html[0] + wrapIn(open, math[0], close) + html[1]; - const result = katexify(testcase, null, undefined, false, {}); + const result = katexify(testcase, undefined, false, false, {}); expect(result).toEqual(html[0] + LATEX + html[1]); // @ts-ignore @@ -48,7 +48,7 @@ describe('TrustedHtml LaTeX locator', () => { it("unbalanced delimiters don't break everything but instead are just skipped", () => { delimiters.forEach(([open, , ]) => { const testcase = html[0] + wrapIn(open, math[0], "") + html[1]; - const result = katexify(testcase, null, undefined, false, {}); + const result = katexify(testcase, undefined, false, false, {}); expect(result).toEqual(html[0] + open + math[0] + html[1]); expect(katex.renderToString).not.toHaveBeenCalled(); @@ -59,7 +59,7 @@ describe('TrustedHtml LaTeX locator', () => { nestedDollars.forEach((dollarMath) => { delimiters.forEach(([open, displayMode, close]) => { const testcase = html[0] + wrapIn(open, dollarMath, close) + html[1]; - const result = katexify(testcase, null, undefined, false, {}); + const result = katexify(testcase, undefined, false, false, {}); expect(result).toEqual(html[0] + LATEX + html[1]); // @ts-ignore @@ -77,7 +77,7 @@ describe('TrustedHtml LaTeX locator', () => { it('can render environments', () => { const env = "\\begin{aligned}" + math[0] + "\\end{aligned}"; const testcase = html[0] + env + html[1]; - const result = katexify(testcase, null, undefined, false, {}); + const result = katexify(testcase, undefined, false, false, {}); expect(result).toEqual(html[0] + LATEX + html[1]); // @ts-ignore @@ -93,7 +93,7 @@ describe('TrustedHtml LaTeX locator', () => { it('missing refs show an inline error', () => { const ref = "\\ref{foo[234o89tdgfiuno34£\"$%^Y}"; const testcase = html[0] + ref + html[1]; - const result = katexify(testcase, null, undefined, false, {}); + const result = katexify(testcase, undefined, false, false, {}); expect(result).toEqual(html[0] + "unknown reference " + ref + html[1]); expect(katex.renderToString).not.toHaveBeenCalled(); @@ -102,7 +102,7 @@ describe('TrustedHtml LaTeX locator', () => { it('found refs show their figure number', () => { const ref = "\\ref{foo}"; const testcase = html[0] + ref + html[1]; - const result = katexify(testcase, null, undefined, false, {foo: 42}); + const result = katexify(testcase, undefined, false, false, {foo: 42}); const expectedFigureRef = "Figure" + " " + "42"; const expectedFigureRefWithFormatting = `${expectedFigureRef}`; @@ -114,7 +114,7 @@ describe('TrustedHtml LaTeX locator', () => { const escapedDollar = "\\$"; const unescapedDollar = "$"; const testcase = html[0] + escapedDollar + html[1]; - const result = katexify(testcase, null, undefined, false, {}); + const result = katexify(testcase, undefined, false, false, {}); expect(result).toEqual(html[0] + unescapedDollar + html[1]); expect(katex.renderToString).not.toHaveBeenCalled(); diff --git a/src/test/pages/__image_snapshots__/ada/My Account should have no visual regressions on Beta page #0.png b/src/test/pages/__image_snapshots__/ada/My Account should have no visual regressions on Beta page #0.png index 69006ffb8c..9f489b7b97 100644 Binary files a/src/test/pages/__image_snapshots__/ada/My Account should have no visual regressions on Beta page #0.png and b/src/test/pages/__image_snapshots__/ada/My Account should have no visual regressions on Beta page #0.png differ diff --git a/src/test/pages/__image_snapshots__/phy/My Account should have no visual regressions on Beta page #0.png b/src/test/pages/__image_snapshots__/phy/My Account should have no visual regressions on Beta page #0.png index 08ef3217b5..b43f67a545 100644 Binary files a/src/test/pages/__image_snapshots__/phy/My Account should have no visual regressions on Beta page #0.png and b/src/test/pages/__image_snapshots__/phy/My Account should have no visual regressions on Beta page #0.png differ diff --git a/yarn.lock b/yarn.lock index 5daa18d0c6..1d4e1c48ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6351,10 +6351,10 @@ inequality-grammar@1.3.5: moo "^0.5.2" nearley "^2.20.1" -inequality@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/inequality/-/inequality-1.2.2.tgz#8b71d2a322b9e8fdce8a63a0495272f9736ac90a" - integrity sha512-VUPfa0KbqjSeqWVL/ZjOzP3OE2KoSTyWrVbWQ6Z1E0vMvyX9QzY8igKty2/YAAWpwqu9x1aGz104haxYieV8rQ== +inequality@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/inequality/-/inequality-1.2.3.tgz#5050360e5a188a5581000d518454bf3571a62e56" + integrity sha512-nzkJ3DCxHmuJbM8L+6q8P9pPK0vALlac9ShXdXZdK3Vyvo78PEKR6h5OQLfNBJkaHMvsKUQRSrKh9Zn6Ok978Q== inflight@^1.0.4: version "1.0.6"