Skip to content

Commit

Permalink
feat(titleProp): add titleProp option (#103)
Browse files Browse the repository at this point in the history
Closes #88
  • Loading branch information
marques-kevin authored and gregberge committed Jun 12, 2018
1 parent ab6e0b6 commit be39fe4
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 1 deletion.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ Options:
--template <file> specify a custom template to use
--trailing-comma <none|es5|all> print trailing commas wherever possible when multi-line (prettier)
--use-tabs indent lines with tabs instead of spaces (prettier)
--title-prop create a title element linked with props
-h, --help output usage information
Examples:
Expand Down Expand Up @@ -535,6 +536,14 @@ Indent lines with tabs instead of spaces. See
| ------- | ------------ | ----------------- |
| `false` | `--use-tabs` | `useTabs: <bool>` |

### Title Prop

Add an `<svg><title>{title}</title></svg>` element managed by React instead of adding a title property to the `<svg title={title}/>` element.

| Default | CLI Override | API Override |
| ------- | -------------- | ------------------- |
| `false` | `--title-prop` | `titleProp: <bool>` |

### Output Directory

Output files into a directory.
Expand Down
14 changes: 14 additions & 0 deletions src/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ export default SvgComponent
"
`;

exports[`convert options titleProp 1`] = `
"import React from 'react'
const SvgComponent = ({ title, ...props }) => (
<svg width={0} height={0} style={{ position: 'absolute' }} {...props}>
<title>{title}</title>
<path d=\\"M0 0h24v24H0z\\" fill=\\"none\\" />
</svg>
)
export default SvgComponent
"
`;

exports[`convert should accept initial state (for webpack) 1`] = `
"import React from 'react'
Expand Down
15 changes: 15 additions & 0 deletions src/cli/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,21 @@ export default function One() {
"
`;

exports[`cli --title-prop 1`] = `
"import React from 'react';
const One = ({ title, ...props }) => (
<svg width={48} height={1} viewBox=\\"0 0 48 1\\" {...props}>
<title>{title}</title>
<path d=\\"M0 0h48v1H0z\\" fill=\\"#063855\\" fillRule=\\"evenodd\\" />
</svg>
);
export default One;
"
`;

exports[`cli --trailing-comma all 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 @@ -75,6 +75,7 @@ program
'print trailing commas wherever possible when multi-line (prettier)',
)
.option('--use-tabs', 'indent lines with tabs instead of spaces (prettier)')
.option('--title-prop', 'create a title element linked with props')

program.on('--help', () => {
console.log(`
Expand Down
5 changes: 5 additions & 0 deletions src/cli/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,10 @@ describe('cli', () => {
const [stdout] = await exec('bin/svgr --svg-attribute focusable=false --svg-attribute hidden=0 __fixtures__/one.svg')

expect(stdout).toMatchSnapshot();
});

it('--title-prop', async () => {
const [stdout] = await exec('bin/svgr --title-prop __fixtures__/one.svg')
expect(stdout).toMatchSnapshot()
})
})
3 changes: 3 additions & 0 deletions src/configToOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import replaceAttrValue from './h2x/replaceAttrValue'
import removeComments from './h2x/removeComments'
import removeStyle from './h2x/removeStyle'
import svgAttribute from './h2x/svgAttribute'
import titleProp from './h2x/titleProp'
import toReactNative from './h2x/toReactNative'

const defaultConfig = {
Expand Down Expand Up @@ -38,6 +39,7 @@ const defaultConfig = {
}

function configToOptions(config = {}) {

if (!config.template && config.native)
config.template = wrapIntoNativeComponent
config = { ...defaultConfig, ...config }
Expand All @@ -54,6 +56,7 @@ function configToOptions(config = {}) {
if (config.svgAttribute) plugins.push(svgAttribute(config.svgAttribute))
if (config.expandProps) plugins.push(expandProps)
if (config.native) plugins.push(toReactNative)
if (config.titleProp) plugins.push(titleProp)

return plugins
}
Expand Down
21 changes: 21 additions & 0 deletions src/h2x/__snapshots__/titleProp.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`titleProp should add title element to svg 1`] = `
"<svg>
<title>
{title}
</title>
<path d=\\"M51,37 L37,51\\" id=\\"Shape\\" />
</svg>
"
`;

exports[`titleProp should remove old title and add the new title 1`] = `
"<svg>
<title>
{title}
</title>
<path d=\\"M51,37 L37,51\\" id=\\"Shape\\" />
</svg>
"
`;
45 changes: 45 additions & 0 deletions src/h2x/titleProp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { JSXElement, JSXText } from 'h2x-plugin-jsx'

/**
* Check if a classical title exist
* @param {*} node - NodeElement
* @returns {boolean}
*/
const hasTitle = node =>
node.children.reduce((accumulation, value) => {
if (value.name !== 'title') return accumulation
if (value.children.some((e) => e.text === '{title}')) return accumulation
return true
}, false)

const titleProp = () => ({
visitor: {
JSXElement: {
enter(path) {
if (path.node.name === 'svg') {
if (hasTitle(path.node)) {
path.node.children = path.node.children.filter(element => {
if (element.name !== 'title') return true
if (element.children.some(e => e.text === '{title}')) return true
return false
})
}

if (!path.node.children.some(children => children.name === 'title')) {
const element = new JSXElement()
const text = new JSXText()

text.text = '{title}'

element.name = 'title'
element.children.push(text)

path.node.children.unshift(element)
}
}
},
},
},
})

export default titleProp
30 changes: 30 additions & 0 deletions src/h2x/titleProp.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import jsx from 'h2x-plugin-jsx'
import h2x from '../plugins/h2x'
import titleProp from './titleProp'

describe('titleProp', () => {
it('should add title element to svg', () => {
const result = h2x(
`<svg>
<path d="M51,37 L37,51" id="Shape"></path>
</svg>
`,
{ plugins: [jsx, titleProp] },
)

expect(result).toMatchSnapshot()
})

it('should remove old title and add the new title', () => {
const result = h2x(
`<svg>
<title>Rectangle 5</title>
<path d="M51,37 L37,51" id="Shape"></path>
</svg>
`,
{ plugins: [jsx, titleProp] },
)

expect(result).toMatchSnapshot()
})
})
9 changes: 9 additions & 0 deletions src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,15 @@ describe('convert', () => {
expect(
await convert(svg, { svgAttribute: { focusable: false } }),
).toMatchSnapshot()
});

it('titleProp', async () => {
const svg = `
<svg width="0" height="0" style="position:absolute">
<path d="M0 0h24v24H0z" fill="none" />
</svg>
`
expect(await convert(svg, { titleProp: true })).toMatchSnapshot()
})
})
})
10 changes: 9 additions & 1 deletion src/transforms/wrapIntoComponent.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
export default (opts = {}) => {
let props = ''

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

return (code, state) => {
Expand Down

0 comments on commit be39fe4

Please sign in to comment.