Proyectos de Subversion Moodle

Rev

Rev 1 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 1 Rev 1441
Línea 23... Línea 23...
23
    eventTypes,
23
    eventTypes,
24
    notifyFilterContentRenderingComplete,
24
    notifyFilterContentRenderingComplete,
25
} from 'core_filters/events';
25
} from 'core_filters/events';
Línea 26... Línea 26...
26
 
26
 
27
/**
-
 
28
 * The users current language - this can't be set until MathJax is loaded - so we need to store it.
-
 
29
 * @property {string} lang
27
/**
30
 * @default ''
28
 * URL to MathJax.
31
 * @private
29
 * @type {string|null}
32
 */
30
 */
Línea 33... Línea 31...
33
let lang = '';
31
let mathJaxUrl = null;
34
 
32
 
35
/**
33
/**
36
 * Used to prevent configuring MathJax twice.
-
 
37
 * @property {boolean} configured
-
 
38
 * @default false
34
 * Promise that is resolved when MathJax was loaded.
39
 * @private
35
 * @type {Promise|null}
Línea 40... Línea 36...
40
 */
36
 */
41
let configured = false;
37
let mathJaxLoaded = null;
42
 
38
 
43
/**
39
/**
44
 * Called by the filter when it is active on any page.
40
 * Called by the filter when it is active on any page.
45
 * This does not load MathJAX yet - it addes the configuration to the head incase it gets loaded later.
41
 * This does not load MathJAX yet - it adds the configuration in case it gets loaded later.
46
 * It also subscribes to the filter-content-updated event so MathJax can respond to content loaded by Ajax.
42
 * It also subscribes to the filter-content-updated event so MathJax can respond to content loaded by Ajax.
47
 *
43
 *
-
 
44
 * @param {Object} params List of configuration params containing mathjaxurl, mathjaxconfig (text) and lang
-
 
45
 */
-
 
46
export const configure = (params) => {
48
 * @param {Object} params List of configuration params containing mathjaxconfig (text) and lang
47
    let config = {};
-
 
48
    try {
-
 
49
        if (params.mathjaxconfig !== '') {
-
 
50
            config = JSON.parse(params.mathjaxconfig);
49
 */
51
        }
-
 
52
    }
50
export const configure = (params) => {
53
    catch (e) {
-
 
54
        window.console.error('Invalid JSON in mathjaxconfig.', e);
-
 
55
    }
51
    // Add a js configuration object to the head.
56
    if (typeof config != 'object') {
-
 
57
        config = {};
-
 
58
    }
52
    // See "https://docs.mathjax.org/en/v2.7-latest/advanced/dynamic.html"
59
    if (typeof config.loader !== 'object') {
-
 
60
        config.loader = {};
-
 
61
    }
53
    const script = document.createElement("script");
62
    if (!Array.isArray(config.loader.load)) {
-
 
63
        config.loader.load = [];
-
 
64
    }
Línea -... Línea 65...
-
 
65
    if (typeof config.startup !== 'object') {
-
 
66
        config.startup = {};
-
 
67
    }
-
 
68
 
-
 
69
    // Always ensure that ui/safe is in the list. Otherwise, there is a risk of XSS.
-
 
70
    // https://docs.mathjax.org/en/v3.2-latest/options/safe.html.
54
    script.type = "text/x-mathjax-config";
71
    if (!config.loader.load.includes('ui/safe')) {
-
 
72
        config.loader.load.push('ui/safe');
-
 
73
    }
-
 
74
 
-
 
75
    // This filter controls what elements to typeset.
55
    script[(window.opera ? "innerHTML" : "text")] = params.mathjaxconfig;
76
    config.startup.typeset = false;
-
 
77
 
-
 
78
    // Let's still set the locale even if the localization is not yet ported to version 3.2.2
-
 
79
    // https://docs.mathjax.org/en/v3.2-latest/upgrading/v2.html#not-yet-ported-to-version-3.
Línea 56... Línea 80...
56
    document.getElementsByTagName("head")[0].appendChild(script);
80
    config.locale = params.lang;
57
 
81
 
58
    // Save the lang config until MathJax is actually loaded.
82
    mathJaxUrl = params.mathjaxurl;
59
    lang = params.lang;
83
    window.MathJax = config;
Línea 60... Línea 84...
60
 
84
 
61
    // Listen for events triggered when new text is added to a page that needs
-
 
62
    // processing by a filter.
-
 
63
    document.addEventListener(eventTypes.filterContentUpdated, contentUpdated);
-
 
64
};
-
 
65
 
-
 
66
/**
-
 
67
 * Set the correct language for the MathJax menus. Only do this once.
-
 
68
 *
-
 
69
 * @private
-
 
70
 */
-
 
71
const setLocale = () => {
-
 
72
    if (!configured) {
-
 
73
        if (typeof window.MathJax !== "undefined") {
-
 
74
            window.MathJax.Hub.Queue(function() {
-
 
75
                window.MathJax.Localization.setLocale(lang);
-
 
76
            });
-
 
77
            window.MathJax.Hub.Configured();
-
 
78
            configured = true;
85
    // Listen for events triggered when new text is added to a page that needs
79
        }
86
    // processing by a filter.
80
    }
87
    document.addEventListener(eventTypes.filterContentUpdated, contentUpdated);
81
};
88
};
82
 
89
 
Línea 91... Línea 98...
91
        // We may have been passed a #text node.
98
        // We may have been passed a #text node.
92
        // These cannot be formatted.
99
        // These cannot be formatted.
93
        return;
100
        return;
94
    }
101
    }
Línea 95... Línea -...
95
 
-
 
96
    // MathJax 2.X does not notify when complete. The best we can do, according to their docs, is to queue a callback.
102
 
97
    // See https://docs.mathjax.org/en/v2.7-latest/advanced/typeset.html
-
 
98
    // Note that the MathJax.Hub.Queue() method will return immediately, regardless of whether the typesetting has taken place
103
    loadMathJax().then(() => {
99
    // or not, so you can not assume that the mathematics is visible after you make this call.
-
 
100
    // That means that things like the size of the container for the mathematics may not yet reflect the size of the
104
        // Chain the calls to typesetPromise as it is recommended.
101
    // typeset mathematics. If you need to perform actions that depend on the mathematics being typeset, you should push those
105
        // https://docs.mathjax.org/en/v3.2-latest/web/typeset.html#handling-asynchronous-typesetting.
102
    // actions onto the MathJax.Hub.queue as well.
106
        window.MathJax.startup.promise = window.MathJax.startup.promise
103
    window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub, node]);
107
            .then(() => window.MathJax.typesetPromise([node]))
104
    window.MathJax.Hub.Queue([(node) => {
108
            .then(() => {
-
 
109
                notifyFilterContentRenderingComplete([node]);
105
        // The notifyFilterContentRenderingComplete event takes an Array of NodeElements or a NodeList.
110
            })
106
        // We cannot create a NodeList so we use an HTMLElement[].
111
            .catch(e => {
107
        notifyFilterContentRenderingComplete([node]);
112
                window.console.log(e);
-
 
113
            });
108
    }, node]);
114
    });
Línea 109... Línea 115...
109
};
115
};
110
 
116
 
111
/**
117
/**
112
 * Called by the filter when an equation is found while rendering the page.
118
 * Called by the filter when an equation is found while rendering the page.
113
 */
-
 
114
export const typeset = () => {
-
 
115
    if (!configured) {
119
 */
116
        setLocale();
120
export const typeset = () => {
117
        const elements = document.getElementsByClassName('filter_mathjaxloader_equation');
-
 
118
        for (const element of elements) {
121
    const elements = document.getElementsByClassName('filter_mathjaxloader_equation');
119
            if (typeof window.MathJax !== "undefined") {
-
 
120
                typesetNode(element);
-
 
121
            }
122
    for (const element of elements) {
122
        }
123
        typesetNode(element);
Línea 123... Línea 124...
123
    }
124
    }
124
};
125
};
125
 
126
 
126
/**
127
/**
127
 * Handle content updated events - typeset the new content.
128
 * Handle content updated events - typeset the new content.
128
 *
129
 *
129
 * @param {CustomEvent} event - Custom event with "nodes" indicating the root of the updated nodes.
-
 
130
 */
-
 
131
export const contentUpdated = (event) => {
-
 
132
    if (typeof window.MathJax === "undefined") {
-
 
133
        return;
130
 * @param {CustomEvent} event - Custom event with "nodes" indicating the root of the updated nodes.
134
    }
131
 */
135
 
132
export const contentUpdated = (event) => {
136
    let listOfElementContainMathJax = [];
133
    let listOfElementContainMathJax = [];
137
    let hasMathJax = false;
134
    let hasMathJax = false;
Línea 145... Línea 142...
145
        if (mathjaxElements.length > 0) {
142
        if (mathjaxElements.length > 0) {
146
            hasMathJax = true;
143
            hasMathJax = true;
147
        }
144
        }
148
        listOfElementContainMathJax.push(mathjaxElements);
145
        listOfElementContainMathJax.push(mathjaxElements);
149
    });
146
    });
-
 
147
 
150
    if (!hasMathJax) {
148
    if (!hasMathJax) {
151
        return;
149
        return;
152
    }
150
    }
153
    const processDelay = window.MathJax.Hub.processSectionDelay;
-
 
154
    // Set the process section delay to 0 when updating the formula.
-
 
155
    window.MathJax.Hub.processSectionDelay = 0;
-
 
156
    // When content is updated never position to hash, it may cause unexpected document scrolling.
-
 
157
    window.MathJax.Hub.Config({positionToHash: false});
-
 
158
    setLocale();
-
 
-
 
151
 
159
    listOfElementContainMathJax.forEach((mathjaxElements) => {
152
    listOfElementContainMathJax.forEach((mathjaxElements) => {
160
        mathjaxElements.forEach((node) => typesetNode(node));
153
        mathjaxElements.forEach((node) => typesetNode(node));
161
    });
154
    });
-
 
155
};
-
 
156
 
-
 
157
/**
-
 
158
 * Load the MathJax script.
-
 
159
 *
-
 
160
 * @return Promise that is resolved when MathJax was loaded.
-
 
161
 */
-
 
162
export const loadMathJax = () => {
-
 
163
    if (!mathJaxLoaded) {
-
 
164
        if (!mathJaxUrl) {
-
 
165
            return Promise.reject(new Error('URL to MathJax not set.'));
-
 
166
        }
-
 
167
 
162
    window.MathJax.Hub.processSectionDelay = processDelay;
168
        mathJaxLoaded = new Promise((resolve, reject) => {
-
 
169
            const script = document.createElement('script');
-
 
170
            script.type = 'text/javascript';
-
 
171
            script.onload = resolve;
-
 
172
            script.onerror = reject;
-
 
173
            script.src = mathJaxUrl;
-
 
174
            document.getElementsByTagName('head')[0].appendChild(script);
-
 
175
        });
-
 
176
    }
-
 
177
    return mathJaxLoaded;
163
};
178
};