Skip to main content
Glama

extract_svg

Extract SVG components from React/TypeScript/JavaScript files into individual SVG files, preserving structure while removing React-specific code.

Instructions

Extract SVG components from React/TypeScript/JavaScript files into individual .svg files. This tool will preserve the SVG structure and attributes while removing React-specific code. By default, the source file will be replaced with "MIGRATED TO " and a warning message after successful extraction, making it easy to track where the SVGs were moved to. This behaviour can be disabled by setting the DISABLE_SOURCE_REPLACEMENT environment variable to 'true'. The warning message can be customized by setting the WARNING_MESSAGE environment variable.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sourcePathYesPath to the source file containing SVG components
targetDirYesDirectory where the SVG files should be written

Implementation Reference

  • Executes the extract_svg tool: extracts SVGs using extractSvgs, writes individual SVG files to targetDir, optionally replaces source file with migration notice.
    } else if (request.params.name === 'extract_svg') {
      const { targetDir } = request.params.arguments as { targetDir: string };
      const svgs = await this.extractSvgs(sourceCode);
    
      // Create target directory if it doesn't exist
      await fs.mkdir(targetDir, { recursive: true });
    
      // Write each SVG to a separate file
      for (const svg of svgs) {
        const filePath = path.join(targetDir, `${svg.name}.svg`);
        await fs.writeFile(filePath, svg.content, 'utf-8');
      }
    
      // Replace source file content with migration message if not disabled
      if (!DISABLE_SOURCE_REPLACEMENT) {
        const absoluteTargetDir = path.resolve(targetDir);
        await fs.writeFile(
          sourcePath,
          `MIGRATED TO ${absoluteTargetDir}${WARNING_MESSAGE}`,
          'utf-8'
        );
      }
    
      return {
        content: [
          {
            type: 'text',
            text: `Successfully extracted ${svgs.length} SVG components to ${path.resolve(targetDir)}${
              !DISABLE_SOURCE_REPLACEMENT ? `. Source file replaced with "MIGRATED TO ${path.resolve(targetDir)}"` : ''
            }`,
          },
        ],
      };
  • Input schema definition for extract_svg tool requiring sourcePath and targetDir.
    inputSchema: {
      type: 'object',
      properties: {
        sourcePath: {
          type: 'string',
          description: 'Path to the source file containing SVG components',
        },
        targetDir: {
          type: 'string',
          description: 'Directory where the SVG files should be written',
        },
      },
      required: ['sourcePath', 'targetDir'],
    },
  • src/index.ts:80-97 (registration)
    Registers the extract_svg tool in the tools list with name, description, and input schema.
    {
      name: 'extract_svg',
      description: 'Extract SVG components from React/TypeScript/JavaScript files into individual .svg files. This tool will preserve the SVG structure and attributes while removing React-specific code. By default, the source file will be replaced with "MIGRATED TO <target absolute path>" and a warning message after successful extraction, making it easy to track where the SVGs were moved to. This behaviour can be disabled by setting the DISABLE_SOURCE_REPLACEMENT environment variable to \'true\'. The warning message can be customized by setting the WARNING_MESSAGE environment variable.',
      inputSchema: {
        type: 'object',
        properties: {
          sourcePath: {
            type: 'string',
            description: 'Path to the source file containing SVG components',
          },
          targetDir: {
            type: 'string',
            description: 'Directory where the SVG files should be written',
          },
        },
        required: ['sourcePath', 'targetDir'],
      },
    },
  • Core extraction logic: parses source with Babel, traverses AST for SVG JSX in arrow function declarations, extracts using extractSvgContent.
    private async extractSvgs(sourceCode: string): Promise<SvgExtraction[]> {
      const ast = parser.parse(sourceCode, {
        sourceType: 'module',
        plugins: ['typescript', 'jsx'],
      });
    
      const svgs: SvgExtraction[] = [];
    
      traverse(ast, {
        VariableDeclaration(path: NodePath<t.VariableDeclaration>) {
          const declaration = path.node.declarations[0];
          if (t.isVariableDeclarator(declaration) &&
              t.isIdentifier(declaration.id) &&
              t.isArrowFunctionExpression(declaration.init)) {
    
            // Look for JSX in the arrow function body
            const body = declaration.init.body;
            if (t.isJSXElement(body)) {
              const svgContent = this.extractSvgContent(body);
              if (svgContent) {
                svgs.push({
                  name: declaration.id.name,
                  content: svgContent
                });
              }
            }
          }
        }
      });
    
      return svgs;
    }
  • Helper to convert JSX SVG element to plain SVG string, handling attributes, nested elements, and text content.
    private extractSvgContent(jsxElement: t.JSXElement): string | null {
      // Check if this is an SVG element
      if (t.isJSXIdentifier(jsxElement.openingElement.name) &&
          jsxElement.openingElement.name.name.toLowerCase() === 'svg') {
    
        // Convert JSX attributes to string
        const attributes = jsxElement.openingElement.attributes
          .map(attr => {
            if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
              const name = attr.name.name;
              if (t.isStringLiteral(attr.value)) {
                return `${name}="${attr.value.value}"`;
              } else if (t.isJSXExpressionContainer(attr.value) &&
                        t.isStringLiteral(attr.value.expression)) {
                return `${name}="${attr.value.expression.value}"`;
              }
            }
            return '';
          })
          .filter(Boolean)
          .join(' ');
    
        // Convert children to string
        const children = jsxElement.children
          .map(child => {
            if (t.isJSXElement(child)) {
              const elementName = (child.openingElement.name as t.JSXIdentifier).name;
              const childAttributes = child.openingElement.attributes
                .map(attr => {
                  if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
                    const name = attr.name.name;
                    if (t.isStringLiteral(attr.value)) {
                      return `${name}="${attr.value.value}"`;
                    }
                  }
                  return '';
                })
                .filter(Boolean)
                .join(' ');
    
              return `<${elementName} ${childAttributes}>${child.children
                .map(c => t.isJSXText(c) ? c.value : '')
                .join('')}</${elementName}>`;
            }
            return '';
          })
          .join('\n    ');
    
        return `<svg ${attributes}>\n    ${children}\n</svg>`;
      }
      return null;
    }
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sammcj/mcp-data-extractor'

If you have feedback or need assistance with the MCP directory API, please join our Discord server