/** * From https://en.wikipedia.org/wiki/User:Nageh/mathJax.js */ /*global mathJax:true, MathJax:true */ ( function ( mw, $ ) { 'use strict'; if ( typeof mathJax === 'undefined' ) { window.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, 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'; MathJax.Ajax.config.path = {}; MathJax.Ajax.config.path.MediaWiki = mw.config.get( 'wgServer' ) + mw.config.get( 'wgExtensionAssetsPath' ) + 'Math/modules/mediawiki-extensions'; // 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 () { mathJax.LoadAndRender( this ); return this; }; mw.log.deprecate( $.fn, 'renderTex', $.fn.renderTex, 'Use the mw.hook wikipage.content instead' ); mathJax.LoadAndRender = function ( $content ) { // create the global MathJax variable to hook into MathJax startup if( typeof MathJax === 'undefined' ) { window.MathJax = { delayStartupUntil: 'configured', skipStartupTypeset: true, AuthorInit: mathJax.Init }; } function render() { var elem = $content.toArray(); MathJax.Hub.Queue( ['Typeset', MathJax.Hub, elem] ); } if ( MathJax.isReady ) { render(); } else { mw.loader.using( 'ext.math.mathjax.mathjax', function () { MathJax.Hub.Startup.signal.MessageHook( 'End', render ); } ); } }; mw.hook( 'wikipage.content' ).add( mathJax.LoadAndRender ); }( mediaWiki, jQuery ) );