Skip to content

Commit

Permalink
Merge pull request #6 from TheTekton/style-parse
Browse files Browse the repository at this point in the history
Add svg style support.
  • Loading branch information
maximalism2 authored Jun 14, 2017
2 parents 9f204e1 + bcf8668 commit 4d84351
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 16 deletions.
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,27 @@ npm install -g msvgc
msvgc -f ./path/to/pic.svg -o ./svgComponents/
```

`--react-native` flag create components using [react-native-svg](https://github.com/react-native-community/react-native-svg) library
`--camelCase` flag creates components with camel-case class names

`--typescript` flag will using react importing like in typescript (`import * as React`)
`--react-native` flag creates components using [react-native-svg](https://github.com/react-native-community/react-native-svg) library

<br />
Then use generated components in your jsx/tsx files:
`--color` flag creates react-native components with color props passed to the svg children's fill prop

`--typescript` flag will use typescript import statements e.g. (`import * as React`)

`--coffeescript` flag will use CoffeeScript CJSX syntax for creating components

**Notes:**

If default params are not set, the current working
directory will be used as the path to .svg files with output in the ./svg directory.

Subdirectories containing .svg files will generate their corresponding react components within a subdirectory in the output path.

The output path contains an index.js that exports all generated components.

### React JS:
Use generated components in your jsx/tsx/cjsx files:

```js
[...]
Expand All @@ -41,5 +56,6 @@ class MyComponent extends Component {
```

#### TODO:
- [ ] do creating index file in components directory for exporting created files
- [ ] do comparating with existing files in target component directory
- [x] Create index file in target component directory.
- [ ] Provide warning when duplicate component names exist in the index.
- [ ] Compare existing files in target component directory.
5 changes: 5 additions & 0 deletions lib/generateConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const defaultConfig = {
typescript: false,
coffeescript: false,
camelCase: false,
color: false,
fileExt: undefined
}

Expand Down Expand Up @@ -52,6 +53,10 @@ module.exports = argv => {
config.camelCase = true
break
}
case '--color': {
config.color = true
break
}
default: {
log.any('Warn', 'Unknown option', argument)
}
Expand Down
14 changes: 8 additions & 6 deletions lib/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ Usage:
msvgc -f <pathToFiles> -o <targetPath>
If default params are not setted, there will be used files from current
directory, create output folder also in current directory.
If default params are not set, the current working
directory will be used as the path to .svg files with output in the ./svg directory
msvgc --react-native prepare output files to use SVG library for react-native
msvgc --camelCase create components with camel-case class names
msvgc --react-native create react svg components using react-native-svg library
https://github.com/react-native-community/react-native-svg
msvgc --typescript prepare output files to using with TypeScript
msvgc --color create react-native components with color props passed to the svg children's fill prop
msvgc --coffeescript prepare output files to using with CoffeeScript
msvgc --typescript prepare output files using TypeScript syntax
msvgc --camelCase prepare class names using camel-case
msvgc --coffeescript prepare output files using CoffeeScript syntax
`

exports.show = () => console.log(helpMessage)
101 changes: 97 additions & 4 deletions lib/renderMarkup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
const Parser = require('xmldom').DOMParser
const { pd } = require('pretty-data')
const indentString = require('indent-string')
const css = require('css')
const { pathProps } = require('./react-native-svg/props')
const camelCase = require('camelcase')

const validKeys = Object.keys(pathProps)

const enabledTags = [
'svg',
Expand All @@ -18,10 +23,12 @@ const enabledTags = [
'text',
'use',
'defs',
'stop'
'stop',
'style'
]

let usedTags = new Set()
let cssRules = []

function map (context, callback) {
return [].map.call(context, callback)
Expand Down Expand Up @@ -56,13 +63,94 @@ function iterateMarkup (markup, config, i = 0) {
name: 'viewBox',
value: viewBox ? `\"${viewBox.join(' ')}\"` : '0 0 50 50'
})
} else if (tagName === 'style') {
const cssAST = css.parse(markup.firstChild.data)
cssRules = cssAST.stylesheet.rules
return ''
} else {
let cssProps = []
let className
// Find classes and match attributes from rule declarations
forEach(markup.attributes, attr => {
if (attr.name === 'class') {
className = '.' + attr.value
const rules = filter(cssRules, rule => {
if (rule.selectors.indexOf(className) > -1) {
return true
} else {
return false
}
})
forEach(rules, rule => {
forEach(rule.declarations, declaration => {
const propertyName = camelCase(declaration.property)

if (config.reactNative) {
// Compare against whitelist/proptypes from react-native-svg props in validKeys
if (validKeys.indexOf(propertyName) > -1) {
// Since Svg doesn't support a color style...
let propertyValue
if (config.color && propertyName === 'fill') {
propertyValue = `{props.color || "${declaration.value}"}`
} else {
propertyValue = `\"${declaration.value}\"`
}
attrs.push({
name: propertyName,
value: propertyValue
})
cssProps.push(propertyName)
}
} else {
attrs.push({
name: propertyName,
value: `\"${declaration.value}\"`
})
cssProps.push(propertyName)
}
})
})
}
})
forEach(markup.attributes, attr => {
const propertyName = camelCase(attr.name)

if (propertyName === 'class') {
return
}

if (cssProps.indexOf(propertyName) > -1) {
return
}

let propertyValue
if (config.color && propertyName === 'fill') {
propertyValue = `{props.color || "${attr.value}"}`
} else {
propertyValue = `\"${attr.value}\"`
}

attrs.push({
name: attr.name,
value: `\"${attr.value}\"`
name: propertyName,
value: propertyValue
})
})

if (config.reactNative && config.color) {
let fillAttr = filter(attrs, attr => {
if (attr.name === 'fill') {
return true
} else {
return false
}
})
if (fillAttr.length === 0) {
attrs.push({
name: 'fill',
value: '{props.color || undefined}'
})
}
}
}

if (config.reactNative) {
Expand All @@ -80,7 +168,12 @@ function iterateMarkup (markup, config, i = 0) {
return iterateMarkup(child, config, ++i)
}).join('\n') : ''

const tag = `<${tagName} ${map(attrs, attr => `${attr.name}=${attr.value}`).join(' ')}>${children}</${tagName}>`
let tag
if (tagName === 'Svg' || tagName === 'Svg.Svg') {
tag = `<${tagName} {...props} ${map(attrs, attr => `${attr.name}=${attr.value}`).join(' ')}>${children}</${tagName}>`
} else {
tag = `<${tagName} ${map(attrs, attr => `${attr.name}=${attr.value}`).join(' ')}>${children}</${tagName}>`
}

return tag
}
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
"dependencies": {
"camelcase": "^4.1.0",
"colors": "^1.1.2",
"css": "^2.2.1",
"fs-extra": "^3.0.1",
"indent-string": "^3.1.0",
"pretty-data": "^0.40.0",
"prop-types": "^15.5.10",
"svgo": "^0.7.1",
"xmldom": "^0.1.22"
},
Expand Down

0 comments on commit 4d84351

Please sign in to comment.