mediawiki-extensions-Math/modules/ext.math.mathjax.enabler.js
Derk-Jan Hartman fbfefac248 LivePreview: Use setTimeout to delay rendering of MathJax
wikipage.content hook is fired before the new content is attached, but
MathJax cannot deal with that. Use setTimeout to delay execution until
next execution run.

Bug: T90808
Change-Id: I02178bfd61d34dff49435f3a17a0ce385b37d14d
2015-02-27 20:51:30 +01:00

241 lines
7.3 KiB
JavaScript

/**
* 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 ) {
// Call render asynchronous because live preview fires the hook with
// detached $content. See T90808
setTimeout( 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 ) );