diff --git a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/call-expression.output.js b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/call-expression.output.js index 2c6d6c0b60a59..ed7186133bfae 100644 --- a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/call-expression.output.js +++ b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/call-expression.output.js @@ -1,7 +1,7 @@ const result = graphql(`{ file(relativePath: {eq: "headers/headshot.jpg"}) { childImageSharp { - gatsbyImageData(layout: FLUID) + gatsbyImageData(layout: FULL_WIDTH) } } } diff --git a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/fluid.input.js b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/fluid.input.js new file mode 100644 index 0000000000000..0a5ae39c081e8 --- /dev/null +++ b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/fluid.input.js @@ -0,0 +1,24 @@ +import React from "react" +import { graphql } from "gatsby" +import Img from "gatsby-image" + +headshot + +export const query = graphql` +{ + file(relativePath: { eq: "headers/default.jpg" }) { + childImageSharp { + fluid(maxWidth: 1000) { + ...GatsbyImageSharpFluid + } + } + } + other: file(relativePath: { eq: "headers/default.jpg" }) { + childImageSharp { + fluid(maxWidth: 500) { + ...GatsbyImageSharpFluid + } + } + } +} +` \ No newline at end of file diff --git a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/fluid.output.js b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/fluid.output.js new file mode 100644 index 0000000000000..f1cf4686654ef --- /dev/null +++ b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/fluid.output.js @@ -0,0 +1,19 @@ +import React from "react" +import { graphql } from "gatsby" +import { GatsbyImage } from "gatsby-plugin-image"; + + + +export const query = graphql`{ + file(relativePath: {eq: "headers/default.jpg"}) { + childImageSharp { + gatsbyImageData(layout: FULL_WIDTH) + } + } + other: file(relativePath: {eq: "headers/default.jpg"}) { + childImageSharp { + gatsbyImageData(width: 500, layout: CONSTRAINED) + } + } +} +` diff --git a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/multiple.output.js b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/multiple.output.js index 673faa71d4e51..1826818eea0f8 100644 --- a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/multiple.output.js +++ b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/multiple.output.js @@ -11,7 +11,7 @@ import { GatsbyImage } from "gatsby-plugin-image"; export const query = graphql`{ file(relativePath: {eq: "headers/headshot.jpg"}) { childImageSharp { - gatsbyImageData(layout: FLUID) + gatsbyImageData(layout: FULL_WIDTH) } } banner: file(relativePath: {eq: "headers/default.jpg"}) { diff --git a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/placeholders.output.js b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/placeholders.output.js index 1ac432f5d041c..0b2e7b73c7f0e 100644 --- a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/placeholders.output.js +++ b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/placeholders.output.js @@ -8,7 +8,7 @@ import { GatsbyImage } from "gatsby-plugin-image"; export const query = graphql`{ named: file(relativePath: {eq: "landscape.jpg"}) { childImageSharp { - gatsbyImageData(placeholder: TRACED_SVG, layout: FLUID) + gatsbyImageData(placeholder: TRACED_SVG, layout: FULL_WIDTH) } } } diff --git a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/typescript.output.tsx b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/typescript.output.tsx index e35175da0c5e8..65ed2bc538890 100644 --- a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/typescript.output.tsx +++ b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/typescript.output.tsx @@ -5,7 +5,7 @@ export const Hero: React.SFC = ({ children }) => { const data = useStaticQuery(graphql`{ file(relativePath: {eq: "banner.jpg"}) { childImageSharp { - gatsbyImageData(layout: FLUID) + gatsbyImageData(layout: FULL_WIDTH) } } } diff --git a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/variable-src.input.js b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/variable-src.input.js new file mode 100644 index 0000000000000..d4921ea594b7f --- /dev/null +++ b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/variable-src.input.js @@ -0,0 +1,4 @@ +import Img from "gatsby-image" +const HomePage = ({ data }) => { + const image = data.file.childImageSharp.fluid.src +} \ No newline at end of file diff --git a/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/variable-src.output.js b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/variable-src.output.js new file mode 100644 index 0000000000000..f6278f0083d6c --- /dev/null +++ b/packages/gatsby-codemods/src/transforms/__testfixtures__/gatsby-plugin-image/variable-src.output.js @@ -0,0 +1,4 @@ +import { GatsbyImage } from "gatsby-plugin-image"; +const HomePage = ({ data }) => { + const image = data.file.childImageSharp.gatsbyImageData.src +} \ No newline at end of file diff --git a/packages/gatsby-codemods/src/transforms/__tests__/gatsby-plugin-image-test.js b/packages/gatsby-codemods/src/transforms/__tests__/gatsby-plugin-image-test.js index 56b6b3e3eae53..24f4f1b1591de 100644 --- a/packages/gatsby-codemods/src/transforms/__tests__/gatsby-plugin-image-test.js +++ b/packages/gatsby-codemods/src/transforms/__tests__/gatsby-plugin-image-test.js @@ -17,6 +17,8 @@ const tests = [ `stunted-ref`, `optional-chaining`, `styled`, + `fluid`, + `variable-src`, ] const defineTest = require(`jscodeshift/dist/testUtils`).defineTest diff --git a/packages/gatsby-codemods/src/transforms/gatsby-plugin-image.js b/packages/gatsby-codemods/src/transforms/gatsby-plugin-image.js index c15cdbef96559..6a74950b596c5 100644 --- a/packages/gatsby-codemods/src/transforms/gatsby-plugin-image.js +++ b/packages/gatsby-codemods/src/transforms/gatsby-plugin-image.js @@ -27,7 +27,7 @@ const legacyFragmentsSVGPlaceholder = [ const typeMapper = { fixed: `FIXED`, - fluid: `FLUID`, + fluid: `FULL_WIDTH`, constrained: `CONSTRAINED`, } @@ -122,6 +122,14 @@ export function updateImport(babel) { propNames.includes(path.node.property.name) && path.node?.object?.property?.name === `childImageSharp` ) { + if ( + t.isMemberExpression(path.parent) || + t.isOptionalMemberExpression(path.parent) + ) { + console.log( + `It appears you're accessing src or similar. This structure has changed. Please inspect ${state.opts.filename} manually, you likely want to use a helper function like getSrc.` + ) + } const updatedExpression = t.memberExpression( path.node.object, t.identifier(`gatsbyImageData`) @@ -135,6 +143,14 @@ export function updateImport(babel) { propNames.includes(path.node.property.name) && path.node?.object?.property?.name === `childImageSharp` ) { + if ( + t.isMemberExpression(path.parent) || + t.isOptionalMemberExpression(path.parent) + ) { + console.log( + `It appears you're accessing src or similar. This structure has changed. Please inspect ${state.opts.filename} manually, you likely want to use a helper function like getSrc.` + ) + } const updatedExpression = t.optionalMemberExpression( path.node.object, t.identifier(`gatsbyImageData`), @@ -154,7 +170,7 @@ export function updateImport(babel) { const { ast: transformedGraphQLQuery, hasChanged, - } = processGraphQLQuery(query) + } = processGraphQLQuery(query, state) if (hasChanged) { node.quasi.quasis[0].value.raw = graphql.print( @@ -174,7 +190,7 @@ export function updateImport(babel) { const { ast: transformedGraphQLQuery, hasChanged, - } = processGraphQLQuery(query) + } = processGraphQLQuery(query, state) if (hasChanged) { node.arguments[0].quasis[0].value.raw = graphql.print( @@ -251,19 +267,9 @@ function processImportUsage(path, t, template, state) { newImageExpression.extra.parenthesized = false // the template adds parens and we don't want it to } else if (t.isObjectExpression(expressionValue)) { - expressionValue.properties.map(item => { - if (item.key?.name !== `src`) return - if (t.isMemberExpression(item.value)) { - let subObject = item.value?.object - while (subObject) { - if (propNames.includes(subObject.property?.name)) { - subObject.property.name = `gatsbyImageData` - break - } - subObject = subObject?.object - } - } - }) + console.log( + `It appears you're passing src or srcSet directly. This API is no longer exposed, please update ${state.opts.filename} manually.` + ) } else if (expressionValue) { console.log( `It appears you're passing a variable to your image component. We haven't changed it, but we have updated it to use the new GatsbyImage component. Please check ${state.opts.filename} manually.` @@ -286,7 +292,7 @@ function processImportUsage(path, t, template, state) { path.skip() // prevent us from revisiting these nodes } -function processArguments(queryArguments, fragment) { +function processArguments(queryArguments, fragment, layout, state) { if (!legacyFragments.includes(fragment.name.value)) { let placeholderEnum = `BLURRED` // just in case these aren't the discrete cases we expect if (legacyFragmentsNoPlaceholder.includes(fragment.name?.value)) { @@ -307,10 +313,32 @@ function processArguments(queryArguments, fragment) { } queryArguments.push(placeholderArgument) } - return + for (let index in queryArguments) { + const argument = queryArguments[index] + if (argument.name.value === `maxWidth`) { + argument.name.value = `width` + if (layout === `fluid` && Number(argument.value.value) >= 1000) { + delete queryArguments[index] + console.log( + `maxWidth is no longer supported for fluid (now fullWidth) images. It's been removed from your query in ${state.opts.filename}.` + ) + } else if (layout === `fluid` && Number(argument.value.value) < 1000) { + console.log( + `maxWidth is no longer supported for fluid (now fullWidth) images. We've updated the query in ${state.opts.filename} to use a constrained image instead.` + ) + return `constrained` + } + } else if (argument.name.value === `maxHeight`) { + argument.name.value = `height` + console.log( + `maxHeight is no longer supported for fluid (now fullWidth) images. It's been removed from your query in ${state.opts.filename}.` + ) + } + } + return layout } -function processGraphQLQuery(query) { +function processGraphQLQuery(query, state) { try { let hasChanged = false // this is sort of a hack, but print changes formatting and we only want to use it when we have to const ast = graphql.parse(query) @@ -333,7 +361,7 @@ function processGraphQLQuery(query) { if (!fixedOrFluidField) { return } - let imageType = fixedOrFluidField.name.value + let layout = fixedOrFluidField.name.value const fragments = fixedOrFluidField.selectionSet.selections const presentationSizeFragment = fragments.find( @@ -341,10 +369,15 @@ function processGraphQLQuery(query) { name.value === `GatsbyImageSharpFluidLimitPresentationSize` ) if (presentationSizeFragment) { - imageType = `constrained` + layout = `constrained` delete fragments[presentationSizeFragment] } - processArguments(fixedOrFluidField.arguments, fragments?.[0]) + layout = processArguments( + fixedOrFluidField.arguments, + fragments?.[0], + layout, + state + ) const typeArgument = { kind: `Argument`, @@ -354,7 +387,7 @@ function processGraphQLQuery(query) { }, value: { kind: `EnumValue`, - value: typeMapper[imageType], + value: typeMapper[layout], }, }