/** * From https://en.wikipedia.org/wiki/User:Nageh/mathJax.js */ /*global mathJax:true, MathJax:true */ ( function ( mw, $ ) { if ( typeof mathJax === 'undefined' ) { mathJax = {}; } mathJax.version = '0.2'; mathJax.loaded = false; mathJax.locale = mw.config.get('wgUserLanguage'); // See http://docs.mathjax.org/en/latest/options/index.html mathJax.config = $.extend( true, { root: mw.config.get('wgExtensionAssetsPath') + '/Math/modules/MathJax/unpacked', 'v1.0-compatible': false, menuSettings: { zoom: 'Click' }, 'HTML-CSS': { imageFont: null, availableFonts: ['TeX'], mtextFontInherit: true }, MathMenu: { showLocale: false }, jax: ['input/TeX','input/MathML','output/NativeMML','output/HTML-CSS'] }, mathJax.config ); /** * @param {string} relative path to a MathJax file * @return {string} MediaWiki module containing the file */ mathJax.getModuleNameFromFile = function (file) { var regexp, module; // These modules are loaded at startup and thus don't need to be specified: // - ext.math.mathjax.mathjax in mathJax.Load // - ext.math.mathjax.localization in mathJax.Init // - ext.math.mathjax.jax.config in MathJax.Hub.Startup.Jax // - ext.math.mathjax.extensions in MathJax.Hub.Startup.Extensions // module = 'ext.math.mathjax.'; regexp = file.match(/(.*)\/jax\.js/); if ( regexp ) { // These are jax.js files of input, element or output modules: // - ext.math.mathjax.jax.input.MathML // - ext.math.mathjax.jax.input.TeX // - ext.math.mathjax.jax.output.HTML-CSS // - ext.math.mathjax.jax.output.NativeMML // - ext.math.mathjax.jax.output.HTML-CSS // - ext.math.mathjax.jax.output.SVG return module + regexp[1].replace(/\//g,'.'); } if ( file.match(/jax\/element\/mml\/optable/) ) { return module + 'jax.element.mml.optable'; } regexp = file.match(/jax\/output\/(HTML-CSS|SVG)/); if ( regexp ) { module += 'jax.output.' + regexp[1] + '.'; if ( file.match(/autoload/) ) { return module + 'autoload'; } if ( file.match(/fonts\/TeX\/fontdata/) ) { return module + 'fonts.TeX.fontdata'; } if ( file.match(/fonts\/TeX\/.*\/.*\/Main\.js/) ) { return module + 'fonts.TeX.MainJS'; } if ( file.match(/fonts\/TeX\/Main/) ) { return module + 'fonts.TeX.Main'; } if ( file.match(/fonts\/TeX\/AMS/) ) { return module + 'fonts.TeX.AMS'; } if ( file.match(/fonts\/TeX/) ) { return module + 'fonts.TeX.Extra'; } } mw.log( 'MathJax resource not handled by MediaWiki: ' + file ); return null; }; /** * Configure MathJax, preload some files and replace MathJax's resource loader * by our own resource loader. */ mathJax.Init = function () { // Configure MathJax MathJax.Hub.Config( mathJax.config ); MathJax.OutputJax.fontDir = mw.config.get('wgExtensionAssetsPath') + '/Math/modules/MathJax/fonts'; // Redefine MathJax.Hub.Startup.Jax MathJax.Hub.Startup.Jax = function () { var config, jax, i, k, name, queue, callback; // Save the order of the output jax since they are loading asynchronously config = MathJax.Hub.config; jax = MathJax.Hub.outputJax; for ( i = 0, k = 0; i < config.jax.length; i++ ) { name = config.jax[i].substr(7); if ( config.jax[i].substr(0,7) === 'output/' && jax.order[name] === null ) { jax.order[name] = k; k++; } } queue = MathJax.Callback.Queue(); callback = MathJax.Callback({}); return queue.Push( ['Post', MathJax.Hub.Startup.signal, 'Begin Jax'], ['using', mw.loader, 'ext.math.mathjax.jax.config', callback], callback, ['Post', MathJax.Hub.Startup.signal, 'End Jax'] ); }; // Redefine MathJax.Hub.Startup.Extensions MathJax.Hub.Startup.Extensions = function () { var queue, callback; queue = MathJax.Callback.Queue(); callback = MathJax.Callback({}); return queue.Push( ['Post', MathJax.Hub.Startup.signal, 'Begin Extensions'], ['using', mw.loader, 'ext.math.mathjax.extensions', callback], callback, ['Post', MathJax.Hub.Startup.signal, 'End Extensions'] ); }; // Redefine MathJax.Ajax.Load MathJax.Ajax.MathJaxLoad = MathJax.Ajax.Load; MathJax.Ajax.Load = function (file, callback) { var type, i, module; callback = MathJax.Callback(callback); if ( file instanceof Object ) { for ( i in file ) { if ( file.hasOwnProperty(i) ) { type = i.toUpperCase(); file = file[i]; } } } else { type = file.split(/\./).pop().toUpperCase(); } file = MathJax.Ajax.fileURL(file); if ( MathJax.Ajax.loading[file] ) { MathJax.Ajax.addHook(file, callback); } else { if ( MathJax.Ajax.loader[type] ) { module = mathJax.getModuleNameFromFile(file.substring(MathJax.Hub.config.root.length + 1)); if ( module ) { // Use MediaWiki's resource loader. MathJax.Ajax.loading[file] = { callback: callback, timeout: -1, status: this.STATUS.OK, script: null }; // Add this to the structure above after it is created to prevent // recursion when loading the initial localization file (before // loading message is available) MathJax.Ajax.loading[file].message = MathJax.Message.File(file); mw.loader.load(module); } else { // Fallback to MathJax's own loader. callback = MathJax.Ajax.MathJaxLoad(file, callback); } } else { throw new Error('Can\'t load files of type ' + type); } } return callback; }; // Register the final action after MathJax processing: hide // SVG/PNG preview if thas was not done before and show MathJax's output. MathJax.Hub.Startup.signal.MessageHook( 'End', function () { mw.loader.load('ext.math.mathml'); }); // Set MathJax's locale and load the localization data. MathJax.Localization.resetLocale(mathJax.locale); mathJax.locale = MathJax.Localization.locale; MathJax.Hub.config.menuSettings.locale = mathJax.locale; mw.loader.using( 'ext.math.mathjax.localization', function () { MathJax.Hub.Configured(); } ); }; /** * Renders all Math TeX inside the given elements. * @param {function} callback to be executed after text elements have rendered [optional] */ $.fn.renderTex = function ( callback ) { var elem = this.find( '.tex' ).parent().toArray(); if ( !$.isFunction( callback ) ) { callback = $.noop; } function render () { MathJax.Hub.Queue( ['Typeset', MathJax.Hub, elem, callback] ); } mw.loader.using( 'ext.math.mathjax.mathjax', function () { if ( MathJax.isReady ) { render(); } else { MathJax.Hub.Startup.signal.MessageHook( 'End', render ); } } ); return this; }; mathJax.Load = function () { if ( this.loaded ) { return true; } // create the global MathJax variable to hook into MathJax startup MathJax = { delayStartupUntil: 'configured', AuthorInit: mathJax.Init }; // load MathJax.js mw.loader.load('ext.math.mathjax.mathjax'); this.loaded = true; return false; }; $( document ).ready( function () { mathJax.Load(); } ); }( mediaWiki, jQuery ) );