diff --git a/packages/babel-plugin-svg-dynamic-title/src/index.js b/packages/babel-plugin-svg-dynamic-title/src/index.js index 1171157e..343ca3f9 100644 --- a/packages/babel-plugin-svg-dynamic-title/src/index.js +++ b/packages/babel-plugin-svg-dynamic-title/src/index.js @@ -11,20 +11,46 @@ const plugin = ({ types: t }) => ({ return } - const titleElement = t.jsxElement( - t.jsxOpeningElement(t.jsxIdentifier('title'), []), - t.jsxClosingElement(t.jsxIdentifier('title')), - [t.jsxExpressionContainer(t.identifier('title'))], - ) + function getTitleElement(existingTitleChildren = []) { + // create the expression for the title rendering + let expression = t.identifier('title') + // get the existing title string value + const existingTitle = (existingTitleChildren || []) + .map(c => c.value) + .join() + if (existingTitle) { + // if title exists + // render as follows + // {title === undefined ? existingTitle : title} + expression = t.conditionalExpression( + t.binaryExpression('===', expression, t.identifier('undefined')), + t.stringLiteral(existingTitle), + expression, + ) + } + + // create a title element with the given expression + return t.jsxElement( + t.jsxOpeningElement(t.jsxIdentifier('title'), []), + t.jsxClosingElement(t.jsxIdentifier('title')), + [t.jsxExpressionContainer(expression)], + ) + } + + // store the title element + let titleElement const hasTitle = path.get('children').some(childPath => { if (!childPath.isJSXElement()) return false if (childPath.node === titleElement) return false if (childPath.node.openingElement.name.name !== 'title') return false + titleElement = getTitleElement(childPath.node.children) childPath.replaceWith(titleElement) return true }) + // create a title element if not already create + titleElement = titleElement || getTitleElement() if (!hasTitle) { // path.unshiftContainer is not working well :( // path.unshiftContainer('children', titleElement) diff --git a/packages/babel-plugin-svg-dynamic-title/src/index.test.js b/packages/babel-plugin-svg-dynamic-title/src/index.test.js index 40e01362..da6da8c1 100644 --- a/packages/babel-plugin-svg-dynamic-title/src/index.test.js +++ b/packages/babel-plugin-svg-dynamic-title/src/index.test.js @@ -17,9 +17,9 @@ describe('plugin', () => { ) }) - it('should replace existing title by title attribute', () => { + it('should add title attribute and fallback to existing title', () => { expect(testPlugin('Hello')).toMatchInlineSnapshot( - `"{title};"`, + `"{title === undefined ? \\"Hello\\" : title};"`, ) }) diff --git a/packages/babel-preset/src/index.test.js b/packages/babel-preset/src/index.test.js index de53db23..1e5e097b 100644 --- a/packages/babel-preset/src/index.test.js +++ b/packages/babel-preset/src/index.test.js @@ -68,6 +68,24 @@ describe('preset', () => { export default SvgComponent;" `) }) + it('should handle titleProp and fallback on existing title', () => { + expect( + testPreset('Old', { + titleProp: true, + state: { + componentName: 'SvgComponent', + }, + }), + ).toMatchInlineSnapshot(` + "import React from \\"react\\"; + + const SvgComponent = ({ + title + }) => {title === undefined ? \\"Old\\" : title}; + + export default SvgComponent;" + `) + }) it('should handle replaceAttrValues', () => { expect( diff --git a/website/src/pages/docs/options.mdx b/website/src/pages/docs/options.mdx index 10ae5d2a..2f01bb97 100644 --- a/website/src/pages/docs/options.mdx +++ b/website/src/pages/docs/options.mdx @@ -134,7 +134,8 @@ Add props to the root SVG tag. ## Title -Add title tag via title property. +Add title tag via title property. If titleProp is set to true and no title is provided (`title={undefined}`) at render time, this will +fallback to existing title element in the svg if exists. | Default | CLI Override | API Override | | ------- | ------------ | ------------------- |