Skip to content

Commit

Permalink
Add an es2015 module. Don't append Icon to the icons. Enable importin…
Browse files Browse the repository at this point in the history
…g single icons. Add tests.
  • Loading branch information
leMaik committed Aug 6, 2017
1 parent d379667 commit c2e50f5
Show file tree
Hide file tree
Showing 8 changed files with 5,218 additions and 5,137 deletions.
5 changes: 2 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
node_modules
icons
lib
node_modules/
package/
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

37 changes: 25 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Material Design Icons for Material-UI

[![npm](https://img.shields.io/npm/v/mdi-material-ui.svg)](https://www.npmjs.com/package/mdi-material-ui)
[![Material Design Icons version](https://img.shields.io/badge/mdi-v2.0.46-blue.svg)](https://github.com/Templarian/MaterialDesign-SVG/)

Expand All @@ -20,29 +19,43 @@ npm install mdi-material-ui --save
```

## Usage
Every icon is exported with its original name in PascalCase. So `coffee` becomes `Coffee`,
`cloud-print-outline` is exported as `CloudPrintOutline` and so on.

Every icon is exported with its original name in PascalCase, plus _Icon_. So `coffee` becomes `CoffeeIcon`,
`cloud-print-outline` is exported as `CloudPrintOutlineIcon` and so on.
### With tree-shaking
If your environment supports tree-shaking and you are sure that it works fine in your setup, you can simply import the icons as follows:

```js
import { CoffeeIcon } from 'mdi-material-ui'
import { Coffee, Food } from 'mdi-material-ui'
```

// ...
### Without tree-shaking
If your environment doesn't support tree-shaking, you should only import the icons that you actually need in order to ensure that you don't end up bundling _all_ icons.

```js
import Coffee from 'mdi-material-ui/Coffee'
import Food from 'mdi-material-ui/Food'
```

render() {
return (
<div>
Enjoy your coffee! <CoffeeIcon />
</div>
)
If you think that this is far too verbose (I agree!), consider using [babel-plugin-direct-import](https://github.com/umidbekkarimov/babel-plugin-direct-import). Install it and adjust your `.babelrc` by adding the following snippet to the plugins section:

```js
{
// ...
plugins: [
// ...
["direct-import", [{
name: "mdi-material-ui",
indexFile: "mdi-material-ui/index.es"
}]]
]
}
```

## Related projects
Feel more like using a webfont instead of inline svg? We've [got your back][materialdesign-webfont-material-ui]!

## License

The scripts included in this repository are licensed under the WTFPL.
The icons are licensed under the MIT license (see [Material Design Icons](https://github.com/Templarian/MaterialDesign-SVG) and the [NOTICE][] file).

Expand Down
41 changes: 41 additions & 0 deletions __tests__/testIcons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* eslint-env jest */
import React from 'react'
import renderer from 'react-test-renderer'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import * as commonjsIcons from '../package/index'
import * as es2015Icons from '../package/index.es'

console.log('hi')

describe('the generated commonjs module', () => {
it('should export icons that render to SVGs', () => {
for (const iconName of Object.keys(commonjsIcons)) {
const Icon = commonjsIcons[iconName]
const renderedIcon = renderer.create((
<MuiThemeProvider>
<Icon />
</MuiThemeProvider>
)).toJSON()
expect(renderedIcon.type).toBe('svg')
}
})
})

describe('the generated es2015 module', () => {
it('should export icons that render to SVGs', () => {
for (const iconName of Object.keys(es2015Icons)) {
const Icon = es2015Icons[iconName]
const renderedIcon = renderer.create((
<MuiThemeProvider>
<Icon />
</MuiThemeProvider>
)).toJSON()
expect(renderedIcon.type).toBe('svg')
}
})

it('should include the same icons as the CommonJS module', () => {
expect(Object.keys(es2015Icons)).toEqual(expect.arrayContaining(Object.keys(commonjsIcons)))
expect(Object.keys(es2015Icons).length).toBe(Object.keys(commonjsIcons).length)
})
})
67 changes: 51 additions & 16 deletions generate-module.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#!/usr/bin/env node
const fs = require('fs')
const fse = require('fs-extra')
const path = require('path')
const mkdirp = require('mkdirp')
const rimraf = require('rimraf')
const pascalCase = require('pascal-case')
const babel = require('babel-core')
const libxmljs = require('libxmljs')
const pick = require('lodash.pick')

function tryRemoveAttr (element, attributeName, matcher) {
const attribute = element.attr(attributeName)
Expand Down Expand Up @@ -41,7 +40,7 @@ function transformForReact (element) {
const mdiSvgPath = path.join(path.dirname(require.resolve('mdi-svg/meta.json')), 'svg')
const icons = require('mdi-svg/meta.json')
.map((icon) => {
const xml = libxmljs.parseXml(fs.readFileSync(path.join(mdiSvgPath, `${icon.name}.svg`), 'utf8'))
const xml = libxmljs.parseXml(fse.readFileSync(path.join(mdiSvgPath, `${icon.name}.svg`), 'utf8'))
const svg = xml.root().childNodes().map((child) => {
if (child.type() === 'text') return
transformForReact(child)
Expand All @@ -54,22 +53,58 @@ const icons = require('mdi-svg/meta.json')
throw Error(`Unexpected number of paths (${xml.svg.path.length}) for ${icon.name}`)
}
return {
name: `${pascalCase(icon.name)}Icon`,
name: pascalCase(icon.name),
svg
}
})

rimraf.sync(path.join(__dirname, 'lib'))
mkdirp.sync(path.join(__dirname, 'lib'))
fse.removeSync(path.join(__dirname, 'package'))
fse.mkdirpSync(path.join(__dirname, 'package'))

// there is an 'svg' icon, so we can't call the SvgIcon component SvgIcon
const code = `
import React from 'react'
import Icon from 'material-ui/SvgIcon'
${icons.map(({ name, svg }) => `export const ${name} = (props) => <Icon {...props}>${svg}</Icon>`).join('\n')}
for (const { name, svg } of icons) {
const code = `import React from 'react'
import SvgIcon from 'material-ui/SvgIcon'
export default (props) => <SvgIcon {...props}>${svg}</SvgIcon>
`
fs.writeFileSync(path.join(__dirname, 'lib', 'index.js'), babel.transform(code, {
presets: ['es2015', 'react', 'stage-0'],
compact: true

// commonjs module syntax
fse.writeFileSync(path.join(__dirname, 'package', `${name}.js`), babel.transform(code, {
presets: ['es2015', 'react', 'stage-0'],
compact: process.env.NODE_ENV === 'production'
}).code)
}

// es2015 module syntax
const allExports = icons.map(({ name }) => `export { default as ${name} } from './${name}'`).join('\n')
fse.writeFileSync(path.join(__dirname, 'package', 'index.es.js'), allExports)

// commonjs module
fse.writeFileSync(path.join(__dirname, 'package', 'index.js'), babel.transform(allExports, {
plugins: ['transform-es2015-modules-commonjs'],
compact: process.env.NODE_ENV === 'production'
}).code)

// copy other files
;[
'README.md',
'NOTICE',
'LICENSE',
'.npmignore'
].forEach((file) => fse.copySync(path.join(__dirname, file), path.join(__dirname, 'package', file)))

const packageJson = require('./package.json')
fse.writeFileSync(path.join(__dirname, 'package', 'package.json'), JSON.stringify(pick(packageJson, [
'name',
'version',
'description',
'main',
'module',
'jsnext:main',
'repository',
'keywords',
'author',
'license',
'bugs',
'homepage',
'peerDependencies'
])), 'utf-8')
Loading

0 comments on commit c2e50f5

Please sign in to comment.