From 38b22124bfe06ce20399231c150e1e5c211cb2a0 Mon Sep 17 00:00:00 2001 From: Huong Nguyen Date: Fri, 11 Apr 2025 12:03:44 +0700 Subject: [PATCH] MDL-85155 filter_mathmaxloader: Fix local hosted instance loading --- filter/mathjaxloader/amd/build/loader.min.js | 2 +- .../mathjaxloader/amd/build/loader.min.js.map | 2 +- filter/mathjaxloader/amd/src/loader.js | 36 ++++++++++++++----- filter/mathjaxloader/classes/text_filter.php | 7 ++-- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/filter/mathjaxloader/amd/build/loader.min.js b/filter/mathjaxloader/amd/build/loader.min.js index e471737b3df..20578da35c5 100644 --- a/filter/mathjaxloader/amd/build/loader.min.js +++ b/filter/mathjaxloader/amd/build/loader.min.js @@ -1,3 +1,3 @@ -define("filter_mathjaxloader/loader",["exports","core_filters/events"],(function(_exports,_events){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.typeset=_exports.contentUpdated=_exports.configure=void 0;_exports.configure=params=>{window.MathJax&&(window.MathJax.config.locale=params.lang),document.addEventListener(_events.eventTypes.filterContentUpdated,contentUpdated)};const typesetNode=node=>{node instanceof HTMLElement&&window.MathJax&&window.MathJax.typesetPromise([node]).then((()=>{(0,_events.notifyFilterContentRenderingComplete)([node])})).catch((e=>{window.console.log(e)}))};_exports.typeset=()=>{const elements=document.getElementsByClassName("filter_mathjaxloader_equation");for(const element of elements)void 0!==window.MathJax&&typesetNode(element)};const contentUpdated=event=>{if(void 0===window.MathJax)return;let listOfElementContainMathJax=[],hasMathJax=!1;event.detail.nodes.forEach((node=>{if(!(node instanceof HTMLElement))return;const mathjaxElements=node.querySelectorAll(".filter_mathjaxloader_equation");mathjaxElements.length>0&&(hasMathJax=!0),listOfElementContainMathJax.push(mathjaxElements)})),hasMathJax&&listOfElementContainMathJax.forEach((mathjaxElements=>{mathjaxElements.forEach((node=>typesetNode(node)))}))};_exports.contentUpdated=contentUpdated})); +define("filter_mathjaxloader/loader",["exports","core_filters/events"],(function(_exports,_events){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.typeset=_exports.contentUpdated=_exports.configure=void 0;_exports.configure=params=>{loadMathJax(params.mathjaxurl,(()=>{window.MathJax&&(window.MathJax.config.locale=params.lang),document.addEventListener(_events.eventTypes.filterContentUpdated,contentUpdated)}))};const typesetNode=node=>{node instanceof HTMLElement&&window.MathJax&&window.MathJax.typesetPromise([node]).then((()=>{(0,_events.notifyFilterContentRenderingComplete)([node])})).catch((e=>{window.console.log(e)}))};_exports.typeset=()=>{const elements=document.getElementsByClassName("filter_mathjaxloader_equation");for(const element of elements)void 0!==window.MathJax&&typesetNode(element)};const contentUpdated=event=>{if(void 0===window.MathJax)return;let listOfElementContainMathJax=[],hasMathJax=!1;event.detail.nodes.forEach((node=>{if(!(node instanceof HTMLElement))return;const mathjaxElements=node.querySelectorAll(".filter_mathjaxloader_equation");mathjaxElements.length>0&&(hasMathJax=!0),listOfElementContainMathJax.push(mathjaxElements)})),hasMathJax&&listOfElementContainMathJax.forEach((mathjaxElements=>{mathjaxElements.forEach((node=>typesetNode(node)))}))};_exports.contentUpdated=contentUpdated;const loadMathJax=(url,callback)=>{const script=document.createElement("script");script.type="text/javascript",script.onload=()=>{callback()},script.src=url,document.getElementsByTagName("head")[0].appendChild(script)}})); //# sourceMappingURL=loader.min.js.map \ No newline at end of file diff --git a/filter/mathjaxloader/amd/build/loader.min.js.map b/filter/mathjaxloader/amd/build/loader.min.js.map index 5434d69977b..9e13f474bb2 100644 --- a/filter/mathjaxloader/amd/build/loader.min.js.map +++ b/filter/mathjaxloader/amd/build/loader.min.js.map @@ -1 +1 @@ -{"version":3,"file":"loader.min.js","sources":["../src/loader.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Mathjax JS Loader.\n *\n * @module filter_mathjaxloader/loader\n * @copyright 2014 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {\n eventTypes,\n notifyFilterContentRenderingComplete,\n} from 'core_filters/events';\n\n/**\n * Called by the filter when it is active on any page.\n * This does not load MathJAX yet - it addes the configuration to the head incase it gets loaded later.\n * It also subscribes to the filter-content-updated event so MathJax can respond to content loaded by Ajax.\n *\n * @param {Object} params List of configuration params containing mathjaxconfig (text) and lang\n */\nexport const configure = (params) => {\n if (window.MathJax) {\n // Let's still set the locale even if the localization is not yet ported to version 3.2.2\n // https://docs.mathjax.org/en/v3.2-latest/upgrading/v2.html#not-yet-ported-to-version-3.\n window.MathJax.config.locale = params.lang;\n }\n\n // Listen for events triggered when new text is added to a page that needs\n // processing by a filter.\n document.addEventListener(eventTypes.filterContentUpdated, contentUpdated);\n};\n\n/**\n * Add the node to the typeset queue.\n *\n * @param {HTMLElement} node The Node to be processed by MathJax\n * @private\n */\nconst typesetNode = (node) => {\n if (!(node instanceof HTMLElement)) {\n // We may have been passed a #text node.\n // These cannot be formatted.\n return;\n }\n\n if (window.MathJax) {\n window.MathJax.typesetPromise([node]).then(() => {\n notifyFilterContentRenderingComplete([node]);\n return;\n })\n .catch(e => {\n window.console.log(e);\n });\n }\n};\n\n/**\n * Called by the filter when an equation is found while rendering the page.\n */\nexport const typeset = () => {\n const elements = document.getElementsByClassName('filter_mathjaxloader_equation');\n for (const element of elements) {\n if (typeof window.MathJax !== \"undefined\") {\n typesetNode(element);\n }\n }\n};\n\n/**\n * Handle content updated events - typeset the new content.\n *\n * @param {CustomEvent} event - Custom event with \"nodes\" indicating the root of the updated nodes.\n */\nexport const contentUpdated = (event) => {\n if (typeof window.MathJax === \"undefined\") {\n return;\n }\n\n let listOfElementContainMathJax = [];\n let hasMathJax = false;\n // The list of HTMLElements in an Array.\n event.detail.nodes.forEach((node) => {\n if (!(node instanceof HTMLElement)) {\n // We may have been passed a #text node.\n return;\n }\n const mathjaxElements = node.querySelectorAll('.filter_mathjaxloader_equation');\n if (mathjaxElements.length > 0) {\n hasMathJax = true;\n }\n listOfElementContainMathJax.push(mathjaxElements);\n });\n\n if (!hasMathJax) {\n return;\n }\n\n listOfElementContainMathJax.forEach((mathjaxElements) => {\n mathjaxElements.forEach((node) => typesetNode(node));\n });\n};\n"],"names":["params","window","MathJax","config","locale","lang","document","addEventListener","eventTypes","filterContentUpdated","contentUpdated","typesetNode","node","HTMLElement","typesetPromise","then","catch","e","console","log","elements","getElementsByClassName","element","event","listOfElementContainMathJax","hasMathJax","detail","nodes","forEach","mathjaxElements","querySelectorAll","length","push"],"mappings":"iPAiC0BA,SAClBC,OAAOC,UAGPD,OAAOC,QAAQC,OAAOC,OAASJ,OAAOK,MAK1CC,SAASC,iBAAiBC,mBAAWC,qBAAsBC,uBASzDC,YAAeC,OACXA,gBAAgBC,aAMlBZ,OAAOC,SACPD,OAAOC,QAAQY,eAAe,CAACF,OAAOG,MAAK,sDACF,CAACH,UAGzCI,OAAMC,IACHhB,OAAOiB,QAAQC,IAAIF,wBAQR,WACbG,SAAWd,SAASe,uBAAuB,qCAC5C,MAAMC,WAAWF,cACY,IAAnBnB,OAAOC,SACdS,YAAYW,gBAUXZ,eAAkBa,gBACG,IAAnBtB,OAAOC,mBAIdsB,4BAA8B,GAC9BC,YAAa,EAEjBF,MAAMG,OAAOC,MAAMC,SAAShB,YAClBA,gBAAgBC,0BAIhBgB,gBAAkBjB,KAAKkB,iBAAiB,kCAC1CD,gBAAgBE,OAAS,IACzBN,YAAa,GAEjBD,4BAA4BQ,KAAKH,oBAGhCJ,YAILD,4BAA4BI,SAASC,kBACjCA,gBAAgBD,SAAShB,MAASD,YAAYC"} \ No newline at end of file +{"version":3,"file":"loader.min.js","sources":["../src/loader.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Mathjax JS Loader.\n *\n * @module filter_mathjaxloader/loader\n * @copyright 2014 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {\n eventTypes,\n notifyFilterContentRenderingComplete,\n} from 'core_filters/events';\n\n/**\n * Called by the filter when it is active on any page.\n * This does not load MathJAX yet - it addes the configuration to the head incase it gets loaded later.\n * It also subscribes to the filter-content-updated event so MathJax can respond to content loaded by Ajax.\n *\n * @param {Object} params List of configuration params containing mathjaxurl, mathjaxconfig (text) and lang\n */\nexport const configure = (params) => {\n loadMathJax(params.mathjaxurl, () => {\n if (window.MathJax) {\n // Let's still set the locale even if the localization is not yet ported to version 3.2.2\n // https://docs.mathjax.org/en/v3.2-latest/upgrading/v2.html#not-yet-ported-to-version-3.\n window.MathJax.config.locale = params.lang;\n }\n\n // Listen for events triggered when new text is added to a page that needs\n // processing by a filter.\n document.addEventListener(eventTypes.filterContentUpdated, contentUpdated);\n });\n};\n\n/**\n * Add the node to the typeset queue.\n *\n * @param {HTMLElement} node The Node to be processed by MathJax\n * @private\n */\nconst typesetNode = (node) => {\n if (!(node instanceof HTMLElement)) {\n // We may have been passed a #text node.\n // These cannot be formatted.\n return;\n }\n\n if (window.MathJax) {\n window.MathJax.typesetPromise([node]).then(() => {\n notifyFilterContentRenderingComplete([node]);\n return;\n })\n .catch(e => {\n window.console.log(e);\n });\n }\n};\n\n/**\n * Called by the filter when an equation is found while rendering the page.\n */\nexport const typeset = () => {\n const elements = document.getElementsByClassName('filter_mathjaxloader_equation');\n for (const element of elements) {\n if (typeof window.MathJax !== \"undefined\") {\n typesetNode(element);\n }\n }\n};\n\n/**\n * Handle content updated events - typeset the new content.\n *\n * @param {CustomEvent} event - Custom event with \"nodes\" indicating the root of the updated nodes.\n */\nexport const contentUpdated = (event) => {\n if (typeof window.MathJax === \"undefined\") {\n return;\n }\n\n let listOfElementContainMathJax = [];\n let hasMathJax = false;\n // The list of HTMLElements in an Array.\n event.detail.nodes.forEach((node) => {\n if (!(node instanceof HTMLElement)) {\n // We may have been passed a #text node.\n return;\n }\n const mathjaxElements = node.querySelectorAll('.filter_mathjaxloader_equation');\n if (mathjaxElements.length > 0) {\n hasMathJax = true;\n }\n listOfElementContainMathJax.push(mathjaxElements);\n });\n\n if (!hasMathJax) {\n return;\n }\n\n listOfElementContainMathJax.forEach((mathjaxElements) => {\n mathjaxElements.forEach((node) => typesetNode(node));\n });\n};\n\n/**\n * Load the MathJax script.\n *\n * @param {String} url The URL of the MathJax script to load.\n * @param {function} callback The function to call when the script has loaded.\n */\nconst loadMathJax = (url, callback) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.onload = () => {\n callback();\n };\n script.src = url;\n document.getElementsByTagName('head')[0].appendChild(script);\n};\n"],"names":["params","loadMathJax","mathjaxurl","window","MathJax","config","locale","lang","document","addEventListener","eventTypes","filterContentUpdated","contentUpdated","typesetNode","node","HTMLElement","typesetPromise","then","catch","e","console","log","elements","getElementsByClassName","element","event","listOfElementContainMathJax","hasMathJax","detail","nodes","forEach","mathjaxElements","querySelectorAll","length","push","url","callback","script","createElement","type","onload","src","getElementsByTagName","appendChild"],"mappings":"iPAiC0BA,SACtBC,YAAYD,OAAOE,YAAY,KACvBC,OAAOC,UAGPD,OAAOC,QAAQC,OAAOC,OAASN,OAAOO,MAK1CC,SAASC,iBAAiBC,mBAAWC,qBAAsBC,0BAU7DC,YAAeC,OACXA,gBAAgBC,aAMlBZ,OAAOC,SACPD,OAAOC,QAAQY,eAAe,CAACF,OAAOG,MAAK,sDACF,CAACH,UAGzCI,OAAMC,IACHhB,OAAOiB,QAAQC,IAAIF,wBAQR,WACbG,SAAWd,SAASe,uBAAuB,qCAC5C,MAAMC,WAAWF,cACY,IAAnBnB,OAAOC,SACdS,YAAYW,gBAUXZ,eAAkBa,gBACG,IAAnBtB,OAAOC,mBAIdsB,4BAA8B,GAC9BC,YAAa,EAEjBF,MAAMG,OAAOC,MAAMC,SAAShB,YAClBA,gBAAgBC,0BAIhBgB,gBAAkBjB,KAAKkB,iBAAiB,kCAC1CD,gBAAgBE,OAAS,IACzBN,YAAa,GAEjBD,4BAA4BQ,KAAKH,oBAGhCJ,YAILD,4BAA4BI,SAASC,kBACjCA,gBAAgBD,SAAShB,MAASD,YAAYC,yDAUhDb,YAAc,CAACkC,IAAKC,kBAChBC,OAAS7B,SAAS8B,cAAc,UACtCD,OAAOE,KAAO,kBACdF,OAAOG,OAAS,KACZJ,YAEJC,OAAOI,IAAMN,IACb3B,SAASkC,qBAAqB,QAAQ,GAAGC,YAAYN"} \ No newline at end of file diff --git a/filter/mathjaxloader/amd/src/loader.js b/filter/mathjaxloader/amd/src/loader.js index 878055f664a..a9731469181 100644 --- a/filter/mathjaxloader/amd/src/loader.js +++ b/filter/mathjaxloader/amd/src/loader.js @@ -29,18 +29,20 @@ import { * This does not load MathJAX yet - it addes the configuration to the head incase it gets loaded later. * It also subscribes to the filter-content-updated event so MathJax can respond to content loaded by Ajax. * - * @param {Object} params List of configuration params containing mathjaxconfig (text) and lang + * @param {Object} params List of configuration params containing mathjaxurl, mathjaxconfig (text) and lang */ export const configure = (params) => { - if (window.MathJax) { - // Let's still set the locale even if the localization is not yet ported to version 3.2.2 - // https://docs.mathjax.org/en/v3.2-latest/upgrading/v2.html#not-yet-ported-to-version-3. - window.MathJax.config.locale = params.lang; - } + loadMathJax(params.mathjaxurl, () => { + if (window.MathJax) { + // Let's still set the locale even if the localization is not yet ported to version 3.2.2 + // https://docs.mathjax.org/en/v3.2-latest/upgrading/v2.html#not-yet-ported-to-version-3. + window.MathJax.config.locale = params.lang; + } - // Listen for events triggered when new text is added to a page that needs - // processing by a filter. - document.addEventListener(eventTypes.filterContentUpdated, contentUpdated); + // Listen for events triggered when new text is added to a page that needs + // processing by a filter. + document.addEventListener(eventTypes.filterContentUpdated, contentUpdated); + }); }; /** @@ -112,3 +114,19 @@ export const contentUpdated = (event) => { mathjaxElements.forEach((node) => typesetNode(node)); }); }; + +/** + * Load the MathJax script. + * + * @param {String} url The URL of the MathJax script to load. + * @param {function} callback The function to call when the script has loaded. + */ +const loadMathJax = (url, callback) => { + const script = document.createElement('script'); + script.type = 'text/javascript'; + script.onload = () => { + callback(); + }; + script.src = url; + document.getElementsByTagName('head')[0].appendChild(script); +}; diff --git a/filter/mathjaxloader/classes/text_filter.php b/filter/mathjaxloader/classes/text_filter.php index 6f931b95ffa..68227d1f6a5 100644 --- a/filter/mathjaxloader/classes/text_filter.php +++ b/filter/mathjaxloader/classes/text_filter.php @@ -78,7 +78,6 @@ class text_filter extends \core_filters\text_filter { $url = get_config('filter_mathjaxloader', 'httpsurl'); $lang = $this->map_language_code(current_language()); $url = new url($url); - $page->requires->js($url); // Let's still get this config even if the value is null due to the setting being set as default. // For the config we can set based on the needs when we need from: @@ -86,7 +85,11 @@ class text_filter extends \core_filters\text_filter { $config = get_config('filter_mathjaxloader', 'mathjaxconfig'); $wwwroot = new url('/'); $config = str_replace('{wwwroot}', $wwwroot->out(true), $config); - $params = ['mathjaxconfig' => $config, 'lang' => $lang]; + $params = [ + 'mathjaxurl' => $url->out(false), + 'mathjaxconfig' => $config, + 'lang' => $lang, + ]; // Let's still send the config and lang to the loader. $page->requires->js_call_amd('filter_mathjaxloader/loader', 'configure', [$params]);