index.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. "use strict";
  2. exports.__esModule = true;
  3. exports.default = void 0;
  4. const elementToComponent = {
  5. svg: 'Svg',
  6. circle: 'Circle',
  7. clipPath: 'ClipPath',
  8. ellipse: 'Ellipse',
  9. g: 'G',
  10. linearGradient: 'LinearGradient',
  11. radialGradient: 'RadialGradient',
  12. line: 'Line',
  13. path: 'Path',
  14. pattern: 'Pattern',
  15. polygon: 'Polygon',
  16. polyline: 'Polyline',
  17. rect: 'Rect',
  18. symbol: 'Symbol',
  19. text: 'Text',
  20. textPath: 'TextPath',
  21. tspan: 'TSpan',
  22. use: 'Use',
  23. defs: 'Defs',
  24. stop: 'Stop',
  25. mask: 'Mask',
  26. image: 'Image',
  27. foreignObject: 'ForeignObject'
  28. };
  29. const expoPrefix = (component, expo) => {
  30. // Prefix with 'Svg.' in the case we're transforming for Expo
  31. if (!expo) {
  32. return component;
  33. }
  34. return (component !== 'Svg' ? 'Svg.' : '') + component;
  35. };
  36. const plugin = ({
  37. types: t
  38. }, {
  39. expo
  40. }) => {
  41. function replaceElement(path, state) {
  42. const {
  43. name
  44. } = path.node.openingElement.name; // Replace element by react-native-svg components
  45. const component = elementToComponent[name];
  46. if (component) {
  47. const prefixedComponent = expoPrefix(component, expo);
  48. const openingElementName = path.get('openingElement.name');
  49. openingElementName.replaceWith(t.jsxIdentifier(prefixedComponent));
  50. if (path.has('closingElement')) {
  51. const closingElementName = path.get('closingElement.name');
  52. closingElementName.replaceWith(t.jsxIdentifier(prefixedComponent));
  53. }
  54. state.replacedComponents.add(prefixedComponent);
  55. return;
  56. } // Remove element if not supported
  57. state.unsupportedComponents.add(name);
  58. path.remove();
  59. }
  60. const svgElementVisitor = {
  61. JSXElement(path, state) {
  62. if (!path.get('openingElement.name').isJSXIdentifier({
  63. name: 'svg'
  64. })) {
  65. return;
  66. }
  67. replaceElement(path, state);
  68. path.traverse(jsxElementVisitor, state);
  69. }
  70. };
  71. const jsxElementVisitor = {
  72. JSXElement(path, state) {
  73. replaceElement(path, state);
  74. }
  75. };
  76. const importDeclarationVisitor = {
  77. ImportDeclaration(path, state) {
  78. if (path.get('source').isStringLiteral({
  79. value: 'react-native-svg'
  80. })) {
  81. state.replacedComponents.forEach(component => {
  82. if (path.get('specifiers').some(specifier => specifier.get('local').isIdentifier({
  83. name: component
  84. }))) {
  85. return;
  86. }
  87. path.pushContainer('specifiers', t.importSpecifier(t.identifier(component), t.identifier(component)));
  88. });
  89. } else if (path.get('source').isStringLiteral({
  90. value: 'expo'
  91. })) {
  92. path.pushContainer('specifiers', t.importSpecifier(t.identifier('Svg'), t.identifier('Svg')));
  93. } else {
  94. return;
  95. }
  96. if (state.unsupportedComponents.size && !path.has('trailingComments')) {
  97. const componentList = [...state.unsupportedComponents].join(', ');
  98. path.addComment('trailing', ` SVGR has dropped some elements not supported by react-native-svg: ${componentList} `);
  99. }
  100. }
  101. };
  102. return {
  103. visitor: {
  104. Program(path, state) {
  105. state.replacedComponents = new Set();
  106. state.unsupportedComponents = new Set();
  107. path.traverse(svgElementVisitor, state);
  108. path.traverse(importDeclarationVisitor, state);
  109. }
  110. }
  111. };
  112. };
  113. var _default = plugin;
  114. exports.default = _default;