mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-24 22:35:41 +00:00
Merge "Infrastructure for loading plugins in the MW integration"
This commit is contained in:
commit
d477bfeb6c
|
@ -121,8 +121,9 @@ class VisualEditorHooks {
|
|||
* Adds extra variables to the global config
|
||||
*/
|
||||
public static function onResourceLoaderGetConfigVars( array &$vars ) {
|
||||
global $wgVisualEditorEnableExperimentalCode, $wgVisualEditorEnableEventLogging,
|
||||
$wgVisualEditorTabLayout, $wgVisualEditorDisableForAnons, $wgVisualEditorNamespaces;
|
||||
global $wgVisualEditorEnableEventLogging, $wgVisualEditorPluginModules,
|
||||
$wgVisualEditorEnableExperimentalCode, $wgVisualEditorTabLayout,
|
||||
$wgVisualEditorDisableForAnons, $wgVisualEditorNamespaces;
|
||||
|
||||
$vars['wgVisualEditorConfig'] = array(
|
||||
'enableExperimentalCode' => $wgVisualEditorEnableExperimentalCode,
|
||||
|
@ -131,6 +132,7 @@ class VisualEditorHooks {
|
|||
'disableForAnons' => $wgVisualEditorDisableForAnons,
|
||||
'namespaces' => $wgVisualEditorNamespaces,
|
||||
'skins' => self::$supportedSkins,
|
||||
'pluginModules' => $wgVisualEditorPluginModules,
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
|
||||
/* Configuration */
|
||||
|
||||
// Array of ResourceLoader module names (strings) that should be loaded when VisualEditor is
|
||||
// loaded. Other extensions that extend VisualEditor should add to this array.
|
||||
$wgVisualEditorPluginModules = array();
|
||||
|
||||
// URL to the Parsoid instance
|
||||
// MUST NOT end in a slash due to Parsoid bug
|
||||
$wgVisualEditorParsoidURL = 'http://localhost:8000';
|
||||
|
@ -38,6 +42,7 @@ $wgVisualEditorTabLayout = 'replace';
|
|||
// upon signup.
|
||||
// Depends on GuidedTour and EventLogging extensions.
|
||||
$wgVisualEditorEnableGenderSurvey = false;
|
||||
|
||||
/* Setup */
|
||||
|
||||
$wgExtensionCredits['other'][] = array(
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
*/
|
||||
( function () {
|
||||
var conf, uri, pageExists, viewUri, veEditUri, isViewPage,
|
||||
init, support, getTargetDeferred;
|
||||
init, support, getTargetDeferred,
|
||||
plugins = [];
|
||||
|
||||
/**
|
||||
* Use deferreds to avoid loading and instantiating Target multiple times.
|
||||
|
@ -38,6 +39,9 @@
|
|||
// Transfer methods
|
||||
ve.init.mw.ViewPageTarget.prototype.setupSectionEditLinks = init.setupSectionEditLinks;
|
||||
|
||||
// Add plugins
|
||||
target.addPlugins( plugins );
|
||||
|
||||
getTargetDeferred.resolve( target );
|
||||
} )
|
||||
.fail( getTargetDeferred.reject );
|
||||
|
@ -98,6 +102,45 @@
|
|||
'blackberry': null
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a plugin module or function.
|
||||
*
|
||||
* Plugins are run after VisualEditor is loaded, but before it is initialized. This allows
|
||||
* plugins to add classes and register them with the factories and registries.
|
||||
*
|
||||
* The parameter to this function can be a ResourceLoader module name or a function.
|
||||
*
|
||||
* If it's a module name, it will be loaded together with the VisualEditor core modules when
|
||||
* VE is loaded. No special care is taken to ensure that the module runs after the VE
|
||||
* classes are loaded, so if this is desired, the module should depend on
|
||||
* ext.visualEditor.core .
|
||||
*
|
||||
* If it's a function, it will be invoked once the VisualEditor core modules and any
|
||||
* plugin modules registered through this function have been loaded, but before the editor
|
||||
* is intialized. The function takes one parameter, which is the ve.init.mw.Target instance
|
||||
* that's initializing, and can optionally return a jQuery.Promise . VisualEditor will
|
||||
* only be initialized once all promises returned by plugin functions have been resolved.
|
||||
*
|
||||
* @example
|
||||
* // Register ResourceLoader module
|
||||
* ve.libs.mw.addPlugin( 'ext.gadget.foobar' );
|
||||
*
|
||||
* // Register a callback
|
||||
* ve.libs.mw.addPlugin( function ( target ) {
|
||||
* ve.dm.Foobar = .....
|
||||
* } );
|
||||
*
|
||||
* // Register a callback that loads another script
|
||||
* ve.libs.mw.addPlugin( function () {
|
||||
* return $.getScript( 'http://example.com/foobar.js' );
|
||||
* } );
|
||||
*
|
||||
* @param {string|Function} plugin Module name or callback that optionally returns a promise
|
||||
*/
|
||||
addPlugin: function( plugin ) {
|
||||
plugins.push( plugin );
|
||||
},
|
||||
|
||||
skinSetup: function () {
|
||||
init.setupTabLayout();
|
||||
init.setupSectionEditLinks();
|
||||
|
|
|
@ -41,7 +41,10 @@ ve.init.mw.Target = function VeInitMwTarget( $container, pageName, revisionId )
|
|||
document.createElementNS && document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ).createSVGRect ?
|
||||
['ext.visualEditor.viewPageTarget.icons-vector', 'ext.visualEditor.icons-vector'] :
|
||||
['ext.visualEditor.viewPageTarget.icons-raster', 'ext.visualEditor.icons-raster']
|
||||
);
|
||||
)
|
||||
.concat( mw.config.get( 'wgVisualEditorConfig' ).pluginModules || [] );
|
||||
this.pluginCallbacks = [];
|
||||
this.modulesReady = $.Deferred();
|
||||
this.loading = false;
|
||||
this.saving = false;
|
||||
this.serializing = false;
|
||||
|
@ -123,6 +126,28 @@ ve.inheritClass( ve.init.mw.Target, ve.init.Target );
|
|||
|
||||
/* Static Methods */
|
||||
|
||||
/**
|
||||
* Handle the RL modules for VE and registered plugin modules being loaded.
|
||||
*
|
||||
* This method is called within the context of a target instance. It executes all registered
|
||||
* plugin callbacks, gathers any promises returned and resolves this.modulesReady when all of
|
||||
* the gathered promises are resolved.
|
||||
*/
|
||||
ve.init.mw.Target.onModulesReady = function () {
|
||||
var i, len, callbackResult, promises = [];
|
||||
for ( i = 0, len = this.pluginCallbacks.length; i < len; i++ ) {
|
||||
callbackResult = this.pluginCallbacks[i]( this );
|
||||
if ( callbackResult && callbackResult.then ) { // duck-type jQuery.Promise using .then
|
||||
promises.push( callbackResult );
|
||||
}
|
||||
}
|
||||
// Dereference the callbacks
|
||||
this.pluginCallbacks = [];
|
||||
// Create a master promise tracking all the promises we got, and wait for it
|
||||
// to be resolved
|
||||
$.when.apply( $, promises ).done( this.modulesReady.resolve ).fail( this.modulesReady.reject );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle response to a successful load request.
|
||||
*
|
||||
|
@ -169,8 +194,8 @@ ve.init.mw.Target.onLoad = function ( response ) {
|
|||
this.baseTimeStamp = data.basetimestamp;
|
||||
this.startTimeStamp = data.starttimestamp;
|
||||
this.revid = data.oldid;
|
||||
// Everything worked, the page was loaded, continue as soon as the module is ready
|
||||
mw.loader.using( this.modules, ve.bind( ve.init.mw.Target.onReady, this ) );
|
||||
// Everything worked, the page was loaded, continue as soon as the modules are loaded
|
||||
this.modulesReady.done( ve.bind( ve.init.mw.Target.onReady, this ) );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -456,6 +481,32 @@ ve.init.mw.Target.onSerializeError = function ( jqXHR, status, error ) {
|
|||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* Add a plugin module or callback.
|
||||
*
|
||||
* @param {string|Function} plugin Plugin module or callback
|
||||
*/
|
||||
ve.init.mw.Target.prototype.addPlugin = function ( plugin ) {
|
||||
if ( typeof plugin === 'string' ) {
|
||||
this.modules.push( plugin );
|
||||
} else if ( $.isFunction( plugin ) ) {
|
||||
this.pluginCallbacks.push( plugin );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add an array of plugins.
|
||||
*
|
||||
* @see #addPlugin
|
||||
* @param {Array} plugins
|
||||
*/
|
||||
ve.init.mw.Target.prototype.addPlugins = function ( plugins ) {
|
||||
var i, len;
|
||||
for ( i = 0, len = plugins.length; i < len; i++ ) {
|
||||
this.addPlugin( plugins[i] );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get HTML to send to Parsoid. This takes a document generated by the converter and
|
||||
* transplants the head tag from the old document into it, as well as the attributes on the
|
||||
|
@ -502,7 +553,11 @@ ve.init.mw.Target.prototype.load = function () {
|
|||
return false;
|
||||
}
|
||||
// Start loading the module immediately
|
||||
mw.loader.load( this.modules );
|
||||
mw.loader.using(
|
||||
// Wait for site and user JS before running plugins
|
||||
this.modules.concat( [ 'site', 'user' ] ),
|
||||
ve.bind( ve.init.mw.Target.onModulesReady, this )
|
||||
);
|
||||
|
||||
data = {
|
||||
'action': 'visualeditor',
|
||||
|
|
Loading…
Reference in a new issue