diff --git a/icon-builder/Gruntfile.js b/icon-builder/Gruntfile.js
new file mode 100644
index 00000000000000..630d50b8c5594b
--- /dev/null
+++ b/icon-builder/Gruntfile.js
@@ -0,0 +1,39 @@
+module.exports = function(grunt) {
+
+ grunt.loadNpmTasks('grunt-mocha-test');
+ grunt.loadNpmTasks('grunt-contrib-watch');
+
+ grunt.initConfig({
+ mochaTest: {
+ test: {
+ options: {
+ reporter: 'spec',
+ clearRequireCache: true
+ },
+ src: ['test/*.js']
+ },
+ },
+
+ watch: {
+ js: {
+ options: {
+ spawn: false,
+ },
+ files: ['build.js', 'test/*.js'],
+ tasks: ['default']
+ }
+ }
+ });
+
+ // On watch events, if the changed file is a test file then configure mochaTest to only
+ // run the tests from that file. Otherwise run all the tests
+ var defaultTestSrc = grunt.config('mochaTest.test.src');
+ grunt.event.on('watch', function(action, filepath) {
+ grunt.config('mochaTest.test.src', defaultTestSrc);
+ if (filepath.match('test/')) {
+ grunt.config('mochaTest.test.src', filepath);
+ }
+ });
+
+ grunt.registerTask('default', 'mochaTest');
+};
diff --git a/icon-builder/build.js b/icon-builder/build.js
index 6af080204f3b45..d89f34ed9b6497 100755
--- a/icon-builder/build.js
+++ b/icon-builder/build.js
@@ -11,85 +11,104 @@
var fs = require('fs');
var path = require('path');
var rimraf = require('rimraf');
-var argv = require('yargs')
- .usage('Build JSX components from SVG\'s.\nUsage: $0')
- .demand('output-dir')
- .describe('output-dir', 'Directory to output jsx components')
- .demand('svg-dir')
- .describe('svg-dir', 'SVG directory')
- .describe('inner-path', '"Reach into" subdirs, since libraries like material-design-icons' +
- ' use arbitrary build directories to organize icons' +
- ' e.g. "action/svg/production/icon_3d_rotation_24px.svg"')
- .describe('file-suffix', 'Filter only files ending with a suffix (pretty much only' +
- ' for material-ui-icons)')
- .options('mui-require', {
- demand: false,
- default: 'absolute',
- describe: 'Load material-ui dependencies (SvgIcon) relatively or absolutely. (absolute|relative). For material-ui distributions, relative, for anything else, you probably want absolute.',
- type: 'string'
- })
- .describe('mui-icons-opts', 'Shortcut to use MUI icons options')
- .boolean('mui-icons-opts')
- .argv;
-
-//Clean old files
-rimraf(argv.outputDir, function() {
+var Mustache = require("mustache");
+var _ = require('lodash');
+
+var svgIconRelativeRequire = "require('../../svg-icon');\n\n"
+ , svgIconAbsoluteRequire = "require('material-ui/lib/svg-icon');\n\n"
+ , defaultRenameFilter = './filters/rename/default'
+ , muiRenameFilter = './filters/rename/material-design-icons';
+
+function parseArgs() {
+ return require('yargs')
+ .usage('Build JSX components from SVG\'s.\nUsage: $0')
+ .demand('output-dir')
+ .describe('output-dir', 'Directory to output jsx components')
+ .demand('svg-dir')
+ .describe('svg-dir', 'SVG directory')
+ .describe('inner-path', '"Reach into" subdirs, since libraries like material-design-icons' +
+ ' use arbitrary build directories to organize icons' +
+ ' e.g. "action/svg/production/icon_3d_rotation_24px.svg"')
+ .describe('file-suffix', 'Filter only files ending with a suffix (pretty much only' +
+ ' for material-ui-icons)')
+ .options('rename-filter', {
+ default: defaultRenameFilter
+ })
+ .options('mui-require', {
+ demand: false,
+ default: 'absolute',
+ describe: 'Load material-ui dependencies (SvgIcon) relatively or absolutely. (absolute|relative). For material-ui distributions, relative, for anything else, you probably want absolute.',
+ type: 'string'
+ })
+ .describe('mui-icons-opts', 'Shortcut to use MUI icons options')
+ .boolean('mui-icons-opts')
+ .argv;
+}
+
+function main(options, cb) {
+ var originalWrite; // todo, add wiston / other logging tool
+ if (options.disable_log) { // disable console.log opt, used for tests.
+ originalWrite = process.stdout.write;
+ process.stdout.write = function() {};
+ }
+
+ rimraf.sync(options.outputDir); // Clean old files
console.log('** Starting Build');
- //Process each folder
- var dirs = fs.readdirSync(argv.svgDir);
- fs.mkdirSync(argv.outputDir);
+ var dirs = fs.readdirSync(options.svgDir);
+
+ var renameFilter = options.renameFilter;
+ if (_.isString(renameFilter)) {
+ renameFilter = require(renameFilter);
+ }
+ if (!_.isFunction(renameFilter)) {
+ throw Error("renameFilter must be a function");
+ }
+
+ fs.mkdirSync(options.outputDir);
+
dirs.forEach(function(dirName) {
- processDir(dirName, argv.svgDir, argv.outputDir, argv.innerPath, argv.fileSuffix, argv.muiRequire)
+ processDir(dirName, options.svgDir, options.outputDir, options.innerPath, options.fileSuffix, renameFilter, options.muiRequire)
});
-});
-function processDir(dirName, svgDir, outputDir, innerPath, fileSuffix, muiRequire) {
+ if (cb) {
+ cb();
+ }
+
+ if (options.disable_log) { // bring back stdout
+ process.stdout.write = originalWrite;
+ }
+}
+
+function processDir(dirName, svgDir, outputDir, innerPath, fileSuffix, renameFilter, muiRequire) {
var newIconDirPath = path.join(outputDir, dirName);
var svgIconDirPath = path.join(svgDir, dirName, innerPath);
if (!fs.existsSync(svgIconDirPath)) { return false; }
if (!fs.lstatSync(svgIconDirPath).isDirectory()) { return false; }
- try {
- var files = fs.readdirSync(svgIconDirPath);
+ var files = fs.readdirSync(svgIconDirPath);
- rimraf(newIconDirPath, function() {
- console.log('\n ' + dirName);
- fs.mkdirSync(newIconDirPath);
+ rimraf.sync(newIconDirPath);
+ console.log('\n ' + dirName);
+ fs.mkdirSync(newIconDirPath);
- files.forEach(function(fileName) {
- processFile(dirName, fileName, newIconDirPath, svgIconDirPath, fileSuffix, muiRequire);
- });
- });
-
- } catch (err) {
- throw (err);
- }
+ files.forEach(function(fileName) {
+ processFile(dirName, fileName, newIconDirPath, svgIconDirPath, fileSuffix, renameFilter, muiRequire);
+ });
}
-function processFile(dirName, fileName, dirPath, svgDirPath, fileSuffix, muiRequire) {
- //Only process 24px files
+function processFile(dirName, fileName, dirPath, svgDirPath, fileSuffix, renameFilter, muiRequire) {
+ var fullPath;
var svgFilePath = svgDirPath + '/' + fileName;
- var newFile;
- if (fileSuffix) {
- if (fileName.indexOf(fileSuffix, fileName.length - fileSuffix.length) !== -1) {
- fileName = fileName.replace(fileSuffix, '.jsx');
- fileName = fileName.slice(3);
- fileName = fileName.replace(/_/g, '-');
- if (fileName.indexOf('3d') === 0) {
- fileName = 'three-d' + fileName.slice(2);
- }
- } else {
- return;
- }
- }
- newFile = path.join(dirPath, fileName);
+
+ fileName = renameFilter(fileName, fileSuffix);
+ if (!fileName) return; // filter can return a falsey to skip
+ fullPath = path.join(dirPath, fileName);
//console.log('writing ' + newFile);
- getJsxString(dirName, fileName, svgFilePath, muiRequire, function(fileString) {
- fs.writeFileSync(newFile, fileString);
- });
+ var fileString = getJsxString(dirName, fileName, svgFilePath, muiRequire);
+ fs.writeFileSync(fullPath, fileString);
}
-function getJsxString(dirName, newFilename, svgFilePath, muiRequire, callback) {
+function getJsxString(dirName, newFilename, svgFilePath, muiRequire, fileString) {
var className = newFilename.replace('.jsx', '');
className = dirName + '-' + className;
className = pascalCase(className);
@@ -98,40 +117,27 @@ function getJsxString(dirName, newFilename, svgFilePath, muiRequire, callback) {
//var parser = new xml2js.Parser();
- fs.readFile(svgFilePath, {encoding: 'utf8'}, function(err, data) {
- if (err) {
- throw err;
- }
- //Extract the paths from the svg string
- var paths = data.slice(data.indexOf('>') + 1);
- paths = paths.slice(0, -6);
- //clean xml paths
- paths = paths.replace('xlink:href="#a"', '');
- paths = paths.replace('xlink:href="#c"', '');
-
- // Node acts wierd if we put this directly into string concatenation
- var muiRequireStmt = muiRequire === "relative" ? "let SvgIcon = require('../../svg-icon');\n\n" : "let SvgIcon = require('material-ui/lib/svg-icon');\n\n";
-
- callback(
- "let React = require('react');\n" +
- muiRequireStmt +
+ var data = fs.readFileSync(svgFilePath, {encoding: 'utf8'});
+ var template = fs.readFileSync(path.join(__dirname, "tpl/SvgIcon.js"), {encoding: 'utf8'});
+ //Extract the paths from the svg string
+ var paths = data.slice(data.indexOf('>') + 1);
+ paths = paths.slice(0, -6);
+ //clean xml paths
+ paths = paths.replace('xlink:href="#a"', '');
+ paths = paths.replace('xlink:href="#c"', '');
- "let " + className + " = React.createClass({\n\n" +
+ // Node acts wierd if we put this directly into string concatenation
- " render() {\n" +
- " return (\n" +
- " \n" +
- " " + paths + "\n" +
- " \n" +
- " );\n" +
- " }\n\n" +
+ var muiRequireStmt = muiRequire === "relative" ? svgIconRelativeRequire : svgIconAbsoluteRequire;
- "});\n\n" +
-
- "module.exports = " + className + ";"
- );
+ return Mustache.render(
+ template, {
+ muiRequireStmt: muiRequireStmt,
+ paths: paths,
+ className: className
+ }
+ );
- });
}
function pascalCase(str) {
@@ -140,3 +146,20 @@ function pascalCase(str) {
return group1.toUpperCase();
});
}
+
+if (require.main === module) {
+ var argv = parseArgs();
+ main(argv);
+}
+
+module.exports = {
+ pascalCase: pascalCase,
+ getJsxString: getJsxString,
+ processDir: processDir,
+ processFile: processFile,
+ main: main,
+ svgIconRelativeRequire: svgIconRelativeRequire,
+ svgIconAbsoluteRequire: svgIconAbsoluteRequire,
+ defaultRenameFilter: defaultRenameFilter,
+ muiRenameFilter: muiRenameFilter
+}
diff --git a/icon-builder/filters/rename/default.js b/icon-builder/filters/rename/default.js
new file mode 100644
index 00000000000000..980264cb14c6c8
--- /dev/null
+++ b/icon-builder/filters/rename/default.js
@@ -0,0 +1,12 @@
+function defaultFilter(fileName, fileSuffix) {
+ if (fileSuffix) {
+ fileName.replace(fileSuffix, ".svg");
+ } else {
+ fileName = fileName.replace('.svg', '.jsx');
+ }
+ fileName = fileName.replace(/_/g, '-');
+ return fileName;
+}
+
+
+module.exports = defaultFilter;
diff --git a/icon-builder/filters/rename/material-design-icons.js b/icon-builder/filters/rename/material-design-icons.js
new file mode 100644
index 00000000000000..a9931c59da600e
--- /dev/null
+++ b/icon-builder/filters/rename/material-design-icons.js
@@ -0,0 +1,14 @@
+function myFilter(fileName, fileSuffix) {
+ if (fileSuffix && fileName.indexOf(fileSuffix, fileName.length - fileSuffix.length) !== -1) {
+ fileName = fileName.replace(fileSuffix, '.jsx');
+ fileName = fileName.slice(3);
+ fileName = fileName.replace(/_/g, '-');
+
+ if (fileName.indexOf('3d') === 0) {
+ fileName = 'three-d' + fileName.slice(2);
+ }
+ return fileName;
+ }
+}
+
+module.exports = myFilter;
diff --git a/icon-builder/package.json b/icon-builder/package.json
index f761fda711fbc8..141dded24f9380 100644
--- a/icon-builder/package.json
+++ b/icon-builder/package.json
@@ -4,7 +4,7 @@
"description": "Material Design Svg Icons converted to React components.",
"scripts": {
"prebuild": "rm -rf js",
- "createMuiIconsJsx": "node build.js --output-dir jsx --svg-dir ./node_modules/material-design-icons --inner-path /svg/production/ --file-suffix _24px.svg --mui-require relative",
+ "createMuiIconsJsx": "node build.js --output-dir jsx --svg-dir ./node_modules/material-design-icons --inner-path /svg/production/ --file-suffix _24px.svg --mui-require relative --renameFilter ./filters/rename/material-design-icons.js",
"build": "npm run createMuiIconsJsx && babel --stage 1 ./jsx --out-dir ./js",
"test": "echo \"Error: no test specified\" && exit 1"
},
@@ -28,7 +28,17 @@
"peerDependencies": {},
"devDependencies": {
"babel": "^5.6.1",
+ "chai": "^3.0.0",
+ "grunt": "^0.4.5",
+ "grunt-contrib-clean": "^0.6.0",
+ "grunt-contrib-watch": "^0.6.1",
+ "grunt-mocha-test": "^0.12.7",
+ "load-grunt-tasks": "^3.2.0",
+ "lodash": "^3.10.0",
"material-design-icons": "^2.0.0",
- "rimraf": "^2.4.0"
+ "mocha": "^2.2.5",
+ "mustache": "^2.1.2",
+ "rimraf": "^2.4.0",
+ "temp": "^0.8.3"
}
}
diff --git a/icon-builder/test/fixtures/game-icons/README.md b/icon-builder/test/fixtures/game-icons/README.md
new file mode 100644
index 00000000000000..34f08b933347ea
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/README.md
@@ -0,0 +1,7 @@
+Game Icons Test Fixtures
+========================
+
+Source: http://game-icons.net/
+Date: July 7, 2015
+License: [CC BY 3.0](http://creativecommons.org/licenses/by/3.0/)
+Extracted from SVG (B/T) set.
diff --git a/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/dice-six-faces-five.svg b/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/dice-six-faces-five.svg
new file mode 100644
index 00000000000000..95b9d74e02963e
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/dice-six-faces-five.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/dice-six-faces-four.svg b/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/dice-six-faces-four.svg
new file mode 100644
index 00000000000000..93f960679a65f8
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/dice-six-faces-four.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/perspective-dice-six-faces-random.svg b/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/perspective-dice-six-faces-random.svg
new file mode 100644
index 00000000000000..0b9b9d2b8217c3
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/perspective-dice-six-faces-random.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/perspective-dice-six-faces-six.svg b/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/perspective-dice-six-faces-six.svg
new file mode 100644
index 00000000000000..cb49a4a6efa442
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/delapouite/dice/svg/000000/transparent/perspective-dice-six-faces-six.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/game-icons/icons/john-colburn/originals/svg/000000/transparent/pistol-gun.svg b/icon-builder/test/fixtures/game-icons/icons/john-colburn/originals/svg/000000/transparent/pistol-gun.svg
new file mode 100644
index 00000000000000..3ebb5df17f6e20
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/john-colburn/originals/svg/000000/transparent/pistol-gun.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/ace.svg b/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/ace.svg
new file mode 100644
index 00000000000000..161eb40574df4f
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/ace.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/acid-blob.svg b/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/acid-blob.svg
new file mode 100644
index 00000000000000..a38418eaa03fde
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/acid-blob.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/acorn.svg b/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/acorn.svg
new file mode 100644
index 00000000000000..b7460cb2ce0ab5
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/acorn.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/alien-skull.svg b/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/alien-skull.svg
new file mode 100644
index 00000000000000..cbf15ed763cd89
--- /dev/null
+++ b/icon-builder/test/fixtures/game-icons/icons/lorc/originals/svg/000000/transparent/alien-skull.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_3d_rotation_24px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_3d_rotation_24px.svg
new file mode 100644
index 00000000000000..db317102ef93cf
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_3d_rotation_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_3d_rotation_48px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_3d_rotation_48px.svg
new file mode 100644
index 00000000000000..6f9d3a42be9634
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_3d_rotation_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_accessibility_24px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_accessibility_24px.svg
new file mode 100644
index 00000000000000..fda62ae6a7cb7b
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_accessibility_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_accessibility_48px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_accessibility_48px.svg
new file mode 100644
index 00000000000000..fee0898b876be1
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_accessibility_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_24px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_24px.svg
new file mode 100644
index 00000000000000..1faddadd515625
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_48px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_48px.svg
new file mode 100644
index 00000000000000..4bbcf36e42cf5a
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_wallet_24px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_wallet_24px.svg
new file mode 100644
index 00000000000000..e71a7654517b14
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_wallet_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_wallet_48px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_wallet_48px.svg
new file mode 100644
index 00000000000000..eb547f4d495799
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_balance_wallet_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_18px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_18px.svg
new file mode 100644
index 00000000000000..7b97842ba11ee2
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_18px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_24px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_24px.svg
new file mode 100644
index 00000000000000..d581147acc01df
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_48px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_48px.svg
new file mode 100644
index 00000000000000..47b1136b2b2b50
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_box_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_18px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_18px.svg
new file mode 100644
index 00000000000000..a5eac61c19756c
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_18px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_24px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_24px.svg
new file mode 100644
index 00000000000000..01dc0621a1262c
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_48px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_48px.svg
new file mode 100644
index 00000000000000..3cfbe0c84f63c2
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_account_circle_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_add_shopping_cart_24px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_add_shopping_cart_24px.svg
new file mode 100644
index 00000000000000..3331ecc706f1ef
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_add_shopping_cart_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_add_shopping_cart_48px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_add_shopping_cart_48px.svg
new file mode 100644
index 00000000000000..86145375e89096
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_add_shopping_cart_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_alarm_24px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_alarm_24px.svg
new file mode 100644
index 00000000000000..edfa7a6a30e84a
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_alarm_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_alarm_48px.svg b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_alarm_48px.svg
new file mode 100644
index 00000000000000..1a5c53978f4400
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/action/svg/production/ic_alarm_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_cake_24px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_cake_24px.svg
new file mode 100644
index 00000000000000..1def9046b4a862
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_cake_24px.svg
@@ -0,0 +1,4 @@
+
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_cake_48px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_cake_48px.svg
new file mode 100644
index 00000000000000..5ee8f5268043ae
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_cake_48px.svg
@@ -0,0 +1,4 @@
+
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_18px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_18px.svg
new file mode 100644
index 00000000000000..22b540aceff98c
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_18px.svg
@@ -0,0 +1,4 @@
+
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_24px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_24px.svg
new file mode 100644
index 00000000000000..378c67e9ff2ffc
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_24px.svg
@@ -0,0 +1,4 @@
+
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_48px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_48px.svg
new file mode 100644
index 00000000000000..7379e710e34256
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/design/ic_domain_48px.svg
@@ -0,0 +1,4 @@
+
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_cake_24px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_cake_24px.svg
new file mode 100644
index 00000000000000..23dc09f5fe90ff
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_cake_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_cake_48px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_cake_48px.svg
new file mode 100644
index 00000000000000..0e21b1193d1782
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_cake_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_18px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_18px.svg
new file mode 100644
index 00000000000000..1090ec609c77c0
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_18px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_24px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_24px.svg
new file mode 100644
index 00000000000000..bfaefa11d318eb
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_48px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_48px.svg
new file mode 100644
index 00000000000000..ca97ee9d2c0b2b
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_domain_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_18px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_18px.svg
new file mode 100644
index 00000000000000..befbf42ce5d473
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_18px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_24px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_24px.svg
new file mode 100644
index 00000000000000..bd9a1335dcd9f4
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_24px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_48px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_48px.svg
new file mode 100644
index 00000000000000..9aadc666b4a4cc
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_48px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_add_18px.svg b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_add_18px.svg
new file mode 100644
index 00000000000000..ddf564c8bd6f0e
--- /dev/null
+++ b/icon-builder/test/fixtures/material-design-icons/social/svg/production/ic_group_add_18px.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/icon-builder/test/index.js b/icon-builder/test/index.js
new file mode 100644
index 00000000000000..8365e28211958e
--- /dev/null
+++ b/icon-builder/test/index.js
@@ -0,0 +1,198 @@
+var assert = require('chai').assert;
+var fs = require('fs');
+var path = require('path');
+
+var temp = require('temp').track();
+var _ = require('lodash');
+
+var DISABLE_LOG = true;
+
+// To cut down on test time, use fixtures instead of node_modules
+// TODO: Make a flag to toggle this.
+var muiIconsDir = path.join(__dirname, './fixtures/material-design-icons/');
+var gameIconsDir = path.join(__dirname, './fixtures/game-icons/icons/');
+// var muiIconsDir = path.join(__dirname, '../node_modules/material-design-icons/');
+
+var builder = require('../build');
+
+describe('material-design-icons', function() {
+ it('should have package installed in node_modules (we will use them to test)', function() {
+ assert.ok(fs.lstatSync(muiIconsDir).isDirectory());
+ });
+});
+
+describe('builder', function() {
+ describe('#pascalCase', function() {
+ it('should have pascalCase', function() {
+ assert.ok(builder.hasOwnProperty('pascalCase'));
+ });
+
+ it('should be a function', function() {
+ assert.isFunction(builder.pascalCase);
+ });
+ });
+
+ describe('#main', function() {
+ it('should have main', function() {
+ assert.ok(builder.hasOwnProperty('main'));
+ });
+
+ it('should be a function', function() {
+ assert.isFunction(builder.main);
+ });
+ });
+
+ describe('#getJsxString', function() {
+ it('should have getJsxString', function() {
+ assert.ok(builder.hasOwnProperty('getJsxString'));
+ });
+
+ it('should be a function', function() {
+ assert.ok(typeof(builder.getJsxString) == "function");
+ });
+ });
+
+ describe('#processDir', function() {
+ it('should have processDir', function() {
+ assert.ok(builder.hasOwnProperty('processDir'));
+ });
+
+ it('should be a function', function() {
+ assert.isFunction(builder.processDir);
+ });
+ });
+
+ describe('#processFile', function() {
+ it('should have processFile', function() {
+ assert.ok(builder.hasOwnProperty('processFile'));
+ });
+
+ it('should be a function', function() {
+ assert.isFunction(builder.processFile);
+ });
+ });
+
+});
+ // renameFilter = require('filter/rename/default');
+ // renameFilter = require('filter/rename/material-design-icons');
+
+describe('--output-dir', function() {
+ var options = {
+ svgDir: muiIconsDir,
+ innerPath: "/svg/production/",
+ fileSuffix: "_24px.svg",
+ renameFilter: builder.muiRenameFilter,
+ disable_log: DISABLE_LOG
+ }, tempPath;
+
+ before(function() {
+ tempPath = temp.mkdirSync();
+ options.outputDir = tempPath;
+ });
+
+ after(function() {
+ temp.cleanupSync();
+ });
+
+ it('script outputs to directory', function(done) {
+ builder.main(options, function() {
+ assert.ok(fs.lstatSync(tempPath).isDirectory());
+ assert.ok(fs.lstatSync(path.join(tempPath, "action")).isDirectory());
+ done();
+ });
+ });
+
+});
+
+describe('--svg-dir, --innerPath, --fileSuffix', function() {
+ var options = {
+ svgDir: gameIconsDir,
+ innerPath: "/dice/svg/000000/transparent/",
+ muiRequire: 'absolute',
+ renameFilter: builder.defaultRenameFilter,
+ disable_log: DISABLE_LOG,
+ }, tempPath, jsxExampleOutputPath;
+
+ before(function() {
+ tempPath = temp.mkdirSync();
+ options.outputDir = tempPath;
+ });
+
+ after(function() {
+ temp.cleanupSync();
+ });
+
+ it('script outputs to directory', function(done) {
+ builder.main(options, function() {
+ assert.ok(fs.lstatSync(tempPath).isDirectory());
+ assert.ok(fs.lstatSync(path.join(tempPath, "delapouite")).isDirectory());
+
+ jsxExampleOutputPath = path.join(tempPath, 'delapouite', 'dice-six-faces-four.jsx');
+ data = fs.readFileSync(jsxExampleOutputPath, {encoding: 'utf8'});
+ assert.include(data, builder.svgIconAbsoluteRequire);
+ done();
+ });
+ });
+
+
+});
+
+describe('--mui-require', function() {
+ var options = {
+ svgDir: muiIconsDir,
+ innerPath: "/svg/production/",
+ fileSuffix: "_24px.svg",
+ disable_log: DISABLE_LOG,
+ renameFilter: builder.muiRenameFilter,
+ }, tempPath, jsxExampleOutputPath;
+
+ before(function() {
+ tempPath = temp.mkdirSync();
+ jsxExampleOutputPath = path.join(tempPath, 'action', 'alarm.jsx');
+ options.outputDir = tempPath;
+ });
+
+ after(function() {
+ temp.cleanupSync();
+ });
+
+ describe('absolute', function() {
+ it('default should be absolute', function(done) {
+ var data;
+ builder.main(options, function() {
+ assert.ok(fs.lstatSync(tempPath).isDirectory());
+ assert.ok(fs.existsSync(jsxExampleOutputPath));
+ data = fs.readFileSync(jsxExampleOutputPath, {encoding: 'utf8'});
+ assert.include(data, builder.svgIconAbsoluteRequire);
+ done();
+ });
+ });
+
+ it('should load SvgIcon as absolute', function(done) {
+ var data;
+ var absoluteOptions = _.extend({}, options, { muiRequire: 'absolute' });
+ builder.main(absoluteOptions, function() {
+ assert.ok(fs.lstatSync(tempPath).isDirectory());
+ assert.ok(fs.existsSync(jsxExampleOutputPath));
+ data = fs.readFileSync(jsxExampleOutputPath, {encoding: 'utf8'});
+ assert.include(data, builder.svgIconAbsoluteRequire);
+ done();
+ });
+ });
+ });
+
+ describe('relative', function() {
+ it('should load SvgIcon as relative', function(done) {
+ var data;
+ var relativeOptions = _.extend({}, options, { muiRequire: 'relative' });
+ builder.main(relativeOptions, function() {
+ assert.ok(fs.lstatSync(tempPath).isDirectory());
+ assert.ok(fs.lstatSync(path.join(tempPath, "action")).isDirectory());
+ assert.ok(fs.existsSync(jsxExampleOutputPath));
+ data = fs.readFileSync(jsxExampleOutputPath, {encoding: 'utf8'});
+ assert.include(data, builder.svgIconRelativeRequire);
+ done();
+ });
+ });
+ });
+})
diff --git a/icon-builder/tpl/SvgIcon.js b/icon-builder/tpl/SvgIcon.js
new file mode 100644
index 00000000000000..d68d693392f89b
--- /dev/null
+++ b/icon-builder/tpl/SvgIcon.js
@@ -0,0 +1,14 @@
+let React = require('react');
+let SvgIcon = {{{ muiRequireStmt }}};
+
+let {{className}} = React.createClass({
+
+ render() {
+ return (
+ {{{paths}}}
+ );
+ }
+
+});
+
+module.exports = {{className}};