diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/Kitten1SVG.jsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/Kitten1SVG.jsx deleted file mode 100644 index c08e4c5a2529..000000000000 --- a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/Kitten1SVG.jsx +++ /dev/null @@ -1,2 +0,0 @@ -const Kitten1 = props => ; -export default Kitten1; diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/Kitten1SVG.tsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/Kitten1SVG.tsx new file mode 100644 index 000000000000..57094f9b4584 --- /dev/null +++ b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/Kitten1SVG.tsx @@ -0,0 +1,3 @@ +import type { SVGProps } from "react"; +const Kitten1 = (props: SVGProps) => ; +export default Kitten1; diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/LogoSVG.jsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/LogoSVG.jsx deleted file mode 100644 index fe47f0a75b3a..000000000000 --- a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/LogoSVG.jsx +++ /dev/null @@ -1,2 +0,0 @@ -const Logo = props => ; -export default Logo; diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/LogoSVG.tsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/LogoSVG.tsx new file mode 100644 index 000000000000..161fa55dc367 --- /dev/null +++ b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/complex/output/mySvgs/LogoSVG.tsx @@ -0,0 +1,3 @@ +import type { SVGProps } from "react"; +const Logo = (props: SVGProps) => ; +export default Logo; diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/input/AsRenderProp.tsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/input/AsRenderProp.jsx similarity index 100% rename from packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/input/AsRenderProp.tsx rename to packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/input/AsRenderProp.jsx diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/input/Simple.tsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/input/Simple.jsx similarity index 100% rename from packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/input/Simple.tsx rename to packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/input/Simple.jsx diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/output/AsRenderProp.tsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/output/AsRenderProp.jsx similarity index 100% rename from packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/output/AsRenderProp.tsx rename to packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/output/AsRenderProp.jsx diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/output/Simple.tsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/output/Simple.jsx similarity index 100% rename from packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/output/Simple.tsx rename to packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/simple/output/Simple.jsx diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/Kitten1WithDashesSVG.jsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/Kitten1WithDashesSVG.jsx deleted file mode 100644 index c10ecf62f32d..000000000000 --- a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/Kitten1WithDashesSVG.jsx +++ /dev/null @@ -1,2 +0,0 @@ -const Kitten1WithDashes = props => ; -export default Kitten1WithDashes; diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/Kitten1WithDashesSVG.tsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/Kitten1WithDashesSVG.tsx new file mode 100644 index 000000000000..851269b61d21 --- /dev/null +++ b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/Kitten1WithDashesSVG.tsx @@ -0,0 +1,3 @@ +import type { SVGProps } from "react"; +const Kitten1WithDashes = (props: SVGProps) => ; +export default Kitten1WithDashes; diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/LogoSVG.jsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/LogoSVG.jsx deleted file mode 100644 index fe47f0a75b3a..000000000000 --- a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/LogoSVG.jsx +++ /dev/null @@ -1,2 +0,0 @@ -const Logo = props => ; -export default Logo; diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/LogoSVG.tsx b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/LogoSVG.tsx new file mode 100644 index 000000000000..161fa55dc367 --- /dev/null +++ b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/__testfixtures__/srcAlias/output/web/src/mySvgs/LogoSVG.tsx @@ -0,0 +1,3 @@ +import type { SVGProps } from "react"; +const Logo = (props: SVGProps) => ; +export default Logo; diff --git a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/replaceComponentSvgs.ts b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/replaceComponentSvgs.ts index e8164cea6fc9..3b1a2a204182 100644 --- a/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/replaceComponentSvgs.ts +++ b/packages/codemods/src/codemods/v6.x.x/replaceComponentSvgs/replaceComponentSvgs.ts @@ -5,10 +5,19 @@ import { transform as svgrTransform } from '@svgr/core' import type { API, FileInfo, StringLiteral } from 'jscodeshift' import pascalcase from 'pascalcase' +import { getPaths } from '@redwoodjs/project-config' + +/** + * @param svgFilePath Full path to the existing svg file + * @param outputPath Full path to the output file + * @param componentName Name of the React component to generate inside the output file + * @param typescript Whether to generate TypeScript code + */ async function convertSvgToReactComponent( svgFilePath: string, outputPath: string, - componentName: string + componentName: string, + typescript: boolean ) { const svgContents = await fs.readFile(svgFilePath, 'utf-8') @@ -17,6 +26,7 @@ async function convertSvgToReactComponent( { jsxRuntime: 'automatic', plugins: ['@svgr/plugin-jsx'], + typescript, }, { componentName: componentName, @@ -25,16 +35,16 @@ async function convertSvgToReactComponent( await fs.writeFile(outputPath, jsCode) + console.log() console.log(`SVG converted to React component: ${outputPath}`) } export default async function transform(file: FileInfo, api: API) { const j = api.jscodeshift - const root = j(file.source) - // Do this lazily - const { getPaths } = await import('@redwoodjs/project-config') + // If the input file is TypeScript, we'll generate TypeScript SVG components + const isTS = file.path.endsWith('.tsx') // Find all import declarations with "*.svg" import const svgImports = root.find(j.ImportDeclaration).filter((path) => { @@ -46,6 +56,7 @@ export default async function transform(file: FileInfo, api: API) { filePath: string importSourcePath: StringLiteral }> = [] + // Process each import declaration svgImports.forEach((importDeclaration) => { const importSpecifiers = importDeclaration.node.specifiers @@ -99,10 +110,10 @@ export default async function transform(file: FileInfo, api: API) { if (svgsToConvert.length > 0) { // if there are any svgs used as components, or render props, convert the svg to a react component await Promise.all( - svgsToConvert.map(async ({ filePath, importSourcePath }) => { + svgsToConvert.map(async (svg) => { const svgFileNameWithoutExtension = path.basename( - filePath, - path.extname(filePath) + svg.filePath, + path.extname(svg.filePath) ) const componentName = pascalcase(svgFileNameWithoutExtension) @@ -111,15 +122,20 @@ export default async function transform(file: FileInfo, api: API) { // The absolute path to the new file const outputPath = path.join( - path.dirname(filePath), - `${newFileName}.jsx` + path.dirname(svg.filePath), + `${newFileName}.${isTS ? 'tsx' : 'jsx'}` ) try { - await convertSvgToReactComponent(filePath, outputPath, componentName) + await convertSvgToReactComponent( + svg.filePath, + outputPath, + componentName, + isTS + ) } catch (error: any) { console.error( - `Error converting ${filePath} to React component: ${error.message}` + `Error converting ${svg.filePath} to React component: ${error.message}` ) // Don't proceed if SVGr fails @@ -129,8 +145,8 @@ export default async function transform(file: FileInfo, api: API) { // If SVGr is successful, change the import path // '../../bazinga.svg' -> '../../BazingaSVG' // Use extname, incase ext casing does not match - importSourcePath.value = importSourcePath.value.replace( - `${svgFileNameWithoutExtension}${path.extname(filePath)}`, + svg.importSourcePath.value = svg.importSourcePath.value.replace( + `${svgFileNameWithoutExtension}${path.extname(svg.filePath)}`, newFileName ) })