diff --git a/packages/babel-plugin-transform-react-native-svg/package.json b/packages/babel-plugin-transform-react-native-svg/package.json index 8c97ee61..3400734a 100644 --- a/packages/babel-plugin-transform-react-native-svg/package.json +++ b/packages/babel-plugin-transform-react-native-svg/package.json @@ -1,7 +1,7 @@ { "name": "@svgr/babel-plugin-transform-react-native-svg", "description": "Transform DOM elements into react-native-svg components", - "version": "8.1.0", + "version": "8.2.0", "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { diff --git a/packages/babel-plugin-transform-react-native-svg/src/index.test.ts b/packages/babel-plugin-transform-react-native-svg/src/index.test.ts index 9fe80b4c..ca691ad5 100644 --- a/packages/babel-plugin-transform-react-native-svg/src/index.test.ts +++ b/packages/babel-plugin-transform-react-native-svg/src/index.test.ts @@ -16,6 +16,35 @@ describe('plugin', () => { expect(code).toMatchInlineSnapshot(`";"`) }) + it('should transform elements with filter', () => { + const svg = ` + + + + + + + + + + + ` + + const code = testPlugin(svg) + expect(code).toMatchInlineSnapshot(` + " + + + + + + + + + ;" + `) + }) + it('should add import', () => { const code = testPlugin( `import Svg from 'react-native-svg';
;`, @@ -27,6 +56,17 @@ describe('plugin', () => { `) }) + it('should add version warning', () => { + const code = testPlugin( + `import Svg from 'react-native-svg'; ;`, + ) + expect(code).toMatchInlineSnapshot(` + "import Svg, { Filter, FeGaussianBlur } from 'react-native-svg'; + /* Using svg filters is only supported on react-native-svg v15.5.0 or later. */ + ;" + `) + }) + it('should add deal with type imports properly', () => { const code = transform( ` diff --git a/packages/babel-plugin-transform-react-native-svg/src/index.ts b/packages/babel-plugin-transform-react-native-svg/src/index.ts index 6c63b203..fc21591d 100644 --- a/packages/babel-plugin-transform-react-native-svg/src/index.ts +++ b/packages/babel-plugin-transform-react-native-svg/src/index.ts @@ -4,6 +4,7 @@ import { NodePath, types as t } from '@babel/core' interface State { replacedComponents: Set unsupportedComponents: Set + filterComponents: Set } const elementToComponent: { [key: string]: string } = { @@ -30,6 +31,31 @@ const elementToComponent: { [key: string]: string } = { mask: 'Mask', image: 'Image', foreignObject: 'ForeignObject', + filter: 'Filter', + fegaussianblur: 'FeGaussianBlur', + feblend: 'FeBlend', + fecolormatrix: 'FeColorMatrix', + fecomponenttransfer: 'FeComponentTransfer', + fecomposite: 'FeComposite', + feconvolvematrix: 'FeConvolveMatrix', + fediffuselighting: 'FeDiffuseLighting', + fedisplacementmap: 'FeDisplacementMap', + fedropshadow: 'FeDropShadow', + feflood: 'FeFlood', + fefunca: 'FeFuncA', + fefuncb: 'FeFuncB', + fefuncg: 'FeFuncG', + fefuncr: 'FeFuncR', + feimage: 'FeImage', + femerge: 'FeMerge', + femergenode: 'FeMergeNode', + femorphology: 'FeMorphology', + feoffset: 'FeOffset', + fepointlight: 'FePointLight', + fespecularlighting: 'FeSpecularLighting', + fespotlight: 'FeSpotLight', + fetile: 'FeTile', + feturbulence: 'FeTurbulence', } const plugin = () => { @@ -39,8 +65,7 @@ const plugin = () => { const { name } = namePath.node // Replace element by react-native-svg components - const component = elementToComponent[name] - + const component = elementToComponent[name.toLowerCase()] // Case insensitive if (component) { namePath.replaceWith(t.jsxIdentifier(component)) if (path.has('closingElement')) { @@ -49,11 +74,15 @@ const plugin = () => { .get('name') as NodePath closingNamePath.replaceWith(t.jsxIdentifier(component)) } + // Add filter elements to show warning + if (name.includes('fe') || name.includes('filter')) { + state.filterComponents.add(name) + } state.replacedComponents.add(component) return } - // Remove element if not supported + // Remove unsupported element state.unsupportedComponents.add(name) path.remove() } @@ -119,6 +148,34 @@ const plugin = () => { ` SVGR has dropped some elements not supported by react-native-svg: ${componentList} `, ) } + + if (state.filterComponents.size && !path.has('trailingComments')) { + state.filterComponents.forEach((filter) => { + if ( + !path + .get('specifiers') + .some((specifier) => + specifier + .get('local') + .isIdentifier({ name: elementToComponent[filter] }), + ) + ) { + if (elementToComponent[filter]) { + path.pushContainer( + 'specifiers', + t.importSpecifier( + t.identifier(elementToComponent[filter]), + t.identifier(elementToComponent[filter]), + ), + ) + } + } + }) + path.addComment( + 'trailing', + ` Using svg filters is only supported on react-native-svg v15.5.0 or later. `, + ) + } }, } @@ -127,6 +184,7 @@ const plugin = () => { Program(path: NodePath, state: Partial) { state.replacedComponents = new Set() state.unsupportedComponents = new Set() + state.filterComponents = new Set() path.traverse(svgElementVisitor, state as State) path.traverse(importDeclarationVisitor, state as State)