From c8ad83310f425433791102e8a958397f2d701b65 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bartosz=20Dziewo=C5=84ski?= Date: Fri, 17 Mar 2017 02:32:59 +0100 Subject: [PATCH] Refactor registration of OOjs UI resource modules includes/resourceloader/ResourceLoaderOOUIModule.php * New trait centralizing some logic for dealing with OOjs UI themes, previously duplicated in OutputPage, ResourcesOOUI.php and ResourceLoaderOOUIImageModule. * Follow-up change I74362f0fc215b26f1f104ce7bdbbac1e106736ad uses this as a base to allow skins/extensions to define new OOjs UI themes. resources/Resources.php resources/ResourcesOOUI.php includes/resourceloader/ResourceLoader.php * OOjs UI resource module definitions are moved back to their rightly place in Resources.php. They are again (almost) normal and static. * Theme-specific logic is now handled by the module code, definitions only specify 'themeScripts'/'themeStyles'/'themeImages'. * ResourcesOOUI.php is deleted and no longer loaded by ResourceLoader. includes/resourceloader/ResourceLoaderOOUIFileModule.php includes/resourceloader/ResourceLoaderOOUIImageModule.php * Glue code previously existing in ResourcesOOUI.php now lives here. * Use the ResourceLoaderOOUIModule trait to avoid code duplication. Change-Id: I39cc2a735d9625c87bf4ede6f5fb0ec441d47dcc --- autoload.php | 2 + docs/extension.schema.v2.json | 3 +- includes/OutputPage.php | 10 +- includes/resourceloader/ResourceLoader.php | 1 - .../ResourceLoaderOOUIFileModule.php | 63 +++++++ .../ResourceLoaderOOUIImageModule.php | 33 +++- .../ResourceLoaderOOUIModule.php | 146 +++++++++++++++ resources/Resources.php | 152 +++++++++++++++- resources/ResourcesOOUI.php | 172 ------------------ 9 files changed, 393 insertions(+), 189 deletions(-) create mode 100644 includes/resourceloader/ResourceLoaderOOUIFileModule.php create mode 100644 includes/resourceloader/ResourceLoaderOOUIModule.php delete mode 100644 resources/ResourcesOOUI.php diff --git a/autoload.php b/autoload.php index 12fe6d10c0..0264435761 100644 --- a/autoload.php +++ b/autoload.php @@ -1221,7 +1221,9 @@ $wgAutoloadLocalClasses = [ 'ResourceLoaderLanguageDataModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLanguageDataModule.php', 'ResourceLoaderLanguageNamesModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLanguageNamesModule.php', 'ResourceLoaderModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderModule.php', + 'ResourceLoaderOOUIFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIFileModule.php', 'ResourceLoaderOOUIImageModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIImageModule.php', + 'ResourceLoaderOOUIModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIModule.php', 'ResourceLoaderRawFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderRawFileModule.php', 'ResourceLoaderSiteModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderSiteModule.php', 'ResourceLoaderSiteStylesModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderSiteStylesModule.php', diff --git a/docs/extension.schema.v2.json b/docs/extension.schema.v2.json index 6345632fcc..518a65c7a8 100644 --- a/docs/extension.schema.v2.json +++ b/docs/extension.schema.v2.json @@ -664,7 +664,8 @@ "description": "Available feeds objects" }, "SkinOOUIThemes": { - "type": "object" + "type": "object", + "description": "Map of skin names to OOjs UI themes to use. Same format as ResourceLoaderOOUIModule::$builtinSkinThemeMap." }, "PasswordPolicy": { "type": "object", diff --git a/includes/OutputPage.php b/includes/OutputPage.php index fe0f0b6356..df948f0cba 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -3952,12 +3952,10 @@ class OutputPage extends ContextSource { * @param String $skinName The Skin name to determine the correct OOUI theme * @param String $dir Language direction */ - public static function setupOOUI( $skinName = '', $dir = 'ltr' ) { - $themes = ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' ); - // Make keys (skin names) lowercase for case-insensitive matching. - $themes = array_change_key_case( $themes, CASE_LOWER ); - $theme = isset( $themes[$skinName] ) ? $themes[$skinName] : 'MediaWiki'; - // For example, 'OOUI\MediaWikiTheme'. + public static function setupOOUI( $skinName = 'default', $dir = 'ltr' ) { + $themes = ResourceLoaderOOUIModule::getSkinThemeMap(); + $theme = isset( $themes[$skinName] ) ? $themes[$skinName] : $themes['default']; + // For example, 'OOUI\WikimediaUITheme'. $themeClass = "OOUI\\{$theme}Theme"; OOUI\Theme::setSingleton( new $themeClass() ); OOUI\Element::setDefaultDir( $dir ); diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php index 0d1284062c..d144987b60 100644 --- a/includes/resourceloader/ResourceLoader.php +++ b/includes/resourceloader/ResourceLoader.php @@ -253,7 +253,6 @@ class ResourceLoader implements LoggerAwareInterface { // Register core modules $this->register( include "$IP/resources/Resources.php" ); - $this->register( include "$IP/resources/ResourcesOOUI.php" ); // Register extension modules $this->register( $config->get( 'ResourceModules' ) ); diff --git a/includes/resourceloader/ResourceLoaderOOUIFileModule.php b/includes/resourceloader/ResourceLoaderOOUIFileModule.php new file mode 100644 index 0000000000..135efa705c --- /dev/null +++ b/includes/resourceloader/ResourceLoaderOOUIFileModule.php @@ -0,0 +1,63 @@ +getSkinSpecific( $options[ 'themeScripts' ], 'scripts' ); + } + if ( isset( $options[ 'themeStyles' ] ) ) { + $options['skinStyles'] = $this->getSkinSpecific( $options[ 'themeStyles' ], 'styles' ); + } + + parent::__construct( $options ); + } + + /** + * Helper function to generate values for 'skinStyles' and 'skinScripts'. + * + * @param string $module Module to generate skinStyles/skinScripts for: + * 'core', 'widgets', 'toolbars', 'windows' + * @param string $which 'scripts' or 'styles' + * @return array + */ + private function getSkinSpecific( $module, $which ) { + $themes = self::getSkinThemeMap(); + + return array_combine( + array_keys( $themes ), + array_map( function ( $theme ) use ( $module, $which ) { + if ( $which === 'scripts' ) { + return $this->getThemeScriptsPath( $theme, $module ); + } else { + return $this->getThemeStylesPath( $theme, $module ); + } + }, array_values( $themes ) ) + ); + } +} diff --git a/includes/resourceloader/ResourceLoaderOOUIImageModule.php b/includes/resourceloader/ResourceLoaderOOUIImageModule.php index 426ba6735f..ee87d8d8e8 100644 --- a/includes/resourceloader/ResourceLoaderOOUIImageModule.php +++ b/includes/resourceloader/ResourceLoaderOOUIImageModule.php @@ -24,24 +24,31 @@ * @since 1.26 */ class ResourceLoaderOOUIImageModule extends ResourceLoaderImageModule { + use ResourceLoaderOOUIModule; + protected function loadFromDefinition() { if ( $this->definition === null ) { // Do nothing if definition was already processed return; } - // Core default themes - $themes = [ 'default' => 'wikimediaui' ]; - $themes += ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' ); + $themes = self::getSkinThemeMap(); - $name = $this->definition['name']; - $rootPath = $this->definition['rootPath']; + // For backwards-compatibility, allow missing 'themeImages' + $module = isset( $this->definition['themeImages'] ) ? $this->definition['themeImages'] : ''; $definition = []; foreach ( $themes as $skin => $theme ) { // Find the path to the JSON file which contains the actual image definitions for this theme - // TODO Allow extensions to specify this path somehow - $dataPath = $rootPath . '/' . strtolower( $theme ) . '/' . $name . '.json'; + if ( $module ) { + $dataPath = $this->getThemeImagesPath( $theme, $module ); + } else { + // Backwards-compatibility for things that probably shouldn't have used this class... + $dataPath = + $this->definition['rootPath'] . '/' . + strtolower( $theme ) . '/' . + $this->definition['name'] . '.json'; + } $localDataPath = $this->localBasePath . '/' . $dataPath; // If there's no file for this module of this theme, that's okay, it will just use the defaults @@ -79,7 +86,7 @@ class ResourceLoaderOOUIImageModule extends ResourceLoaderImageModule { } elseif ( $definition[$key] !== $data[$key] ) { throw new Exception( "Mismatched OOUI theme images definition: " . - "key '$key' of theme '$theme' " . + "key '$key' of theme '$theme' for module '$module' " . "does not match other themes" ); } @@ -88,6 +95,16 @@ class ResourceLoaderOOUIImageModule extends ResourceLoaderImageModule { } } + // Extra selectors to allow using the same icons for old-style MediaWiki UI code + if ( substr( $module, 0, 5 ) === 'icons' ) { + $definition['selectorWithoutVariant'] = '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before'; + $definition['selectorWithVariant'] = ' + .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before, + /* Hack for Flow, see T110051 */ + .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before, + .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before'; + } + // Fields from module definition silently override keys from JSON files $this->definition += $definition; diff --git a/includes/resourceloader/ResourceLoaderOOUIModule.php b/includes/resourceloader/ResourceLoaderOOUIModule.php new file mode 100644 index 0000000000..4228a45f28 --- /dev/null +++ b/includes/resourceloader/ResourceLoaderOOUIModule.php @@ -0,0 +1,146 @@ + 'WikimediaUI', + ]; + + // Note that keys must be TitleCase. + protected static $builtinThemePaths = [ + 'WikimediaUI' => [ + 'scripts' => 'resources/lib/oojs-ui/oojs-ui-wikimediaui.js', + 'styles' => 'resources/lib/oojs-ui/oojs-ui-{module}-wikimediaui.css', + 'images' => 'resources/lib/oojs-ui/themes/wikimediaui/{module}.json', + ], + 'Apex' => [ + 'scripts' => 'resources/lib/oojs-ui/oojs-ui-apex.js', + 'styles' => 'resources/lib/oojs-ui/oojs-ui-{module}-apex.css', + 'images' => 'resources/lib/oojs-ui/themes/apex/{module}.json', + ], + ]; + + /** + * Return a map of skin names (in lowercase) to OOUI theme names, defining which theme a given + * skin should use. + * + * @return array + */ + public static function getSkinThemeMap() { + $themeMap = self::$builtinSkinThemeMap; + $themeMap += ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' ); + return $themeMap; + } + + /** + * Return a map of theme names to lists of paths from which a given theme should be loaded. + * + * Keys are theme names, values are associative arrays. Keys of the inner array are 'scripts', + * 'styles', or 'images', and values are string paths. + * + * Additionally, the string '{module}' in paths represents the name of the module to load. + * + * @return array + */ + protected static function getThemePaths() { + $themePaths = self::$builtinThemePaths; + return $themePaths; + } + + /** + * Return a path to load given module of given theme from. + * + * @param string $theme OOUI theme name, for example 'WikimediaUI' or 'Apex' + * @param string $kind Kind of the module: 'scripts', 'styles', or 'images' + * @param string $module Module name, for valid values see $knownScriptsModules, + * $knownStylesModules, $knownImagesModules + * @return string + */ + protected function getThemePath( $theme, $kind, $module ) { + $paths = self::getThemePaths(); + $path = $paths[ $theme ][ $kind ]; + $path = str_replace( '{module}', $module, $path ); + return $path; + } + + /** + * @param string $theme See getThemePath() + * @param string $module See getThemePath() + * @return string + */ + protected function getThemeScriptsPath( $theme, $module ) { + if ( !in_array( $module, self::$knownScriptsModules ) ) { + throw new InvalidArgumentException( "Invalid OOUI scripts module '$module'" ); + } + return $this->getThemePath( $theme, 'scripts', $module ); + } + + /** + * @param string $theme See getThemePath() + * @param string $module See getThemePath() + * @return string + */ + protected function getThemeStylesPath( $theme, $module ) { + if ( !in_array( $module, self::$knownStylesModules ) ) { + throw new InvalidArgumentException( "Invalid OOUI styles module '$module'" ); + } + return $this->getThemePath( $theme, 'styles', $module ); + } + + /** + * @param string $theme See getThemePath() + * @param string $module See getThemePath() + * @return string + */ + protected function getThemeImagesPath( $theme, $module ) { + if ( !in_array( $module, self::$knownImagesModules ) ) { + throw new InvalidArgumentException( "Invalid OOUI images module '$module'" ); + } + return $this->getThemePath( $theme, 'images', $module ); + } +} diff --git a/resources/Resources.php b/resources/Resources.php index e30196cf6b..7deabf0614 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -2550,5 +2550,155 @@ return [ ], /* OOjs UI */ - // @see ResourcesOOUI.php + + // Omnibus module. + 'oojs-ui' => [ + 'dependencies' => [ + 'oojs-ui-core', + 'oojs-ui-widgets', + 'oojs-ui-toolbars', + 'oojs-ui-windows', + ], + 'targets' => [ 'desktop', 'mobile' ], + ], + + // The core JavaScript library. + 'oojs-ui-core' => [ + 'class' => 'ResourceLoaderOOUIFileModule', + 'scripts' => [ + 'resources/lib/oojs-ui/oojs-ui-core.js', + 'resources/src/oojs-ui-local.js', + ], + 'themeScripts' => 'core', + 'dependencies' => [ + 'oojs', + 'oojs-ui-core.styles', + 'oojs-ui.styles.indicators', + 'oojs-ui.styles.textures', + 'mediawiki.language', + ], + 'targets' => [ 'desktop', 'mobile' ], + ], + // This contains only the styles required by core widgets. + 'oojs-ui-core.styles' => [ + 'class' => 'ResourceLoaderOOUIFileModule', + 'styles' => 'resources/src/oojs-ui-local.css', // HACK, see inside the file + 'themeStyles' => 'core', + 'targets' => [ 'desktop', 'mobile' ], + ], + // Additional widgets and layouts module. + 'oojs-ui-widgets' => [ + 'class' => 'ResourceLoaderOOUIFileModule', + 'scripts' => 'resources/lib/oojs-ui/oojs-ui-widgets.js', + 'themeStyles' => 'widgets', + 'dependencies' => 'oojs-ui-core', + 'messages' => [ + 'ooui-outline-control-move-down', + 'ooui-outline-control-move-up', + 'ooui-outline-control-remove', + 'ooui-selectfile-button-select', + 'ooui-selectfile-dragdrop-placeholder', + 'ooui-selectfile-not-supported', + 'ooui-selectfile-placeholder', + ], + 'targets' => [ 'desktop', 'mobile' ], + ], + // Toolbar and tools module. + 'oojs-ui-toolbars' => [ + 'class' => 'ResourceLoaderOOUIFileModule', + 'scripts' => 'resources/lib/oojs-ui/oojs-ui-toolbars.js', + 'themeStyles' => 'toolbars', + 'dependencies' => 'oojs-ui-core', + 'messages' => [ + 'ooui-toolbar-more', + 'ooui-toolgroup-collapse', + 'ooui-toolgroup-expand', + ], + 'targets' => [ 'desktop', 'mobile' ], + ], + // Windows and dialogs module. + 'oojs-ui-windows' => [ + 'class' => 'ResourceLoaderOOUIFileModule', + 'scripts' => 'resources/lib/oojs-ui/oojs-ui-windows.js', + 'themeStyles' => 'windows', + 'dependencies' => 'oojs-ui-core', + 'messages' => [ + 'ooui-dialog-message-accept', + 'ooui-dialog-message-reject', + 'ooui-dialog-process-continue', + 'ooui-dialog-process-dismiss', + 'ooui-dialog-process-error', + 'ooui-dialog-process-retry', + ], + 'targets' => [ 'desktop', 'mobile' ], + ], + + 'oojs-ui.styles.indicators' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'indicators', + ], + 'oojs-ui.styles.textures' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'textures', + ], + 'oojs-ui.styles.icons-accessibility' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-accessibility', + ], + 'oojs-ui.styles.icons-alerts' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-alerts', + ], + 'oojs-ui.styles.icons-content' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-content', + ], + 'oojs-ui.styles.icons-editing-advanced' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-editing-advanced', + ], + 'oojs-ui.styles.icons-editing-core' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-editing-core', + ], + 'oojs-ui.styles.icons-editing-list' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-editing-list', + ], + 'oojs-ui.styles.icons-editing-styling' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-editing-styling', + ], + 'oojs-ui.styles.icons-interactions' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-interactions', + ], + 'oojs-ui.styles.icons-layout' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-layout', + ], + 'oojs-ui.styles.icons-location' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-location', + ], + 'oojs-ui.styles.icons-media' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-media', + ], + 'oojs-ui.styles.icons-moderation' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-moderation', + ], + 'oojs-ui.styles.icons-movement' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-movement', + ], + 'oojs-ui.styles.icons-user' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-user', + ], + 'oojs-ui.styles.icons-wikimedia' => [ + 'class' => 'ResourceLoaderOOUIImageModule', + 'themeImages' => 'icons-wikimedia', + ], ]; diff --git a/resources/ResourcesOOUI.php b/resources/ResourcesOOUI.php deleted file mode 100644 index c9b5d89c94..0000000000 --- a/resources/ResourcesOOUI.php +++ /dev/null @@ -1,172 +0,0 @@ -getAttribute( 'SkinOOUIThemes' ); - // We only use the theme names for file names, and they are lowercase - $themes = array_map( 'strtolower', $themes ); - $themes['default'] = 'wikimediaui'; - - // Helper function to generate paths to files used in 'skinStyles' and 'skinScripts'. - $getSkinSpecific = function ( $module, $ext = 'css' ) use ( $themes ) { - return array_combine( - array_keys( $themes ), - array_map( function ( $theme ) use ( $module, $ext ) { - $module = $module ? "$module-" : ''; - // TODO Allow extensions to specify this path somehow - return "resources/lib/oojs-ui/oojs-ui-$module$theme.$ext"; - }, array_values( $themes ) ) - ); - }; - - $modules = []; - - // Omnibus module. - $modules['oojs-ui'] = [ - 'dependencies' => [ - 'oojs-ui-core', - 'oojs-ui-widgets', - 'oojs-ui-toolbars', - 'oojs-ui-windows', - ], - 'targets' => [ 'desktop', 'mobile' ], - ]; - - // The core JavaScript library. - $modules['oojs-ui-core'] = [ - 'scripts' => [ - 'resources/lib/oojs-ui/oojs-ui-core.js', - 'resources/src/oojs-ui-local.js', - ], - 'skinScripts' => $getSkinSpecific( null, 'js' ), - 'dependencies' => [ - 'oojs', - 'oojs-ui-core.styles', - 'oojs-ui.styles.indicators', - 'oojs-ui.styles.textures', - 'mediawiki.language', - ], - 'targets' => [ 'desktop', 'mobile' ], - ]; - // This contains only the styles required by core widgets. - $modules['oojs-ui-core.styles'] = [ - 'position' => 'top', - 'styles' => 'resources/src/oojs-ui-local.css', // HACK, see inside the file - 'skinStyles' => $getSkinSpecific( 'core' ), - 'targets' => [ 'desktop', 'mobile' ], - ]; - - // Additional widgets and layouts module. - $modules['oojs-ui-widgets'] = [ - 'scripts' => 'resources/lib/oojs-ui/oojs-ui-widgets.js', - 'skinStyles' => $getSkinSpecific( 'widgets' ), - 'dependencies' => 'oojs-ui-core', - 'messages' => [ - 'ooui-outline-control-move-down', - 'ooui-outline-control-move-up', - 'ooui-outline-control-remove', - 'ooui-selectfile-button-select', - 'ooui-selectfile-dragdrop-placeholder', - 'ooui-selectfile-not-supported', - 'ooui-selectfile-placeholder', - ], - 'targets' => [ 'desktop', 'mobile' ], - ]; - // Toolbar and tools module. - $modules['oojs-ui-toolbars'] = [ - 'scripts' => 'resources/lib/oojs-ui/oojs-ui-toolbars.js', - 'skinStyles' => $getSkinSpecific( 'toolbars' ), - 'dependencies' => 'oojs-ui-core', - 'messages' => [ - 'ooui-toolbar-more', - 'ooui-toolgroup-collapse', - 'ooui-toolgroup-expand', - ], - 'targets' => [ 'desktop', 'mobile' ], - ]; - // Windows and dialogs module. - $modules['oojs-ui-windows'] = [ - 'scripts' => 'resources/lib/oojs-ui/oojs-ui-windows.js', - 'skinStyles' => $getSkinSpecific( 'windows' ), - 'dependencies' => 'oojs-ui-core', - 'messages' => [ - 'ooui-dialog-message-accept', - 'ooui-dialog-message-reject', - 'ooui-dialog-process-continue', - 'ooui-dialog-process-dismiss', - 'ooui-dialog-process-error', - 'ooui-dialog-process-retry', - ], - 'targets' => [ 'desktop', 'mobile' ], - ]; - - $imageSets = [ - // Comments for greppability - 'icons', // oojs-ui.styles.icons - 'indicators', // oojs-ui.styles.indicators - 'textures', // oojs-ui.styles.textures - 'icons-accessibility', // oojs-ui.styles.icons-accessibility - '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 = [ - '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}, .mw-ui-icon-{name}-{variant}:before, - /* Hack for Flow, see T110051 */ - .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; -} ); -- 2.20.1