Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ref option for svgr #29

Merged
merged 3 commits into from
Dec 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Options:
--template <file> specify a custom template to use
--no-expand-props disable props expanding (default: true)
--ids keep ids within the svg
--ref add svgRef prop to svg
--icon use "1em" as width and height
--no-view-box remove viewBox (default: true)
--native add react-native support with react-native-svg
Expand Down Expand Up @@ -167,10 +168,23 @@ $ svgr --template path/to/template.js my-icon.svg
**Example of template:**

```js
module.exports = (opts = {}) => (code, state) => `import React from 'react'
const ${state.componentName} = (${opts.expandProps ? 'props' : ''}) => ${code}
export default ${state.componentName}
`
export default (opts = {}) => {
let props = ''

if (opts.expandProps && opts.ref) {
props = '{svgRef, ...props}'
} else if (opts.expandProps) {
props = 'props'
} else if (opts.ref) {
props = '{svgRef}'
}

return (code, state) => `import React from 'react'

const ${state.componentName} = (${props}) => ${code}

export default ${state.componentName}`
}
```

## Node API usage
Expand Down Expand Up @@ -319,6 +333,14 @@ using CSS or third party library (eg:
| ------- | ------------ | ------------- |
| `false` | `--ids` | `ids: <bool>` |

### Ref

Setting this to `true` will allow you to hook into the ref of the svg components that are created by exposing a `svgRef` prop

| Default | CLI Override | API Override |
| ------- | ------------ | ------------- |
| `false` | `--ref` | `ref: <bool>` |

### Replace attribute value

Replace an attribute value by an other. The main usage of this option is to
Expand Down
30 changes: 30 additions & 0 deletions src/cli/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,36 @@ export default One;
"
`;

exports[`cli --ref --no-expand-props 1`] = `
"import React from \\"react\\";

const One = ({ svgRef }) => (
<svg width={48} height={1} viewBox=\\"0 0 48 1\\" ref={svgRef}>
<title>Rectangle 5</title>
<path d=\\"M0 0h48v1H0z\\" fill=\\"#063855\\" fillRule=\\"evenodd\\" />
</svg>
);

export default One;

"
`;

exports[`cli --ref 1`] = `
"import React from \\"react\\";

const One = ({ svgRef, ...props }) => (
<svg width={48} height={1} viewBox=\\"0 0 48 1\\" ref={svgRef} {...props}>
<title>Rectangle 5</title>
<path d=\\"M0 0h48v1H0z\\" fill=\\"#063855\\" fillRule=\\"evenodd\\" />
</svg>
);

export default One;

"
`;

exports[`cli --replace-attr-value 1`] = `
"import React from \\"react\\";

Expand Down
1 change: 1 addition & 0 deletions src/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ program
.option('--template <file>', 'specify a custom template to use')
.option('--no-expand-props', 'disable props expanding')
.option('--ids', 'keep ids within the svg')
.option('--ref', 'add svgRef prop to svg')
.option('--icon', 'use "1em" as width and height')
.option('--no-view-box', 'remove viewBox')
.option('--native', 'add react-native support with react-native-svg')
Expand Down
40 changes: 18 additions & 22 deletions src/cli/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,12 @@ describe('cli', () => {
})

it('--no-svgo', async () => {
const [stdout] = await exec(
'bin/svgr --no-svgo __fixtures__/one.svg',
)
const [stdout] = await exec('bin/svgr --no-svgo __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

it('--no-prettier', async () => {
const [stdout] = await exec(
'bin/svgr --no-prettier __fixtures__/one.svg',
)
const [stdout] = await exec('bin/svgr --no-prettier __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

Expand All @@ -34,8 +30,18 @@ describe('cli', () => {
})

it('--icon', async () => {
const [stdout] = await exec('bin/svgr --icon __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

it('--ref', async () => {
const [stdout] = await exec('bin/svgr --ref __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

it('--ref --no-expand-props', async () => {
const [stdout] = await exec(
'bin/svgr --icon __fixtures__/one.svg',
'bin/svgr --ref --no-expand-props __fixtures__/one.svg',
)
expect(stdout).toMatchSnapshot()
})
Expand All @@ -46,9 +52,7 @@ describe('cli', () => {
})

it('--no-view-box', async () => {
const [stdout] = await exec(
'bin/svgr --no-view-box __fixtures__/one.svg',
)
const [stdout] = await exec('bin/svgr --no-view-box __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

Expand All @@ -60,23 +64,17 @@ describe('cli', () => {
})

it('--precision', async () => {
const [stdout] = await exec(
'bin/svgr --precision 1 __fixtures__/one.svg',
)
const [stdout] = await exec('bin/svgr --precision 1 __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

it('--no-title', async () => {
const [stdout] = await exec(
'bin/svgr --no-title __fixtures__/one.svg',
)
const [stdout] = await exec('bin/svgr --no-title __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

it('--no-semi', async () => {
const [stdout] = await exec(
'bin/svgr --no-semi __fixtures__/one.svg',
)
const [stdout] = await exec('bin/svgr --no-semi __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

Expand All @@ -88,9 +86,7 @@ describe('cli', () => {
})

it('--native', async () => {
const [stdout] = await exec(
'bin/svgr --native __fixtures__/one.svg',
)
const [stdout] = await exec('bin/svgr --native __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})

Expand Down
3 changes: 3 additions & 0 deletions src/configToOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import wrapIntoNativeComponent from './transforms/wrapIntoNativeComponent'
import stripAttribute from './h2x/stripAttribute'
import emSize from './h2x/emSize'
import expandProps from './h2x/expandProps'
import svgRef from './h2x/svgRef'
import replaceAttrValue from './h2x/replaceAttrValue'
import removeComments from './h2x/removeComments'
import removeStyle from './h2x/removeStyle'
import toReactNative from './h2x/toReactNative'

const defaultConfig = {
ref: false,
svgo: true,
prettier: true,
native: false,
Expand Down Expand Up @@ -41,6 +43,7 @@ function configToOptions(config = {}) {
config.replaceAttrValues.forEach(([oldValue, newValue]) => {
plugins.push(replaceAttrValue(oldValue, newValue))
})
if (config.ref) plugins.push(svgRef)
if (config.expandProps) plugins.push(expandProps)
if (config.native) plugins.push(toReactNative)

Expand Down
23 changes: 23 additions & 0 deletions src/h2x/svgRef.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { JSXAttribute } from 'h2x-plugin-jsx'

const svgRef = () => ({
visitor: {
JSXElement: {
enter(path) {
if (
path.node.name === 'svg' &&
!path.node.attributes.some(attr => attr && attr.name === 'ref')
) {
const props = new JSXAttribute()
props.name = 'ref'
props.value = 'svgRef'
props.litteral = true
path.node.attributes.push(props)
path.replace(path.node)
}
},
},
},
})

export default svgRef
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { pascalCase } from './transforms/rename'
import stripAttribute from './h2x/stripAttribute'
import emSize from './h2x/emSize'
import expandProps from './h2x/expandProps'
import svgRef from './h2x/svgRef'
import replaceAttrValue from './h2x/replaceAttrValue'
import removeComments from './h2x/removeComments'
import removeStyle from './h2x/removeStyle'
Expand All @@ -20,6 +21,7 @@ export {
emSize,
expandProps,
replaceAttrValue,
svgRef,
wrapIntoComponent,
removeComments,
removeStyle,
Expand Down
16 changes: 14 additions & 2 deletions src/transforms/wrapIntoComponent.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
export default (opts = {}) => (code, state) => `import React from 'react'
export default (opts = {}) => {
let props = ''

const ${state.componentName} = (${opts.expandProps ? 'props' : ''}) => ${code}
if (opts.expandProps && opts.ref) {
props = '{svgRef, ...props}'
} else if (opts.expandProps) {
props = 'props'
} else if (opts.ref) {
props = '{svgRef}'
}

return (code, state) => `import React from 'react'

const ${state.componentName} = (${props}) => ${code}

export default ${state.componentName}`
}
12 changes: 11 additions & 1 deletion src/transforms/wrapIntoNativeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,24 @@ export default (opts = {}) => (code, state) => {
unsupportedComponents = new Set(),
} = state

let props = ''

if (opts.expandProps && opts.ref) {
props = '{svgRef, ...props}'
} else if (opts.expandProps) {
props = 'props'
} else if (opts.ref) {
props = '{svgRef}'
}

return `import React from 'react'
import Svg, { ${componentsToList(
reactNativeSvgReplacedComponents,
)} } from 'react-native-svg';
${logUnsupportedComponents(unsupportedComponents)}


const ${state.componentName} = (${opts.expandProps ? 'props' : ''}) => ${code}
const ${state.componentName} = (${props}) => ${code}

export default ${state.componentName}`
}