Bartosz Dziewoński has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/200272

Change subject: Refactor icon handling again
......................................................................

Refactor icon handling again

Objective: To use the same configuration format for JSON files with
  icons definitions as MediaWiki's ResourceLoaderImageModule, in order
  to be able to reuse the definitions there.

* Split the monolithic images.json files for both themes into separate
  file for each image set (or 'type', as we used to call them).
* colorize-svg.js: Added support for a number of new options and
  renamed/removed some other ones to match ResourceLoaderImageModule.
* modules.json: JSON files containing icon definitions can now be
  specified directly.
* Gruntfile.js: 'colorizeSvg' task details are now generated from
  modules.json, like the ones for 'less'.

Changes made in this patch should also let us get rid of the two-step
Less build, but this was not done yet.

Bug: T93669
Change-Id: Icd959166f847560cc40b881a0ff2f62c389e4e3b
---
M Gruntfile.js
D build/images.json
M build/modules.json
M build/tasks/colorize-svg.js
M src/styles/common.less
A src/themes/apex/icons-editing-core.json
A src/themes/apex/icons-moderation.json
A src/themes/apex/icons.json
D src/themes/apex/images.json
D src/themes/apex/images.less
A src/themes/apex/indicators.json
A src/themes/apex/textures.json
D src/themes/blank/images.json
D src/themes/blank/images.less
A src/themes/mediawiki/icons-alerts.json
A src/themes/mediawiki/icons-content.json
A src/themes/mediawiki/icons-editing-advanced.json
A src/themes/mediawiki/icons-editing-core.json
A src/themes/mediawiki/icons-editing-list.json
A src/themes/mediawiki/icons-editing-styling.json
A src/themes/mediawiki/icons-interactions.json
A src/themes/mediawiki/icons-layout.json
A src/themes/mediawiki/icons-location.json
A src/themes/mediawiki/icons-media.json
A src/themes/mediawiki/icons-moderation.json
A src/themes/mediawiki/icons-movement.json
A src/themes/mediawiki/icons-user.json
A src/themes/mediawiki/icons-wikimedia.json
A src/themes/mediawiki/icons.json
D src/themes/mediawiki/images.json
D src/themes/mediawiki/images.less
A src/themes/mediawiki/indicators.json
A src/themes/mediawiki/textures.json
33 files changed, 472 insertions(+), 562 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/72/200272/1

diff --git a/Gruntfile.js b/Gruntfile.js
index 24921ce..574bf60 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -29,6 +29,7 @@
                        vector: {},
                        mixed: {}
                },
+               colorizeSvgFiles = {},
                originalLessFiles = {},
                concatCssFiles = {},
                rtlFiles = {
@@ -37,10 +38,28 @@
                minBanner = '/*! OOjs UI v<%= pkg.version %> | 
http://oojs.mit-license.org */';
 
        ( function () {
-               var distFile, target, module, moduleStyleFiles;
+               var distFile, target, module, moduleStyleFiles,
+                       path = require( 'path' );
                // We compile LESS copied to a different directory
                function fixLessDirectory( fileName ) {
                        return fileName.replace( /^src\//, 'dist/tmp/' );
+               }
+               function processFile( fileName ) {
+                       if ( path.extname( fileName ) === '.json' ) {
+                               var
+                                       theme = path.basename( path.dirname( 
fileName ) ),
+                                       lessFileName = fileName.replace( 
/\.json$/, '.less' );
+                               colorizeSvgFiles[ fileName ] = {
+                                       options: grunt.file.readJSON( fileName 
),
+                                       srcDir: 'src/themes/' + theme,
+                                       destDir: 'dist/tmp/themes/' + theme,
+                                       // This should not be needed, but our 
dist directory structure is weird
+                                       cssPrependPath: 'themes/' + theme + '/',
+                                       destLessFile: path.basename( 
lessFileName )
+                               };
+                               fileName = lessFileName;
+                       }
+                       return fixLessDirectory( fileName );
                }
                for ( module in modules ) {
                        if ( modules[ module ].styles ) {
@@ -48,10 +67,8 @@
                                for ( target in lessFiles ) {
                                        distFile = 'dist/' + module + ( target 
!== 'mixed' ? '.' + target : '' ) + '.css';
 
-                                       if ( !modules[ module ].generated ) {
-                                               originalLessFiles[ distFile ] = 
moduleStyleFiles;
-                                       }
-                                       lessFiles[ target ][ distFile ] = 
moduleStyleFiles.map( fixLessDirectory );
+                                       originalLessFiles[ distFile ] = 
moduleStyleFiles;
+                                       lessFiles[ target ][ distFile ] = 
moduleStyleFiles.map( processFile );
 
                                        // Concat isn't doing much other than 
prepending the banner...
                                        concatCssFiles[ distFile ] = distFile;
@@ -60,29 +77,6 @@
                        }
                }
        }() );
-
-       function merge( target/*, sources...*/ ) {
-               var
-                       sources = Array.prototype.slice.call( arguments, 1 ),
-                       len = sources.length,
-                       i = 0,
-                       source, prop;
-
-               for ( ; i < len; i++ ) {
-                       source = sources[ i ];
-                       if ( source ) {
-                               for ( prop in source ) {
-                                       if ( typeof target[ prop ] === 'object' 
&& target[ prop ] !== null ) {
-                                               target[ prop ] = merge( {}, 
target[ prop ], source[ prop ] );
-                                       } else {
-                                               target[ prop ] = source[ prop ];
-                                       }
-                               }
-                       }
-               }
-
-               return target;
-       }
 
        function strip( str ) {
                var path = require( 'path' );
@@ -243,24 +237,7 @@
                                expand: true
                        }
                },
-               colorizeSvg: {
-                       apex: {
-                               options: merge(
-                                       grunt.file.readJSON( 
'build/images.json' ),
-                                       grunt.file.readJSON( 
'src/themes/apex/images.json' )
-                               ),
-                               srcDir: 'src/themes/apex/images',
-                               destDir: 'dist/tmp/themes/apex/images'
-                       },
-                       mediawiki: {
-                               options: merge(
-                                       grunt.file.readJSON( 
'build/images.json' ),
-                                       grunt.file.readJSON( 
'src/themes/mediawiki/images.json' )
-                               ),
-                               srcDir: 'src/themes/mediawiki/images',
-                               destDir: 'dist/tmp/themes/mediawiki/images'
-                       }
-               },
+               colorizeSvg: colorizeSvgFiles,
                svg2png: {
                        dist: {
                                src: 'dist/{images,themes}/**/*.svg'
diff --git a/build/images.json b/build/images.json
deleted file mode 100644
index e522a14..0000000
--- a/build/images.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-       "css": {
-               "indicators": {
-                       "classPrefix": ".oo-ui-indicator"
-               },
-               "icons": {
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "textures": {
-                       "classPrefix": ".oo-ui-texture"
-               }
-       }
-}
diff --git a/build/modules.json b/build/modules.json
index 3a402ca..bae9bb6 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -107,19 +107,19 @@
                ],
                "styles": [
                        "src/themes/apex/core.less",
-                       "src/themes/apex/images.less"
+                       "src/themes/apex/icons.json",
+                       "src/themes/apex/indicators.json",
+                       "src/themes/apex/textures.json"
                ]
        },
        "oojs-ui-apex-icons-moderation": {
-               "generated": true,
                "styles": [
-                       "src/themes/apex/images/icons/icons-moderation.less"
+                       "src/themes/apex/icons-moderation.json"
                ]
        },
        "oojs-ui-apex-icons-editing-core": {
-               "generated": true,
                "styles": [
-                       "src/themes/apex/images/icons/icons-editing-core.less"
+                       "src/themes/apex/icons-editing-core.json"
                ]
        },
        "oojs-ui-mediawiki": {
@@ -128,91 +128,79 @@
                ],
                "styles": [
                        "src/themes/mediawiki/core.less",
-                       "src/themes/mediawiki/images.less"
+                       "src/themes/mediawiki/icons.json",
+                       "src/themes/mediawiki/indicators.json",
+                       "src/themes/mediawiki/textures.json"
                ]
        },
        "oojs-ui-mediawiki-icons-movement": {
-               "generated": true,
                "styles": [
-                       "src/themes/mediawiki/images/icons/icons-movement.less"
+                       "src/themes/mediawiki/icons-movement.json"
                ]
        },
        "oojs-ui-mediawiki-icons-content": {
-               "generated": true,
                "styles": [
-                       "src/themes/mediawiki/images/icons/icons-content.less"
+                       "src/themes/mediawiki/icons-content.json"
                ]
        },
        "oojs-ui-mediawiki-icons-alerts": {
-               "generated": true,
                "styles": [
-                       "src/themes/mediawiki/images/icons/icons-alerts.less"
+                       "src/themes/mediawiki/icons-alerts.json"
                ]
        },
        "oojs-ui-mediawiki-icons-interactions": {
-               "generated": true,
                "styles": [
-                       
"src/themes/mediawiki/images/icons/icons-interactions.less"
+                       "src/themes/mediawiki/icons-interactions.json"
                ]
        },
        "oojs-ui-mediawiki-icons-moderation": {
-               "generated": true,
                "styles": [
-                       
"src/themes/mediawiki/images/icons/icons-moderation.less"
+                       "src/themes/mediawiki/icons-moderation.json"
                ]
        },
        "oojs-ui-mediawiki-icons-editing-core": {
-               "generated": true,
                "styles": [
-                       
"src/themes/mediawiki/images/icons/icons-editing-core.less"
+                       "src/themes/mediawiki/icons-editing-core.json"
                ]
        },
        "oojs-ui-mediawiki-icons-editing-styling": {
-               "generated": true,
                "styles": [
-                       
"src/themes/mediawiki/images/icons/icons-editing-styling.less"
+                       "src/themes/mediawiki/icons-editing-styling.json"
                ]
        },
        "oojs-ui-mediawiki-icons-editing-list": {
-               "generated": true,
                "styles": [
-                       
"src/themes/mediawiki/images/icons/icons-editing-list.less"
+                       "src/themes/mediawiki/icons-editing-list.json"
                ]
        },
        "oojs-ui-mediawiki-icons-editing-advanced": {
-               "generated": true,
                "styles": [
-                       
"src/themes/mediawiki/images/icons/icons-editing-advanced.less"
+                       "src/themes/mediawiki/icons-editing-advanced.json"
                ]
        },
        "oojs-ui-mediawiki-icons-media": {
-               "generated": true,
                "styles": [
-                       "src/themes/mediawiki/images/icons/icons-media.less"
+                       "src/themes/mediawiki/icons-media.json"
                ]
        },
        "oojs-ui-mediawiki-icons-location": {
-               "generated": true,
                "styles": [
-                       "src/themes/mediawiki/images/icons/icons-location.less"
+                       "src/themes/mediawiki/icons-location.json"
                ]
        },
        "oojs-ui-mediawiki-icons-user": {
-               "generated": true,
                "styles": [
-                       "src/themes/mediawiki/images/icons/icons-user.less"
+                       "src/themes/mediawiki/icons-user.json"
                ]
        },
        "oojs-ui-mediawiki-icons-layout": {
-               "generated": true,
                "styles": [
-                       "src/themes/mediawiki/images/icons/icons-layout.less"
+                       "src/themes/mediawiki/icons-layout.json"
                ]
        },
        "oojs-ui-mediawiki-icons-wikimedia": {
-               "generated": true,
                "styles": [
-                       "src/themes/mediawiki/images/icons/icons-wikimedia.less"
+                       "src/themes/mediawiki/icons-wikimedia.json"
                ]
        }
 }
diff --git a/build/tasks/colorize-svg.js b/build/tasks/colorize-svg.js
index 4148c00..59d6d52 100644
--- a/build/tasks/colorize-svg.js
+++ b/build/tasks/colorize-svg.js
@@ -3,8 +3,6 @@
  *
  * The task currently doesn't use the standard file specifying methods with 
this.filesSrc.
  * An option to do it may be added in the future.
- *
- *
  */
 
 /*jshint node:true */
@@ -20,29 +18,33 @@
                'colorizeSvg',
                'Generate colored variants of SVG images',
                function () {
-                       var originals = 0,
+                       var
                                data = this.data,
                                options = this.options(),
                                source = new Source(
                                        data.srcDir,
                                        options.images,
                                        options.variants,
-                                       options.css
+                                       {
+                                               intro: options.intro,
+                                               prefix: options.prefix,
+                                               cssPrependPath: 
data.cssPrependPath,
+                                               selectorWithoutVariant: 
options.selectorWithoutVariant || options.selector,
+                                               selectorWithVariant: 
options.selectorWithVariant || options.selector
+                                       }
                                ),
-                               imageLists = source.getImageLists();
+                               imageList = source.getImageList(),
+                               originals = imageList.getLength();
 
-                       return Q.all( Object.keys( imageLists ).map( function ( 
type ) {
-                               originals += imageLists[ type ].getLength();
-                               return imageLists[ type ].generate(
-                                       new Destination( path.join( 
data.destDir, imageLists[ type ].css.path || type ), type )
-                               );
-                       } ) ).then( function ( sums ) {
+                       return imageList.generate(
+                               new Destination(
+                                       data.destDir,
+                                       data.destLessFile || 'images.less'
+                               )
+                       ).then( function ( processed ) {
                                grunt.log.writeln(
                                        'Processed ' + originals + ' original 
SVG files into ' +
-                                       sums.reduce( function ( a, b ) {
-                                               return a + b;
-                                       } ) +
-                                       ' additional color variants.'
+                                       processed + ' additional color 
variants.'
                                );
                        } );
                }
@@ -57,15 +59,15 @@
         *
         * @constructor
         * @param {string} path Directory containing source images
-        * @param {Object} images Lists of image configurations, keyed by type
-        * @param {Object} variants List of variant configurations, keyed by 
type and variant name
-        * @param {Object} css List of CSS class configurations, keyed by type
+        * @param {Object} images Lists of image configurations
+        * @param {Object} [variants] List of variant configurations, keyed by 
variant name
+        * @param {Object} [options] Additional options
         */
-       function Source( path, images, variants, css ) {
+       function Source( path, images, variants, options ) {
                this.path = path;
                this.images = images;
-               this.variants = variants;
-               this.css = css;
+               this.variants = variants || {};
+               this.options = options || {};
        }
 
        /**
@@ -78,24 +80,17 @@
        };
 
        /**
-        * Get image lists for each type.
+        * Get image list.
         *
-        * @return {Object.<string,ImageList>} Image lists
+        * @return ImageList Image list
         */
-       Source.prototype.getImageLists = function () {
-               var type,
-                       lists = {};
-
-               for ( type in this.images ) {
-                       lists[ type ] = new ImageList(
-                               path.join( this.path, ( this.css[ type ] || {} 
).path || type ),
-                               new VariantList( this.variants[ type ] || {} ),
-                               this.css[ type ] || {},
-                               this.images[ type ]
-                       );
-               }
-
-               return lists;
+       Source.prototype.getImageList = function () {
+               return new ImageList(
+                       this.path,
+                       new VariantList( this.variants ),
+                       this.options,
+                       this.images
+               );
        };
 
        /**
@@ -105,11 +100,11 @@
         *
         * @constructor
         * @param {string} path Image path
-        * @param {string} [stylesheetName] Stylesheet file name
+        * @param {string} stylesheetName Stylesheet file name
         */
        function Destination( path, stylesheetName ) {
                this.path = path;
-               this.stylesheetName = stylesheetName || path.basename( 
this.path );
+               this.stylesheetName = stylesheetName;
        }
 
        /**
@@ -127,7 +122,7 @@
         * @return {string} Destination path
         */
        Destination.prototype.getStylesheetPath = function () {
-               return path.join( this.path, this.stylesheetName + '.less' );
+               return path.join( this.path, this.stylesheetName );
        };
 
        /**
@@ -165,37 +160,49 @@
                        } );
                }
 
-               var params,
+               // TODO Make configurable
+               function getDeclarations( svg, fallback ) {
+                       return '.oo-ui-background-image-svg2(' +
+                               '\'' + ( cssPrependPath || '' ) + svg + '\', ' +
+                               '\'' + ( cssPrependPath || '' ) + fallback + 
'\'' +
+                               ')';
+               }
+
+               var selector, declarations, destinationFilePath,
                        deferred = Q.defer(),
                        errors = 0,
                        file = this.file,
                        name = this.name,
                        fileExtension = path.extname( file ),
-                       fileExtensionBase = fileExtension.slice( 1 ),
-                       fileNameBase = path.basename( file, fileExtension ),
                        filePath = path.join( this.list.getPath(), file ),
                        // TODO This should be configurable in task config, 
like in CSSJanus
                        flippable = flipPath( filePath ) !== filePath,
-                       variable = fileExtensionBase.toLowerCase() === 'svg',
+                       variable = fileExtension.toLowerCase() === '.svg',
+                       fallbackFile = variable ? file.replace( '.svg', '.png' 
) : file,
                        variants = this.list.getVariants(),
                        cssClassPrefix = this.list.getCssClassPrefix(),
+                       cssSelectors = this.list.getCssSelectors(),
+                       cssPrependPath = this.list.options.cssPrependPath,
                        rules = [],
                        uncolorizableImages = [],
                        unknownVariants = [];
 
                // Original
-               params = [ name, fileNameBase ];
-               if ( !variable ) {
-                       params.push( fileExtensionBase );
-               }
-               grunt.file.copy( filePath, path.join( destination.getPath(), 
file ) );
+               destinationFilePath = path.join( destination.getPath(), file );
+               selector = cssSelectors.selectorWithoutVariant
+                       .replace( /{prefix}/g, cssClassPrefix )
+                       .replace( /{name}/g, name )
+                       .replace( /{variant}/g, '' );
+               declarations = getDeclarations( file, fallbackFile );
+               rules.push( selector + ' {\n\t' + declarations + '\n}' );
+
+               grunt.file.copy( filePath, destinationFilePath );
                if ( flippable ) {
                        grunt.file.copy(
                                flipPath( filePath ),
-                               flipPath( path.join( destination.getPath(), 
file ) )
+                               flipPath( destinationFilePath )
                        );
                }
-               rules.push( cssClassPrefix + '( ' + params.join( ', ' ) + ' );' 
);
 
                // Variants
                if ( variable ) {
@@ -221,12 +228,21 @@
                                        return;
                                }
 
-                               params = [ name, fileNameBase, variantName ];
+                               destinationFilePath = path.join(
+                                       destination.getPath(),
+                                       file.replace( fileExtension, '-' + 
variantName + fileExtension )
+                               );
+                               selector = cssSelectors.selectorWithVariant
+                                       .replace( /{prefix}/g, cssClassPrefix )
+                                       .replace( /{name}/g, name )
+                                       .replace( /{variant}/g, variantName );
+                               declarations = getDeclarations(
+                                       file.replace( fileExtension, '-' + 
variantName + fileExtension ),
+                                       file.replace( fileExtension, '-' + 
variantName + ( variable ? '.png' : fileExtension ) )
+                               );
+
                                grunt.file.write(
-                                       path.join(
-                                               destination.getPath(),
-                                               fileNameBase + '-' + 
variantName + fileExtension
-                                       ),
+                                       destinationFilePath,
                                        variantSvg
                                );
 
@@ -243,15 +259,12 @@
                                        }
 
                                        grunt.file.write(
-                                               flipPath( path.join(
-                                                       destination.getPath(),
-                                                       fileNameBase + '-' + 
variantName + fileExtension
-                                               ) ),
+                                               flipPath( destinationFilePath ),
                                                variantSvg
                                        );
                                        // TODO Report the correct number of 
files processed when flipping
                                }
-                               return cssClassPrefix + '-variant' + '( ' + 
params.join( ', ' ) + ' );';
+                               return selector + ' {\n\t' + declarations + 
'\n}';
                        } ) );
                }
 
@@ -286,16 +299,16 @@
         * @constructor
         * @param {string} path Images path
         * @param {VariantList} variants Variants list
-        * @param {Object} css CSS class configuration
+        * @param {Object} options Additional options
         * @param {Object} data List of image configurations keyed by name
         */
-       function ImageList( path, variants, css, data ) {
+       function ImageList( path, variants, options, data ) {
                var key;
 
                this.list = {};
                this.path = path;
                this.variants = variants;
-               this.css = css;
+               this.options = options;
 
                for ( key in data ) {
                        this.list[ key ] = new Image( this, key, data[ key ] );
@@ -326,7 +339,19 @@
         * @return {string} CSS class prefix
         */
        ImageList.prototype.getCssClassPrefix = function () {
-               return this.css.classPrefix || '';
+               return this.options.prefix || '';
+       };
+
+       /**
+        * Get CSS selectors.
+        *
+        * @return {Object.<string, string>} CSS selectors
+        */
+       ImageList.prototype.getCssSelectors = function () {
+               return {
+                       selectorWithoutVariant: 
this.options.selectorWithoutVariant || '.{prefix}-{name}',
+                       selectorWithVariant: this.options.selectorWithVariant 
|| '.{prefix}-{name}-{variant}'
+               };
        };
 
        /**
@@ -335,7 +360,7 @@
         * @return {string} CSS file intro
         */
        ImageList.prototype.getCssIntro = function () {
-               return this.css.intro || '';
+               return this.options.intro || '';
        };
 
        /**
diff --git a/src/styles/common.less b/src/styles/common.less
index ed1d7be..dc52c7c 100644
--- a/src/styles/common.less
+++ b/src/styles/common.less
@@ -12,63 +12,27 @@
        background-image: e('/* @embed */') url(~'@{url}');
 }
 
-.oo-ui-background-image-svg( @url-without-extension, @fallback-ext: 
@oo-ui-default-image-ext )
-               when ( @oo-ui-distribution = mixed ) {
-       @svg: '@{url-without-extension}.svg';
-       @fallback: '@{url-without-extension}.@{fallback-ext}';
+.oo-ui-background-image-svg2( @svg, @fallback ) when ( @oo-ui-distribution = 
mixed ) {
        background-image: url(@fallback);
        background-image: -webkit-linear-gradient(transparent, transparent), 
e('/* @embed */') url(@svg);
        background-image: linear-gradient(transparent, transparent), e('/* 
@embed */') url(@svg);
        background-image: -o-linear-gradient(transparent, transparent), 
url(@fallback);
 }
-.oo-ui-background-image-svg( @url-without-extension, @fallback-ext: 
@oo-ui-default-image-ext )
-               when ( @oo-ui-distribution = vector ) {
-       .oo-ui-background-image('@{url-without-extension}.svg');
+.oo-ui-background-image-svg2( @svg, @fallback ) when ( @oo-ui-distribution = 
vector ) {
+       .oo-ui-background-image(@svg);
 }
-.oo-ui-background-image-svg( @url-without-extension, @fallback-ext: 
@oo-ui-default-image-ext )
-               when ( @oo-ui-distribution = raster ) {
-       .oo-ui-background-image('@{url-without-extension}.@{fallback-ext}');
+.oo-ui-background-image-svg2( @svg, @fallback ) when ( @oo-ui-distribution = 
raster ) {
+       .oo-ui-background-image(@fallback);
+}
+
+.oo-ui-background-image-svg( @url-without-extension ) {
+       @svg: '@{url-without-extension}.svg';
+       @fallback: '@{url-without-extension}.@{@oo-ui-default-image-ext}';
+       .oo-ui-background-image-svg2(@svg, @fallback);
 }
 
 .oo-ui-force-webkit-gpu() {
        -webkit-transform: translate3d(0, 0, 0);
-}
-
-.oo-ui-image( @type, @name, @file, @ext, @path ) {
-       .oo-ui-@{type}-@{name} {
-               .oo-ui-background-image-svg('@{path}/@{type}s/@{file}', @ext);
-       }
-}
-
-.oo-ui-image-variant( @type, @name, @file, @variant, @ext, @path ) {
-       .oo-ui-image-@{variant} .oo-ui-@{type}-@{name},
-       .oo-ui-image-@{variant}.oo-ui-@{type}-@{name} {
-               
.oo-ui-background-image-svg('@{path}/@{type}s/@{file}-@{variant}', @ext);
-       }
-}
-
-.oo-ui-icon( @name, @file, @ext: @oo-ui-default-image-ext, @path: 
@oo-ui-default-image-path ) {
-       .oo-ui-image( icon, @name, @file, @ext, @path );
-}
-
-.oo-ui-icon-variant( @name, @file, @variant, @ext: @oo-ui-default-image-ext, 
@path: @oo-ui-default-image-path ) {
-       .oo-ui-image-variant( icon, @name, @file, @variant, @ext, @path );
-}
-
-.oo-ui-indicator( @name, @file, @ext: @oo-ui-default-image-ext, @path: 
@oo-ui-default-image-path ) {
-       .oo-ui-image( indicator, @name, @file, @ext, @path );
-}
-
-.oo-ui-indicator-variant( @name, @file, @variant, @ext: 
@oo-ui-default-image-ext, @path: @oo-ui-default-image-path ) {
-       .oo-ui-image-variant( indicator, @name, @file, @variant, @ext, @path );
-}
-
-.oo-ui-texture( @name, @file, @ext: @oo-ui-default-image-ext, @path: 
@oo-ui-default-image-path ) {
-       .oo-ui-image( texture, @name, @file, @ext, @path );
-}
-
-.oo-ui-texture-variant ( @name, @file, @variant, @ext: 
@oo-ui-default-image-ext, @path: @oo-ui-default-image-path ) {
-       .oo-ui-image-variant( texture, @name, @file, @variant, @ext, @path );
 }
 
 .oo-ui-animation( @value1, @value2: X, ... ) {
diff --git a/src/themes/apex/icons-editing-core.json 
b/src/themes/apex/icons-editing-core.json
new file mode 100644
index 0000000..36c0e10
--- /dev/null
+++ b/src/themes/apex/icons-editing-core.json
@@ -0,0 +1,7 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "link": { "file": "images/icons/link.svg" }
+       }
+}
diff --git a/src/themes/apex/icons-moderation.json 
b/src/themes/apex/icons-moderation.json
new file mode 100644
index 0000000..66aeb91
--- /dev/null
+++ b/src/themes/apex/icons-moderation.json
@@ -0,0 +1,7 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "lock": { "file": "images/icons/lock.svg" }
+       }
+}
diff --git a/src/themes/apex/icons.json b/src/themes/apex/icons.json
new file mode 100644
index 0000000..2b99b58
--- /dev/null
+++ b/src/themes/apex/icons.json
@@ -0,0 +1,31 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "circle": { "file": "images/icons/circle.svg" },
+               "add": { "file": "images/icons/add.svg" },
+               "advanced": { "file": "images/icons/advanced.svg" },
+               "alert": { "file": "images/icons/alert.svg" },
+               "check": { "file": "images/icons/check.svg" },
+               "clear": { "file": "images/icons/clear.svg" },
+               "close": { "file": "images/icons/close.svg" },
+               "code": { "file": "images/icons/code.svg" },
+               "collapse": { "file": "images/icons/collapse.svg" },
+               "comment": { "file": "images/icons/comment.svg" },
+               "ellipsis": { "file": "images/icons/ellipsis.svg" },
+               "expand": { "file": "images/icons/expand.svg" },
+               "help": { "file": "images/icons/help.svg" },
+               "info": { "file": "images/icons/info.svg" },
+               "menu": { "file": "images/icons/menu.svg" },
+               "next": { "file": "images/icons/move-ltr.svg" },
+               "picture": { "file": "images/icons/picture.svg" },
+               "previous": { "file": "images/icons/move-rtl.svg" },
+               "redo": { "file": "images/icons/arched-arrow-ltr.svg" },
+               "remove": { "file": "images/icons/remove.svg" },
+               "search": { "file": "images/icons/search.svg" },
+               "settings": { "file": "images/icons/settings.svg" },
+               "tag": { "file": "images/icons/tag.svg" },
+               "undo": { "file": "images/icons/arched-arrow-rtl.svg" },
+               "window": { "file": "images/icons/window.svg" }
+       }
+}
diff --git a/src/themes/apex/images.json b/src/themes/apex/images.json
deleted file mode 100644
index a96ef20..0000000
--- a/src/themes/apex/images.json
+++ /dev/null
@@ -1,62 +0,0 @@
-{
-       "css": {
-               "icons-moderation": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-editing-core": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               }
-       },
-       "variants": {},
-       "images": {
-               "icons": {
-                       "circle": { "file": "circle.svg" },
-                       "add": { "file": "add.svg" },
-                       "advanced": { "file": "advanced.svg" },
-                       "alert": { "file": "alert.svg" },
-                       "check": { "file": "check.svg" },
-                       "clear": { "file": "clear.svg" },
-                       "close": { "file": "close.svg" },
-                       "code": { "file": "code.svg" },
-                       "collapse": { "file": "collapse.svg" },
-                       "comment": { "file": "comment.svg" },
-                       "ellipsis": { "file": "ellipsis.svg" },
-                       "expand": { "file": "expand.svg" },
-                       "help": { "file": "help.svg" },
-                       "info": { "file": "info.svg" },
-                       "menu": { "file": "menu.svg" },
-                       "next": { "file": "move-ltr.svg" },
-                       "picture": { "file": "picture.svg" },
-                       "previous": { "file": "move-rtl.svg" },
-                       "redo": { "file": "arched-arrow-ltr.svg" },
-                       "remove": { "file": "remove.svg" },
-                       "search": { "file": "search.svg" },
-                       "settings": { "file": "settings.svg" },
-                       "tag": { "file": "tag.svg" },
-                       "undo": { "file": "arched-arrow-rtl.svg" },
-                       "window": { "file": "window.svg" }
-               },
-               "indicators": {
-                       "alert": { "file": "alert.svg" },
-                       "up": { "file": "arrow-up.svg" },
-                       "down": { "file": "arrow-down.svg" },
-                       "next": { "file": "arrow-ltr.svg" },
-                       "previous": { "file": "arrow-rtl.svg" },
-                       "required": { "file": "required.svg" }
-               },
-               "textures": {
-                       "pending": { "file": "pending.gif" },
-                       "transparency": { "file": "transparency.svg" }
-               },
-               "icons-editing-core": {
-                       "link": { "file": "link.svg" }
-               },
-               "icons-moderation": {
-                       "lock": { "file": "lock.svg" }
-               }
-       }
-}
diff --git a/src/themes/apex/images.less b/src/themes/apex/images.less
deleted file mode 100644
index a62a5b3..0000000
--- a/src/themes/apex/images.less
+++ /dev/null
@@ -1,6 +0,0 @@
-@import 'common';
-
-// These files are generated from images.json during the build
-@import 'images/icons/icons';
-@import 'images/indicators/indicators';
-@import 'images/textures/textures';
diff --git a/src/themes/apex/indicators.json b/src/themes/apex/indicators.json
new file mode 100644
index 0000000..e21ad03
--- /dev/null
+++ b/src/themes/apex/indicators.json
@@ -0,0 +1,12 @@
+{
+       "prefix": "oo-ui-indicator",
+       "intro": "@import 'common';",
+       "images": {
+               "alert": { "file": "images/indicators/alert.svg" },
+               "up": { "file": "images/indicators/arrow-up.svg" },
+               "down": { "file": "images/indicators/arrow-down.svg" },
+               "next": { "file": "images/indicators/arrow-ltr.svg" },
+               "previous": { "file": "images/indicators/arrow-rtl.svg" },
+               "required": { "file": "images/indicators/required.svg" }
+       }
+}
diff --git a/src/themes/apex/textures.json b/src/themes/apex/textures.json
new file mode 100644
index 0000000..53bc310
--- /dev/null
+++ b/src/themes/apex/textures.json
@@ -0,0 +1,8 @@
+{
+       "prefix": "oo-ui-texture",
+       "intro": "@import 'common';",
+       "images": {
+               "pending": { "file": "images/textures/pending.gif" },
+               "transparency": { "file": "images/textures/transparency.svg" }
+       }
+}
diff --git a/src/themes/blank/images.json b/src/themes/blank/images.json
deleted file mode 100644
index 8b9e284..0000000
--- a/src/themes/blank/images.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-       "variants": {},
-       "images": {
-               "icons": {},
-               "indicators": {},
-               "textures": {}
-       }
-}
diff --git a/src/themes/blank/images.less b/src/themes/blank/images.less
deleted file mode 100644
index a62a5b3..0000000
--- a/src/themes/blank/images.less
+++ /dev/null
@@ -1,6 +0,0 @@
-@import 'common';
-
-// These files are generated from images.json during the build
-@import 'images/icons/icons';
-@import 'images/indicators/indicators';
-@import 'images/textures/textures';
diff --git a/src/themes/mediawiki/icons-alerts.json 
b/src/themes/mediawiki/icons-alerts.json
new file mode 100644
index 0000000..e15f950
--- /dev/null
+++ b/src/themes/mediawiki/icons-alerts.json
@@ -0,0 +1,15 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "bell": { "file": "images/icons/bell.svg" },
+               "bellOn": { "file": "images/icons/bellOn-ltr.svg" },
+               "eye": { "file": "images/icons/eye.svg" },
+               "eyeClosed": { "file": "images/icons/eyeClosed.svg" },
+               "message": { "file": "images/icons/message-ltr.svg" },
+               "signature": { "file": "images/icons/signature-ltr.svg" },
+               "speechBubble": { "file": "images/icons/speechBubble-ltr.svg" },
+               "speechBubbleAdd": { "file": 
"images/icons/speechBubbleAdd-ltr.svg" },
+               "speechBubbles": { "file": "images/icons/speechBubbles-ltr.svg" 
}
+       }
+}
diff --git a/src/themes/mediawiki/icons-content.json 
b/src/themes/mediawiki/icons-content.json
new file mode 100644
index 0000000..59941c9
--- /dev/null
+++ b/src/themes/mediawiki/icons-content.json
@@ -0,0 +1,17 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "article": { "file": "images/icons/article-ltr.svg" },
+               "articleCheck": { "file": "images/icons/articleCheck-ltr.svg" },
+               "articleSearch": { "file": "images/icons/articleSearch-ltr.svg" 
},
+               "book": { "file": "images/icons/book-ltr.svg" },
+               "citeArticle": { "file": "images/icons/citeArticle-ltr.svg" },
+               "die": { "file": "images/icons/die-ltr.svg" },
+               "download": { "file": "images/icons/download-ltr.svg" },
+               "folderPlaceholder": { "file": 
"images/icons/folderPlaceholder-ltr.svg" },
+               "journal": { "file": "images/icons/journal-ltr.svg" },
+               "newspaper": { "file": "images/icons/newspaper-ltr.svg" },
+               "upload": { "file": "images/icons/upload-ltr.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-editing-advanced.json 
b/src/themes/mediawiki/icons-editing-advanced.json
new file mode 100644
index 0000000..d390068
--- /dev/null
+++ b/src/themes/mediawiki/icons-editing-advanced.json
@@ -0,0 +1,16 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "table": { "file": "images/icons/table.svg" },
+               "newline": { "file": "images/icons/newline-ltr.svg" },
+               "redirect": { "file": "images/icons/redirect-ltr.svg" },
+               "noWikiText": { "file": "images/icons/noWikiText-ltr.svg" },
+               "puzzle": { "file": "images/icons/puzzle-ltr.svg" },
+               "quotes": { "file": "images/icons/quotes-ltr.svg" },
+               "quotesAdd": { "file": "images/icons/quotesAdd-ltr.svg" },
+               "templateAdd": { "file": "images/icons/templateAdd-ltr.svg" },
+               "translation": { "file": "images/icons/translation-ltr.svg" },
+               "wikiText": { "file": "images/icons/wikiText.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-editing-core.json 
b/src/themes/mediawiki/icons-editing-core.json
new file mode 100644
index 0000000..6f44b55
--- /dev/null
+++ b/src/themes/mediawiki/icons-editing-core.json
@@ -0,0 +1,10 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "edit": { "file": "images/icons/edit-ltr.svg" },
+               "editLock": { "file": "images/icons/editLock-ltr.svg" },
+               "editUndo": { "file": "images/icons/editUndo-ltr.svg" },
+               "link": { "file": "images/icons/link-ltr.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-editing-list.json 
b/src/themes/mediawiki/icons-editing-list.json
new file mode 100644
index 0000000..cb94213
--- /dev/null
+++ b/src/themes/mediawiki/icons-editing-list.json
@@ -0,0 +1,10 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "indent": { "file": "images/icons/indent-ltr.svg" },
+               "listBullet": { "file": "images/icons/listBullet-ltr.svg" },
+               "listNumbered": { "file": "images/icons/listNumbered-ltr.svg" },
+               "outdent": { "file": "images/icons/outdent-ltr.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-editing-styling.json 
b/src/themes/mediawiki/icons-editing-styling.json
new file mode 100644
index 0000000..6a018ea
--- /dev/null
+++ b/src/themes/mediawiki/icons-editing-styling.json
@@ -0,0 +1,10 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "bigger": { "file": "images/icons/bigger-ltr.svg" },
+               "smaller": { "file": "images/icons/smaller-ltr.svg" },
+               "subscript": { "file": "images/icons/subscript-ltr.svg" },
+               "superscript": { "file": "images/icons/superscript-ltr.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-interactions.json 
b/src/themes/mediawiki/icons-interactions.json
new file mode 100644
index 0000000..028e724
--- /dev/null
+++ b/src/themes/mediawiki/icons-interactions.json
@@ -0,0 +1,23 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "beta": { "file": "images/icons/beta.svg" },
+               "betaLaunch": { "file": "images/icons/betaLaunch.svg" },
+               "bookmark": { "file": "images/icons/bookmark-ltr.svg" },
+               "browser": { "file": "images/icons/browser-ltr.svg" },
+               "clock": { "file": "images/icons/clock.svg" },
+               "closeInput": { "file": "images/icons/closeInput.svg" },
+               "funnel": { "file": "images/icons/funnel-ltr.svg" },
+               "heart": { "file": "images/icons/heart.svg" },
+               "key": { "file": "images/icons/key-ltr.svg" },
+               "keyboard": { "file": "images/icons/keyboard-ltr.svg" },
+               "logOut": { "file": "images/icons/logOut-ltr.svg" },
+               "magnifyingGlass": { "file": 
"images/icons/magnifyingGlass-ltr.svg" },
+               "newWindow": { "file": "images/icons/newWindow-ltr.svg" },
+               "printer": { "file": "images/icons/printer-ltr.svg" },
+               "ribbonPrize": { "file": "images/icons/ribbonPrize.svg" },
+               "sun": { "file": "images/icons/sun-ltr.svg" },
+               "watchlist": { "file": "images/icons/watchlist-ltr.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-layout.json 
b/src/themes/mediawiki/icons-layout.json
new file mode 100644
index 0000000..009c32e
--- /dev/null
+++ b/src/themes/mediawiki/icons-layout.json
@@ -0,0 +1,10 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "stripeFlow": { "file": "images/icons/stripeFlow-ltr.svg" },
+               "stripeSideMenu": { "file": "images/icons/stripeSideMenu.svg" },
+               "stripeSummary": { "file": "images/icons/stripeSummary-ltr.svg" 
},
+               "stripeToC": { "file": "images/icons/stripeToC-ltr.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-location.json 
b/src/themes/mediawiki/icons-location.json
new file mode 100644
index 0000000..5fbd2bb
--- /dev/null
+++ b/src/themes/mediawiki/icons-location.json
@@ -0,0 +1,10 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "map": { "file": "images/icons/map-ltr.svg" },
+               "mapPin": { "file": "images/icons/mapPin.svg" },
+               "mapPinAdd": { "file": "images/icons/mapPinAdd-ltr.svg" },
+               "wikitrail": { "file": "images/icons/wikitrail-ltr.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-media.json 
b/src/themes/mediawiki/icons-media.json
new file mode 100644
index 0000000..7e34004
--- /dev/null
+++ b/src/themes/mediawiki/icons-media.json
@@ -0,0 +1,12 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "image": { "file": "images/icons/image-ltr.svg" },
+               "imageAdd": { "file": "images/icons/imageAdd-ltr.svg" },
+               "imageLock": { "file": "images/icons/imageLock-ltr.svg" },
+               "photoGallery": { "file": "images/icons/photoGallery-ltr.svg" },
+               "play": { "file": "images/icons/play-ltr.svg" },
+               "stop": { "file": "images/icons/stop.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-moderation.json 
b/src/themes/mediawiki/icons-moderation.json
new file mode 100644
index 0000000..b179059
--- /dev/null
+++ b/src/themes/mediawiki/icons-moderation.json
@@ -0,0 +1,16 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "block": { "file": "images/icons/block.svg" },
+               "blockUndo": { "file": "images/icons/blockUndo-ltr.svg" },
+               "flag": { "file": "images/icons/flag-ltr.svg" },
+               "flagUndo": { "file": "images/icons/flagUndo-ltr.svg" },
+               "lock": { "file": "images/icons/lock-ltr.svg" },
+               "star": { "file": "images/icons/star.svg" },
+               "trash": { "file": "images/icons/trash.svg" },
+               "trashUndo": { "file": "images/icons/trashUndo-ltr.svg" },
+               "unLock": { "file": "images/icons/unLock-ltr.svg" },
+               "unStar": { "file": "images/icons/unStar.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-movement.json 
b/src/themes/mediawiki/icons-movement.json
new file mode 100644
index 0000000..970cff8
--- /dev/null
+++ b/src/themes/mediawiki/icons-movement.json
@@ -0,0 +1,15 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "arrowNext": { "file": "images/icons/arrow-ltr.svg" },
+               "arrowLast": { "file": "images/icons/arrow-rtl.svg" },
+               "caretNext": { "file": "images/icons/caret-rtl.svg" },
+               "caretLast": { "file": "images/icons/caret-ltr.svg" },
+               "caretDown": { "file": "images/icons/caretDown.svg" },
+               "caretUp": { "file": "images/icons/caretUp.svg" },
+               "downTriangle": { "file": "images/icons/downTriangle.svg" },
+               "move": { "file": "images/icons/move.svg" },
+               "upTriangle": { "file": "images/icons/upTriangle.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-user.json 
b/src/themes/mediawiki/icons-user.json
new file mode 100644
index 0000000..52f0db2
--- /dev/null
+++ b/src/themes/mediawiki/icons-user.json
@@ -0,0 +1,10 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "userActive": { "file": "images/icons/userActive-ltr.svg" },
+               "userAvatar": { "file": "images/icons/userAvatar.svg" },
+               "userInactive": { "file": "images/icons/userInactive-ltr.svg" },
+               "userTalk": { "file": "images/icons/userTalk-ltr.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons-wikimedia.json 
b/src/themes/mediawiki/icons-wikimedia.json
new file mode 100644
index 0000000..f7831ba
--- /dev/null
+++ b/src/themes/mediawiki/icons-wikimedia.json
@@ -0,0 +1,9 @@
+{
+       "prefix": "oo-ui-icon",
+       "intro": "@import 'common';",
+       "images": {
+               "logoCC": { "file": "images/icons/logo-cc.svg" },
+               "logoWikimediaCommons": { "file": 
"images/icons/logo-wikimediaCommons.svg" },
+               "logoWikipedia": { "file": "images/icons/logo-wikipedia.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/icons.json b/src/themes/mediawiki/icons.json
new file mode 100644
index 0000000..95fb57a
--- /dev/null
+++ b/src/themes/mediawiki/icons.json
@@ -0,0 +1,50 @@
+{
+       "selectorWithoutVariant": ".oo-ui-icon-{name}",
+       "selectorWithVariant": ".oo-ui-image-{variant} .oo-ui-icon-{name}, 
.oo-ui-image-{variant}.oo-ui-icon-{name}",
+       "intro": "@import 'common';",
+       "variants": {
+               "invert": {
+                       "color": "#FFFFFF",
+                       "global": true
+               },
+               "progressive": {
+                       "color": "#347BFF"
+               },
+               "constructive": {
+                       "color": "#00AF89"
+               },
+               "destructive": {
+                       "color": "#D11D13"
+               },
+               "warning": {
+                       "color": "#FF5D00"
+               }
+       },
+       "images": {
+               "add": { "file": "images/icons/add.svg", "variants": [ 
"constructive" ] },
+               "advanced": { "file": "images/icons/advanced.svg" },
+               "alert": { "file": "images/icons/alert.svg", "variants": [ 
"warning" ] },
+               "check": { "file": "images/icons/check.svg", "variants": [ 
"constructive", "progressive" ] },
+               "circle": { "file": "images/icons/circle.svg", "variants": [ 
"constructive" ] },
+               "clear": { "file": "images/icons/clear.svg" },
+               "close": { "file": "images/icons/close-ltr.svg" },
+               "code": { "file": "images/icons/code.svg" },
+               "collapse": { "file": "images/icons/collapse.svg" },
+               "comment": { "file": "images/icons/comment.svg" },
+               "ellipsis": { "file": "images/icons/ellipsis.svg" },
+               "expand": { "file": "images/icons/expand.svg" },
+               "help": { "file": "images/icons/help.svg" },
+               "info": { "file": "images/icons/info.svg" },
+               "menu": { "file": "images/icons/menu.svg" },
+               "next": { "file": "images/icons/move-ltr.svg" },
+               "picture": { "file": "images/icons/picture.svg" },
+               "previous": { "file": "images/icons/move-rtl.svg" },
+               "redo": { "file": "images/icons/arched-arrow-ltr.svg" },
+               "remove": { "file": "images/icons/remove.svg", "variants": [ 
"destructive" ] },
+               "search": { "file": "images/icons/search.svg" },
+               "settings": { "file": "images/icons/settings.svg" },
+               "tag": { "file": "images/icons/tag.svg" },
+               "undo": { "file": "images/icons/arched-arrow-rtl.svg" },
+               "window": { "file": "images/icons/window.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/images.json b/src/themes/mediawiki/images.json
deleted file mode 100644
index 1cdf66e..0000000
--- a/src/themes/mediawiki/images.json
+++ /dev/null
@@ -1,268 +0,0 @@
-{
-       "css": {
-               "icons-movement": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-content": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-alerts": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-interactions": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-moderation": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-editing-core": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-editing-styling": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-editing-list": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-editing-advanced": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-media": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-location": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-user": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-layout": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               },
-               "icons-wikimedia": {
-                       "intro": "@import '../../common';",
-                       "path": "icons",
-                       "classPrefix": ".oo-ui-icon"
-               }
-       },
-       "variants": {
-               "icons": {
-                       "invert": {
-                               "color": "#FFFFFF",
-                               "global": true
-                       },
-                       "progressive": {
-                               "color": "#347BFF"
-                       },
-                       "constructive": {
-                               "color": "#00AF89"
-                       },
-                       "destructive": {
-                               "color": "#D11D13"
-                       },
-                       "warning": {
-                               "color": "#FF5D00"
-                       }
-               },
-               "indicators": {
-                       "invert": {
-                               "color": "#FFFFFF",
-                               "global": true
-                       }
-               }
-       },
-       "images": {
-               "icons": {
-                       "add": { "file": "add.svg", "variants": [ 
"constructive" ] },
-                       "advanced": { "file": "advanced.svg" },
-                       "alert": { "file": "alert.svg", "variants": [ "warning" 
] },
-                       "check": { "file": "check.svg", "variants": [ 
"constructive", "progressive" ] },
-                       "circle": { "file": "circle.svg", "variants": [ 
"constructive" ] },
-                       "clear": { "file": "clear.svg" },
-                       "close": { "file": "close-ltr.svg" },
-                       "code": { "file": "code.svg" },
-                       "collapse": { "file": "collapse.svg" },
-                       "comment": { "file": "comment.svg" },
-                       "ellipsis": { "file": "ellipsis.svg" },
-                       "expand": { "file": "expand.svg" },
-                       "help": { "file": "help.svg" },
-                       "info": { "file": "info.svg" },
-                       "menu": { "file": "menu.svg" },
-                       "next": { "file": "move-ltr.svg" },
-                       "picture": { "file": "picture.svg" },
-                       "previous": { "file": "move-rtl.svg" },
-                       "redo": { "file": "arched-arrow-ltr.svg" },
-                       "remove": { "file": "remove.svg", "variants": [ 
"destructive" ] },
-                       "search": { "file": "search.svg" },
-                       "settings": { "file": "settings.svg" },
-                       "tag": { "file": "tag.svg" },
-                       "undo": { "file": "arched-arrow-rtl.svg" },
-                       "window": { "file": "window.svg" }
-               },
-               "indicators": {
-                       "alert": { "file": "alert.svg" },
-                       "up": { "file": "arrow-up.svg" },
-                       "down": { "file": "arrow-down.svg" },
-                       "next": { "file": "arrow-ltr.svg" },
-                       "previous": { "file": "arrow-rtl.svg" },
-                       "required": { "file": "required.svg" }
-               },
-               "textures": {
-                       "pending": { "file": "pending.gif" },
-                       "transparency": { "file": "transparency.svg" }
-               },
-               "icons-movement": {
-                       "arrowNext": { "file": "arrow-ltr.svg" },
-                       "arrowLast": { "file": "arrow-rtl.svg" },
-                       "caretNext": { "file": "caret-rtl.svg" },
-                       "caretLast": { "file": "caret-ltr.svg" },
-                       "caretDown": { "file": "caretDown.svg" },
-                       "caretUp": { "file": "caretUp.svg" },
-                       "downTriangle": { "file": "downTriangle.svg" },
-                       "move": { "file": "move.svg" },
-                       "upTriangle": { "file": "upTriangle.svg" }
-               },
-               "icons-content": {
-                       "article": { "file": "article-ltr.svg" },
-                       "articleCheck": { "file": "articleCheck-ltr.svg" },
-                       "articleSearch": { "file": "articleSearch-ltr.svg" },
-                       "book": { "file": "book-ltr.svg" },
-                       "citeArticle": { "file": "citeArticle-ltr.svg" },
-                       "die": { "file": "die-ltr.svg" },
-                       "download": { "file": "download-ltr.svg" },
-                       "folderPlaceholder": { "file": 
"folderPlaceholder-ltr.svg" },
-                       "journal": { "file": "journal-ltr.svg" },
-                       "newspaper": { "file": "newspaper-ltr.svg" },
-                       "upload": { "file": "upload-ltr.svg" }
-               },
-               "icons-alerts": {
-                       "bell": { "file": "bell.svg" },
-                       "bellOn": { "file": "bellOn-ltr.svg" },
-                       "eye": { "file": "eye.svg" },
-                       "eyeClosed": { "file": "eyeClosed.svg" },
-                       "message": { "file": "message-ltr.svg" },
-                       "signature": { "file": "signature-ltr.svg" },
-                       "speechBubble": { "file": "speechBubble-ltr.svg" },
-                       "speechBubbleAdd": { "file": "speechBubbleAdd-ltr.svg" 
},
-                       "speechBubbles": { "file": "speechBubbles-ltr.svg" }
-               },
-               "icons-interactions": {
-                       "beta": { "file": "beta.svg" },
-                       "betaLaunch": { "file": "betaLaunch.svg" },
-                       "bookmark": { "file": "bookmark-ltr.svg" },
-                       "browser": { "file": "browser-ltr.svg" },
-                       "clock": { "file": "clock.svg" },
-                       "closeInput": { "file": "closeInput.svg" },
-                       "funnel": { "file": "funnel-ltr.svg" },
-                       "heart": { "file": "heart.svg" },
-                       "key": { "file": "key-ltr.svg" },
-                       "keyboard": { "file": "keyboard-ltr.svg" },
-                       "logOut": { "file": "logOut-ltr.svg" },
-                       "magnifyingGlass": { "file": "magnifyingGlass-ltr.svg" 
},
-                       "newWindow": { "file": "newWindow-ltr.svg" },
-                       "printer": { "file": "printer-ltr.svg" },
-                       "ribbonPrize": { "file": "ribbonPrize.svg" },
-                       "sun": { "file": "sun-ltr.svg" },
-                       "watchlist": { "file": "watchlist-ltr.svg" }
-               },
-               "icons-moderation": {
-                       "block": { "file": "block.svg" },
-                       "blockUndo": { "file": "blockUndo-ltr.svg" },
-                       "flag": { "file": "flag-ltr.svg" },
-                       "flagUndo": { "file": "flagUndo-ltr.svg" },
-                       "lock": { "file": "lock-ltr.svg" },
-                       "star": { "file": "star.svg" },
-                       "trash": { "file": "trash.svg" },
-                       "trashUndo": { "file": "trashUndo-ltr.svg" },
-                       "unLock": { "file": "unLock-ltr.svg" },
-                       "unStar": { "file": "unStar.svg" }
-               },
-               "icons-editing-core": {
-                       "edit": { "file": "edit-ltr.svg" },
-                       "editLock": { "file": "editLock-ltr.svg" },
-                       "editUndo": { "file": "editUndo-ltr.svg" },
-                       "link": { "file": "link-ltr.svg" }
-               },
-               "icons-editing-styling": {
-                       "bigger": { "file": "bigger-ltr.svg" },
-                       "smaller": { "file": "smaller-ltr.svg" },
-                       "subscript": { "file": "subscript-ltr.svg" },
-                       "superscript": { "file": "superscript-ltr.svg" }
-               },
-               "icons-editing-list": {
-                       "indent": { "file": "indent-ltr.svg" },
-                       "listBullet": { "file": "listBullet-ltr.svg" },
-                       "listNumbered": { "file": "listNumbered-ltr.svg" },
-                       "outdent": { "file": "outdent-ltr.svg" }
-               },
-               "icons-editing-advanced": {
-                       "table": { "file": "table.svg" },
-                       "newline": { "file": "newline-ltr.svg" },
-                       "redirect": { "file": "redirect-ltr.svg" },
-                       "noWikiText": { "file": "noWikiText-ltr.svg" },
-                       "puzzle": { "file": "puzzle-ltr.svg" },
-                       "quotes": { "file": "quotes-ltr.svg" },
-                       "quotesAdd": { "file": "quotesAdd-ltr.svg" },
-                       "templateAdd": { "file": "templateAdd-ltr.svg" },
-                       "translation": { "file": "translation-ltr.svg" },
-                       "wikiText": { "file": "wikiText.svg" }
-               },
-               "icons-media": {
-                       "image": { "file": "image-ltr.svg" },
-                       "imageAdd": { "file": "imageAdd-ltr.svg" },
-                       "imageLock": { "file": "imageLock-ltr.svg" },
-                       "photoGallery": { "file": "photoGallery-ltr.svg" },
-                       "play": { "file": "play-ltr.svg" },
-                       "stop": { "file": "stop.svg" }
-               },
-               "icons-location": {
-                       "map": { "file": "map-ltr.svg" },
-                       "mapPin": { "file": "mapPin.svg" },
-                       "mapPinAdd": { "file": "mapPinAdd-ltr.svg" },
-                       "wikitrail": { "file": "wikitrail-ltr.svg" }
-               },
-               "icons-user": {
-                       "userActive": { "file": "userActive-ltr.svg" },
-                       "userAvatar": { "file": "userAvatar.svg" },
-                       "userInactive": { "file": "userInactive-ltr.svg" },
-                       "userTalk": { "file": "userTalk-ltr.svg" }
-               },
-               "icons-layout": {
-                       "stripeFlow": { "file": "stripeFlow-ltr.svg" },
-                       "stripeSideMenu": { "file": "stripeSideMenu.svg" },
-                       "stripeSummary": { "file": "stripeSummary-ltr.svg" },
-                       "stripeToC": { "file": "stripeToC-ltr.svg" }
-               },
-               "icons-wikimedia": {
-                       "logoCC": { "file": "logo-cc.svg" },
-                       "logoWikimediaCommons": { "file": 
"logo-wikimediaCommons.svg" },
-                       "logoWikipedia": { "file": "logo-wikipedia.svg" }
-               }
-       }
-}
diff --git a/src/themes/mediawiki/images.less b/src/themes/mediawiki/images.less
deleted file mode 100644
index a62a5b3..0000000
--- a/src/themes/mediawiki/images.less
+++ /dev/null
@@ -1,6 +0,0 @@
-@import 'common';
-
-// These files are generated from images.json during the build
-@import 'images/icons/icons';
-@import 'images/indicators/indicators';
-@import 'images/textures/textures';
diff --git a/src/themes/mediawiki/indicators.json 
b/src/themes/mediawiki/indicators.json
new file mode 100644
index 0000000..11465ec
--- /dev/null
+++ b/src/themes/mediawiki/indicators.json
@@ -0,0 +1,19 @@
+{
+       "selectorWithoutVariant": ".oo-ui-indicator-{name}",
+       "selectorWithVariant": ".oo-ui-image-{variant} .oo-ui-indicator-{name}, 
.oo-ui-image-{variant}.oo-ui-indicator-{name}",
+       "intro": "@import 'common';",
+       "variants": {
+               "invert": {
+                       "color": "#FFFFFF",
+                       "global": true
+               }
+       },
+       "images": {
+               "alert": { "file": "images/indicators/alert.svg" },
+               "up": { "file": "images/indicators/arrow-up.svg" },
+               "down": { "file": "images/indicators/arrow-down.svg" },
+               "next": { "file": "images/indicators/arrow-ltr.svg" },
+               "previous": { "file": "images/indicators/arrow-rtl.svg" },
+               "required": { "file": "images/indicators/required.svg" }
+       }
+}
diff --git a/src/themes/mediawiki/textures.json 
b/src/themes/mediawiki/textures.json
new file mode 100644
index 0000000..53bc310
--- /dev/null
+++ b/src/themes/mediawiki/textures.json
@@ -0,0 +1,8 @@
+{
+       "prefix": "oo-ui-texture",
+       "intro": "@import 'common';",
+       "images": {
+               "pending": { "file": "images/textures/pending.gif" },
+               "transparency": { "file": "images/textures/transparency.svg" }
+       }
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/200272
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Icd959166f847560cc40b881a0ff2f62c389e4e3b
Gerrit-PatchSet: 1
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Bartosz Dziewoński <matma....@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to