From: Bartosz DziewoƄski Date: Sun, 24 May 2015 16:56:44 +0000 (+0200) Subject: OOUI theme support X-Git-Tag: 1.31.0-rc.0~11211^2 X-Git-Url: http://git.cyclocoop.org/%22.%24image2.%22?a=commitdiff_plain;h=1fc57830e257f47ae0508899dc35b80674475859;p=lhc%2Fweb%2Fwiklou.git OOUI theme support * Split off OOjs UI's module definitions to a separate file from Resources.php. * Extend ResourceLoaderImageModule to support per-skin images and variants. * Allow skins to specify their preferred OOjs UI theme using new skin registry attribute 'SkinOOUIThemes'. The default remains the 'mediawiki' theme, 'apex' can also be chosen now. * Implement custom ResourceLoaderOOUIImageModule which implements some special sauce required to shoehorn OOjs UI image set definitions into ResourceLoaderImageModule with skin-specific styles support. Bug: T100895 Change-Id: I3fbacbce95126a4cc29221352f3ef846f41e7b1b --- diff --git a/autoload.php b/autoload.php index 8749310318..4da4d89016 100644 --- a/autoload.php +++ b/autoload.php @@ -997,6 +997,7 @@ $wgAutoloadLocalClasses = array( 'ResourceLoaderImage' => __DIR__ . '/includes/resourceloader/ResourceLoaderImage.php', 'ResourceLoaderImageModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderImageModule.php', 'ResourceLoaderJqueryMsgDataModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderJqueryMsgDataModule.php', + 'ResourceLoaderOOUIImageModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIImageModule.php', 'ResourceLoaderLanguageDataModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLanguageDataModule.php', 'ResourceLoaderLanguageNamesModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLanguageNamesModule.php', 'ResourceLoaderModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderModule.php', diff --git a/docs/extension.schema.json b/docs/extension.schema.json index 05f0c45e68..898b11f8dd 100644 --- a/docs/extension.schema.json +++ b/docs/extension.schema.json @@ -611,6 +611,9 @@ "ValidSkinNames": { "type": "object" }, + "SkinOOUIThemes": { + "type": "object" + }, "callback": { "type": [ "array", diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php index b8a0acf14f..5a9465e747 100644 --- a/includes/resourceloader/ResourceLoader.php +++ b/includes/resourceloader/ResourceLoader.php @@ -247,6 +247,7 @@ class ResourceLoader { // Register core modules $this->register( include "$IP/resources/Resources.php" ); + $this->register( include "$IP/resources/ResourcesOOUI.php" ); // Register extension modules Hooks::run( 'ResourceLoaderRegisterModules', array( &$this ) ); $this->register( $config->get( 'ResourceModules' ) ); diff --git a/includes/resourceloader/ResourceLoaderImageModule.php b/includes/resourceloader/ResourceLoaderImageModule.php index eaff4ab403..f695b1118f 100644 --- a/includes/resourceloader/ResourceLoaderImageModule.php +++ b/includes/resourceloader/ResourceLoaderImageModule.php @@ -28,7 +28,7 @@ */ class ResourceLoaderImageModule extends ResourceLoaderModule { - private $definition = null; + protected $definition = null; /** * Local base path, see __construct() @@ -73,21 +73,27 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { * 'selectorWithVariant' => [CSS selector template, variables: {prefix} {name} {variant}], * // List of variants that may be used for the image files * 'variants' => array( + * [theme name] => array( * [variant name] => array( * 'color' => [color string, e.g. '#ffff00'], * 'global' => [boolean, if true, this variant is available * for all images of this type], * ), + * ... + * ), * ... * ), * // List of image files and their options * 'images' => array( + * [theme name] => array( * [file path string], * [file path string] => array( * 'name' => [image name string, defaults to file name], * 'variants' => [array of variant name strings, variants * available for this image], * ), + * ... + * ), * ... * ), * ) @@ -103,7 +109,7 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { /** * Parse definition and external JSON data, if referenced. */ - private function loadFromDefinition() { + protected function loadFromDefinition() { if ( $this->definition === null ) { return; } @@ -151,6 +157,17 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { "Invalid list error. '$option' given, array expected." ); } + if ( !isset( $option['default'] ) ) { + // Backwards compatibility + $option = array( 'default' => $option ); + } + foreach ( $option as $skin => $data ) { + if ( !is_array( $option ) ) { + throw new InvalidArgumentException( + "Invalid list error. '$option' given, array expected." + ); + } + } $this->{$member} = $option; break; @@ -194,9 +211,9 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { * @param string $name Image name * @return ResourceLoaderImage|null */ - public function getImage( $name ) { + public function getImage( $name, ResourceLoaderContext $context ) { $this->loadFromDefinition(); - $images = $this->getImages(); + $images = $this->getImages( $context ); return isset( $images[$name] ) ? $images[$name] : null; } @@ -204,21 +221,29 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { * Get ResourceLoaderImage objects for all images. * @return ResourceLoaderImage[] Array keyed by image name */ - public function getImages() { + public function getImages( ResourceLoaderContext $context ) { + $skin = $context->getSkin(); if ( !isset( $this->imageObjects ) ) { $this->loadFromDefinition(); $this->imageObjects = array(); - - foreach ( $this->images as $name => $options ) { + } + if ( !isset( $this->imageObjects[ $skin ] ) ) { + $this->imageObjects[ $skin ] = array(); + if ( !isset( $this->images[ $skin ] ) ) { + $this->images[ $skin ] = isset( $this->images[ 'default' ] ) ? + $this->images[ 'default' ] : + array(); + } + foreach ( $this->images[ $skin ] as $name => $options ) { $fileDescriptor = is_string( $options ) ? $options : $options['file']; $allowedVariants = array_merge( is_array( $options ) && isset( $options['variants'] ) ? $options['variants'] : array(), - $this->getGlobalVariants() + $this->getGlobalVariants( $context ) ); - if ( isset( $this->variants ) ) { + if ( isset( $this->variants[ $skin ] ) ) { $variantConfig = array_intersect_key( - $this->variants, + $this->variants[ $skin ], array_fill_keys( $allowedVariants, true ) ); } else { @@ -232,11 +257,11 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { $this->localBasePath, $variantConfig ); - $this->imageObjects[ $image->getName() ] = $image; + $this->imageObjects[ $skin ][ $image->getName() ] = $image; } } - return $this->imageObjects; + return $this->imageObjects[ $skin ]; } /** @@ -244,21 +269,27 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { * for every image regardless of image options. * @return string[] */ - public function getGlobalVariants() { + public function getGlobalVariants( ResourceLoaderContext $context ) { + $skin = $context->getSkin(); if ( !isset( $this->globalVariants ) ) { $this->loadFromDefinition(); $this->globalVariants = array(); - - if ( isset( $this->variants ) ) { - foreach ( $this->variants as $name => $config ) { - if ( isset( $config['global'] ) && $config['global'] ) { - $this->globalVariants[] = $name; - } + } + if ( !isset( $this->globalVariants[ $skin ] ) ) { + $this->globalVariants[ $skin ] = array(); + if ( !isset( $this->variants[ $skin ] ) ) { + $this->variants[ $skin ] = isset( $this->variants[ 'default' ] ) ? + $this->variants[ 'default' ] : + array(); + } + foreach ( $this->variants[ $skin ] as $name => $config ) { + if ( isset( $config['global'] ) && $config['global'] ) { + $this->globalVariants[ $skin ][] = $name; } } } - return $this->globalVariants; + return $this->globalVariants[ $skin ]; } /** @@ -273,7 +304,7 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { $script = $context->getResourceLoader()->getLoadScript( $this->getSource() ); $selectors = $this->getSelectors(); - foreach ( $this->getImages() as $name => $image ) { + foreach ( $this->getImages( $context ) as $name => $image ) { $declarations = $this->getCssDeclarations( $image->getDataUri( $context, null, 'original' ), $image->getUrl( $context, $script, null, 'rasterized' ) @@ -371,7 +402,7 @@ class ResourceLoaderImageModule extends ResourceLoaderModule { public function getModifiedTime( ResourceLoaderContext $context ) { $this->loadFromDefinition(); $files = array(); - foreach ( $this->getImages() as $name => $image ) { + foreach ( $this->getImages( $context ) as $name => $image ) { $files[] = $image->getPath( $context ); } diff --git a/includes/resourceloader/ResourceLoaderOOUIImageModule.php b/includes/resourceloader/ResourceLoaderOOUIImageModule.php new file mode 100644 index 0000000000..6d76493a5f --- /dev/null +++ b/includes/resourceloader/ResourceLoaderOOUIImageModule.php @@ -0,0 +1,77 @@ +definition === null ) { + return; + } + + // Core default themes + $themes = array( 'default' => 'mediawiki' ); + $themes += ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' ); + + $name = $this->definition['name']; + $rootPath = $this->definition['rootPath']; + + $definition = array(); + foreach ( $themes as $skin => $theme ) { + // TODO Allow extensions to specify this path somehow + $dataPath = $this->localBasePath . '/' . $rootPath . '/' . $theme . '/' . $name . '.json'; + + if ( file_exists( $dataPath ) ) { + $data = json_decode( file_get_contents( $dataPath ), true ); + array_walk_recursive( $data['images'], function ( &$path ) use ( $rootPath, $theme ) { + // TODO Allow extensions to specify this path somehow + $path = $rootPath . '/' . $theme . '/' . $path; + } ); + } else { + $data = array(); + } + + foreach ( $data as $key => $value ) { + switch ( $key ) { + case 'images': + case 'variants': + $definition[$key][$skin] = $data[$key]; + break; + + default: + if ( !isset( $definition[$key] ) ) { + $definition[$key] = $data[$key]; + } elseif ( $definition[$key] !== $data[$key] ) { + throw new Exception( "Mismatched OOUI theme definitions are not supported: trying to load $key of $theme theme" ); + } + break; + } + } + } + + // Fields from definition silently override keys from JSON files + $this->definition += $definition; + + parent::loadFromDefinition(); + } +} diff --git a/resources/Resources.php b/resources/Resources.php index 58a8f19baf..366352e5c8 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -1775,178 +1775,5 @@ return array( /* OOjs UI */ // WARNING: OOjs-UI is NOT TESTED with older browsers and is likely to break // if loaded in browsers that don't support ES5 - 'oojs-ui' => array( - 'scripts' => array( - 'resources/lib/oojs-ui/oojs-ui.js', - ), - 'skinScripts' => array( - 'default' => 'resources/lib/oojs-ui/oojs-ui-mediawiki.js', - ), - 'dependencies' => array( - 'es5-shim', - 'oojs', - 'oojs-ui.styles', - 'oojs-ui.styles.icons', - 'oojs-ui.styles.indicators', - 'oojs-ui.styles.textures', - ), - 'messages' => array( - 'ooui-dialog-message-accept', - 'ooui-dialog-message-reject', - 'ooui-dialog-process-continue', - 'ooui-dialog-process-dismiss', - 'ooui-dialog-process-error', - 'ooui-dialog-process-retry', - 'ooui-outline-control-move-down', - 'ooui-outline-control-move-up', - 'ooui-outline-control-remove', - 'ooui-toolbar-more', - 'ooui-toolgroup-collapse', - 'ooui-toolgroup-expand', - ), - 'targets' => array( 'desktop', 'mobile' ), - ), - - 'oojs-ui.styles' => array( - 'position' => 'top', - 'styles' => 'resources/src/oojs-ui-local.css', // HACK, see inside the file - 'skinStyles' => array( - 'default' => 'resources/lib/oojs-ui/oojs-ui-mediawiki-noimages.css', - ), - 'targets' => array( 'desktop', 'mobile' ), - ), - - 'oojs-ui.styles.icons' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.indicators' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'indicators.json', - ), - 'oojs-ui.styles.textures' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'textures.json', - ), - 'oojs-ui.styles.icons-alerts' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-alerts.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-content' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-content.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-editing-advanced' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-editing-advanced.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-editing-core' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-editing-core.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-editing-list' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-editing-list.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-editing-styling' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-editing-styling.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-interactions' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-interactions.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-layout' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-layout.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-location' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-location.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-media' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-media.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-moderation' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-moderation.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-movement' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-movement.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-user' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-user.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - 'oojs-ui.styles.icons-wikimedia' => array( - 'position' => 'top', - 'class' => 'ResourceLoaderImageModule', - 'localBasePath' => "$IP/resources/lib/oojs-ui/themes/mediawiki", - 'data' => 'icons-wikimedia.json', - 'selectorWithoutVariant' => '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before', - 'selectorWithVariant' => '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before', - ), - + // @see ResourcesOOUI.php ); diff --git a/resources/ResourcesOOUI.php b/resources/ResourcesOOUI.php new file mode 100644 index 0000000000..37203fb586 --- /dev/null +++ b/resources/ResourcesOOUI.php @@ -0,0 +1,122 @@ + 'mediawiki' ); + $themes += ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' ); + $modules = array(); + + $modules['oojs-ui'] = array( + 'scripts' => array( + 'resources/lib/oojs-ui/oojs-ui.js', + ), + 'skinScripts' => array_combine( + array_keys( $themes ), + array_map( function ( $theme ) { + // TODO Allow extensions to specify this path somehow + return "resources/lib/oojs-ui/oojs-ui-$theme.js"; + }, array_values( $themes ) ) + ), + 'dependencies' => array( + 'es5-shim', + 'oojs', + 'oojs-ui.styles', + 'oojs-ui.styles.icons', + 'oojs-ui.styles.indicators', + 'oojs-ui.styles.textures', + ), + 'messages' => array( + 'ooui-dialog-message-accept', + 'ooui-dialog-message-reject', + 'ooui-dialog-process-continue', + 'ooui-dialog-process-dismiss', + 'ooui-dialog-process-error', + 'ooui-dialog-process-retry', + 'ooui-outline-control-move-down', + 'ooui-outline-control-move-up', + 'ooui-outline-control-remove', + 'ooui-toolbar-more', + 'ooui-toolgroup-collapse', + 'ooui-toolgroup-expand', + ), + 'targets' => array( 'desktop', 'mobile' ), + ); + $modules['oojs-ui.styles'] = array( + 'position' => 'top', + 'styles' => 'resources/src/oojs-ui-local.css', // HACK, see inside the file + 'skinStyles' => array_combine( + array_keys( $themes ), + array_map( function ( $theme ) { + // TODO Allow extensions to specify this path somehow + return "resources/lib/oojs-ui/oojs-ui-$theme-noimages.css"; + }, array_values( $themes ) ) + ), + 'targets' => array( 'desktop', 'mobile' ), + ); + + $imageSets = array( + // Comments for greppability + 'icons', // oojs-ui.styles.icons + 'indicators', // oojs-ui.styles.indicators + 'textures', // oojs-ui.styles.textures + 'icons-alerts', // oojs-ui.styles.icons-alerts + 'icons-content', // oojs-ui.styles.icons-content + 'icons-editing-advanced', // oojs-ui.styles.icons-editing-advanced + 'icons-editing-core', // oojs-ui.styles.icons-editing-core + 'icons-editing-list', // oojs-ui.styles.icons-editing-list + 'icons-editing-styling', // oojs-ui.styles.icons-editing-styling + 'icons-interactions', // oojs-ui.styles.icons-interactions + 'icons-layout', // oojs-ui.styles.icons-layout + 'icons-location', // oojs-ui.styles.icons-location + 'icons-media', // oojs-ui.styles.icons-media + 'icons-moderation', // oojs-ui.styles.icons-moderation + 'icons-movement', // oojs-ui.styles.icons-movement + 'icons-user', // oojs-ui.styles.icons-user + 'icons-wikimedia', // oojs-ui.styles.icons-wikimedia + ); + $rootPath = 'resources/lib/oojs-ui/themes'; + + foreach ( $imageSets as $name ) { + $module = array( + 'position' => 'top', + 'class' => 'ResourceLoaderOOUIImageModule', + 'name' => $name, + 'rootPath' => $rootPath, + ); + + if ( substr( $name, 0, 5 ) === 'icons' ) { + $module['selectorWithoutVariant'] = '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before'; + $module['selectorWithVariant'] = '.oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before'; + } + + $modules[ "oojs-ui.styles.$name" ] = $module; + } + + return $modules; +} );