From 78c14bdb025b0cceb756b3691ec4f32665b3abdd Mon Sep 17 00:00:00 2001 From: Caner Akdas Date: Wed, 20 Nov 2024 22:23:38 +0300 Subject: [PATCH] fix: Unoptimized SVG images (#7244) * fix: unoptimized SVG image * chore: review updates * Update apps/site/util/imageUtils.ts Co-authored-by: Steven Signed-off-by: Caner Akdas * chore: format files * chore: review update * Update apps/site/util/imageUtils.ts Co-authored-by: Steven Signed-off-by: Claudio W --------- Signed-off-by: Caner Akdas Signed-off-by: Claudio W Co-authored-by: Steven Co-authored-by: Claudio W --- apps/site/components/MDX/Image/index.tsx | 19 ++++++++- apps/site/next.config.mjs | 2 - apps/site/util/__tests__/imageUtils.test.mjs | 43 ++++++++++++++++++++ apps/site/util/imageUtils.ts | 19 +++++++++ 4 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 apps/site/util/__tests__/imageUtils.test.mjs create mode 100644 apps/site/util/imageUtils.ts diff --git a/apps/site/components/MDX/Image/index.tsx b/apps/site/components/MDX/Image/index.tsx index 42634bb9ad24b..871651ddd2882 100644 --- a/apps/site/components/MDX/Image/index.tsx +++ b/apps/site/components/MDX/Image/index.tsx @@ -2,7 +2,11 @@ import type { ImageProps } from 'next/image'; import Image from 'next/image'; import type { FC } from 'react'; -const MDXImage: FC = ({ width, height, alt, ...props }) => { +import { isSvgImage } from '@/util/imageUtils'; + +const MDXImage: FC = ({ width, height, alt, src, ...props }) => { + const isUnoptimizedImage = isSvgImage(src.toString()); + if (!width || !height) { // Since `width` and `height` are not provided in the Markdown image format, // we provide the height and width automatically. @@ -10,6 +14,8 @@ const MDXImage: FC = ({ width, height, alt, ...props }) => { return ( {alt} = ({ width, height, alt, ...props }) => { ); } - return {alt}; + return ( + {alt} + ); }; export default MDXImage; diff --git a/apps/site/next.config.mjs b/apps/site/next.config.mjs index 245c905ab71a5..167b52803379e 100644 --- a/apps/site/next.config.mjs +++ b/apps/site/next.config.mjs @@ -23,8 +23,6 @@ const nextConfig = { images: { // We disable image optimisation during static export builds unoptimized: ENABLE_STATIC_EXPORT, - // We allow SVGs to be used as images - dangerouslyAllowSVG: true, // We add it to the remote pattern for the static images we use from GitHub remotePatterns: [ { diff --git a/apps/site/util/__tests__/imageUtils.test.mjs b/apps/site/util/__tests__/imageUtils.test.mjs new file mode 100644 index 0000000000000..3e2ec00245ca1 --- /dev/null +++ b/apps/site/util/__tests__/imageUtils.test.mjs @@ -0,0 +1,43 @@ +import { isSvgImage } from '@/util/imageUtils'; + +describe('isSvgImage', () => { + const testCases = [ + { + description: 'should return true for a valid .svg URL', + input: 'https://nodejs.org/image.svg', + expected: true, + }, + { + description: 'should return true for a URL with query params', + input: 'https://nodejs.org/image.svg?query=param', + expected: true, + }, + { + description: 'should return false for a URL without a .svg extension', + input: 'https://nodejs.org/image', + expected: false, + }, + { + description: + 'should return false for a URL containing ".svg" but not ending with it', + input: 'https://nodejs.org/image.svg.png', + expected: false, + }, + { + description: 'should return false for an empty string', + input: '', + expected: false, + }, + { + description: 'should return false for a non-URL string', + input: 'not-a-url', + expected: false, + }, + ]; + + testCases.forEach(({ description, input, expected }) => { + it(description, () => { + expect(isSvgImage(input)).toBe(expected); + }); + }); +}); diff --git a/apps/site/util/imageUtils.ts b/apps/site/util/imageUtils.ts new file mode 100644 index 0000000000000..d75193e8c561b --- /dev/null +++ b/apps/site/util/imageUtils.ts @@ -0,0 +1,19 @@ +/** + * This is a temporary workaround that can be removed once Next.js is upgraded. + * See https://github.com/vercel/next.js/pull/72970 + * + * Checks if the given source string points to an SVG image. + * + * This function examines the base part of the provided string (ignoring query parameters) + * to determine if it ends with the `.svg` extension. + * + * @param src - The URL or string representing the source of the image. + * @returns `true` if the source points to an SVG image, otherwise `false`. + */ +export const isSvgImage = (src: string): boolean => { + // Split the source string at the '?' character to separate the main path from query parameters + const [image] = src.split('?'); + + // Check if the base path (before any query parameters) ends with '.svg' + return image.endsWith('.svg'); +};