index.js 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. "use strict";
  2. exports.__esModule = true;
  3. exports.default = void 0;
  4. const elements = ['svg', 'Svg'];
  5. const plugin = ({
  6. types: t
  7. }) => ({
  8. visitor: {
  9. JSXElement(path) {
  10. if (!elements.some(element => path.get('openingElement.name').isJSXIdentifier({
  11. name: element
  12. }))) {
  13. return;
  14. }
  15. function createTitle(children = [], attributes = []) {
  16. return t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier('title'), attributes), t.jsxClosingElement(t.jsxIdentifier('title')), children);
  17. }
  18. function createTitleIdAttribute() {
  19. return t.jsxAttribute(t.jsxIdentifier('id'), t.jsxExpressionContainer(t.identifier('titleId')));
  20. }
  21. function enhanceAttributes(attributes) {
  22. const existingId = attributes.find(attribute => attribute.name.name === 'id');
  23. if (!existingId) {
  24. return [...attributes, createTitleIdAttribute()];
  25. }
  26. existingId.value = t.jsxExpressionContainer(t.logicalExpression('||', t.identifier('titleId'), existingId.value));
  27. return attributes;
  28. }
  29. function getTitleElement(existingTitle) {
  30. const titleExpression = t.identifier('title');
  31. if (existingTitle) {
  32. existingTitle.openingElement.attributes = enhanceAttributes(existingTitle.openingElement.attributes);
  33. }
  34. let titleElement = t.conditionalExpression(titleExpression, createTitle([t.jsxExpressionContainer(titleExpression)], existingTitle ? existingTitle.openingElement.attributes : [t.jsxAttribute(t.jsxIdentifier('id'), t.jsxExpressionContainer(t.identifier('titleId')))]), t.nullLiteral());
  35. if (existingTitle && existingTitle.children && existingTitle.children.length) {
  36. // if title already exists
  37. // render as follows
  38. const fallbackTitleElement = existingTitle; // {title === undefined ? fallbackTitleElement : titleElement}
  39. const conditionalExpressionForTitle = t.conditionalExpression(t.binaryExpression('===', titleExpression, t.identifier('undefined')), fallbackTitleElement, titleElement);
  40. titleElement = t.jsxExpressionContainer(conditionalExpressionForTitle);
  41. } else {
  42. titleElement = t.jsxExpressionContainer(titleElement);
  43. }
  44. return titleElement;
  45. } // store the title element
  46. let titleElement;
  47. const hasTitle = path.get('children').some(childPath => {
  48. if (!childPath.isJSXElement()) return false;
  49. if (childPath.node === titleElement) return false;
  50. if (childPath.node.openingElement.name.name !== 'title') return false;
  51. titleElement = getTitleElement(childPath.node);
  52. childPath.replaceWith(titleElement);
  53. return true;
  54. }); // create a title element if not already create
  55. titleElement = titleElement || getTitleElement();
  56. if (!hasTitle) {
  57. // path.unshiftContainer is not working well :(
  58. // path.unshiftContainer('children', titleElement)
  59. path.node.children.unshift(titleElement);
  60. path.replaceWith(path.node);
  61. }
  62. }
  63. }
  64. });
  65. var _default = plugin;
  66. exports.default = _default;