From d979b40f0a3eaf4f196f20cd03d0ff0658ce3d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Tainon?= Date: Wed, 5 Nov 2025 16:05:04 +0100 Subject: [PATCH] Add LaTeX expressions using Mathjax lib --- frontend/index.tsx | 1 + frontend/submission/task_platform.ts | 12 ++++++++++- frontend/task/instructions/instructions.scss | 4 ++++ frontend/task/libs/import_modules.ts | 21 +++++++++++++++++++ .../task/libs/quickalgo_library_factory.ts | 6 ++++-- frontend/task/task_types.ts | 1 + 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/frontend/index.tsx b/frontend/index.tsx index 1376f89c3..73ad19d96 100644 --- a/frontend/index.tsx +++ b/frontend/index.tsx @@ -149,6 +149,7 @@ declare global { taskSettings?: any, initBlocklySubTask?: () => void, instructionsPostProcessing?: (() => void)[], + MathJax: any, } } diff --git a/frontend/submission/task_platform.ts b/frontend/submission/task_platform.ts index 5a28837c6..facceff9e 100644 --- a/frontend/submission/task_platform.ts +++ b/frontend/submission/task_platform.ts @@ -123,7 +123,7 @@ export function getTaskDataFromTaskSettings(taskSettings: any) { return taskData; } -export function getServerTaskFromTaskData(taskData: any, task: TaskServer = null) { +export function getServerTaskFromTaskData(taskData: any, task: TaskServer = null): Task { if (taskData.data) { taskData.gridInfos.allowClientExecution = true; } @@ -136,6 +136,16 @@ export function getServerTaskFromTaskData(taskData: any, task: TaskServer = null if (window.PEMTaskMetaData.supportedLanguages) { taskData.supportedLanguages = window.PEMTaskMetaData.supportedLanguages.join(','); } + if (window.PEMTaskMetaData.useLatex) { + taskData.useLatex = !!window.PEMTaskMetaData.useLatex; + } + } + + if (task.useLatex) { + taskData.gridInfos.importModules = [ + ...(taskData.gridInfos.importModules ?? []), + 'mathjax', + ]; } return { diff --git a/frontend/task/instructions/instructions.scss b/frontend/task/instructions/instructions.scss index e063c77ab..a24a38d75 100644 --- a/frontend/task/instructions/instructions.scss +++ b/frontend/task/instructions/instructions.scss @@ -46,3 +46,7 @@ .task-instructions-video.is-not-shown { cursor: pointer; } + +.mjx-chtml { + font-size: 100% !important; +} diff --git a/frontend/task/libs/import_modules.ts b/frontend/task/libs/import_modules.ts index 752a0d9d7..60fb217fb 100644 --- a/frontend/task/libs/import_modules.ts +++ b/frontend/task/libs/import_modules.ts @@ -361,6 +361,27 @@ export function loadFonts(theme: string, task: Task|null) { } } +let mathJaxConfigured = false; +export function loadMathJax() { + if (mathJaxConfigured) { + return; + } + + window.MathJax.Hub.Config({ + tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}, + messageStyle: "none", + }); + window.MathJax.Hub.processSectionDelay = 0; + + window.instructionsPostProcessing = [ + ...(window.instructionsPostProcessing ?? []), + () => { + window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub]); + }, + ]; + mathJaxConfigured = true; +} + export function getJsLibLoaded() { return jsLibLoaded; } diff --git a/frontend/task/libs/quickalgo_library_factory.ts b/frontend/task/libs/quickalgo_library_factory.ts index babbce232..e8bdda93e 100644 --- a/frontend/task/libs/quickalgo_library_factory.ts +++ b/frontend/task/libs/quickalgo_library_factory.ts @@ -2,8 +2,8 @@ import {appSelect} from '../../hooks'; import {quickAlgoLibraries} from './quick_algo_libraries_model'; import log from 'loglevel'; import {extractLevelSpecific, extractVariantSpecific} from '../utils'; -import {call, put, select} from 'typed-redux-saga'; -import {importModules, importPlatformModules, loadFonts} from './import_modules'; +import {call, put} from 'typed-redux-saga'; +import {importModules, importPlatformModules, loadFonts, loadMathJax} from './import_modules'; import {SmartContractLib} from './smart_contract/smart_contract_lib'; import {DefaultQuickalgoLibrary} from './default_quickalgo_library'; import {PrinterLib} from './printer/printer_lib'; @@ -81,6 +81,8 @@ export function* createQuickalgoLibrary(platformAlreadyChanged: boolean = false) yield* call(importModules, levelGridInfos.importModules, window.modulesPath); } } + + yield* call(loadMathJax); yield* call(loadFonts, state.options.theme, currentTask); // Reset fully local strings when creating a new context to avoid keeping strings from an other language diff --git a/frontend/task/task_types.ts b/frontend/task/task_types.ts index 31b289e0c..fd01fb555 100644 --- a/frontend/task/task_types.ts +++ b/frontend/task/task_types.ts @@ -164,6 +164,7 @@ export interface TaskNormalized { author: string, showLimits: boolean, userTests: boolean, + useLatex: boolean, isEvaluable: boolean, scriptAnimation: string, hasSubtasks: boolean,