Skip to content

Commit ca1f744

Browse files
committed
gpt5 update 💪
1 parent 02a849e commit ca1f744

File tree

3 files changed

+46
-23
lines changed

3 files changed

+46
-23
lines changed

‎next.config.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {codecovNextJSWebpackPlugin} from '@codecov/nextjs-webpack-plugin';
22
import {withSentryConfig} from '@sentry/nextjs';
33

44
import {redirects} from './redirects.js';
5+
import {REMOTE_IMAGE_PATTERNS} from './src/config/images';
56

67
const outputFileTracingExcludes = process.env.NEXT_PUBLIC_DEVELOPER_DOCS
78
? {
@@ -56,16 +57,7 @@ const nextConfig = {
5657
outputFileTracingExcludes,
5758
images: {
5859
contentDispositionType: 'inline', // "open image in new tab" instead of downloading
59-
remotePatterns: [
60-
{
61-
protocol: 'https',
62-
hostname: 'user-images.githubusercontent.com',
63-
},
64-
{
65-
protocol: 'https',
66-
hostname: 'sentry-brand.storage.googleapis.com',
67-
},
68-
],
60+
remotePatterns: REMOTE_IMAGE_PATTERNS,
6961
},
7062
webpack: (config, options) => {
7163
config.plugins.push(

‎src/components/imageLightbox/index.tsx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {X} from 'react-feather';
55
import * as Dialog from '@radix-ui/react-dialog';
66
import Image from 'next/image';
77

8+
import {isAllowedRemoteImage} from 'sentry-docs/config/images';
9+
810
import styles from './imageLightbox.module.scss';
911

1012
interface ImageLightboxProps
@@ -25,6 +27,8 @@ const isExternalImage = (src: string): boolean => src.startsWith('http');
2527
const getImageUrl = (src: string, imgPath: string): string =>
2628
isExternalImage(src) ? src : imgPath;
2729

30+
// Using shared allowlist logic from src/config/images
31+
2832
type ValidDimensions = {
2933
height: number;
3034
width: number;
@@ -59,9 +63,9 @@ export function ImageLightbox({
5963
// Check if we should use Next.js Image or regular img
6064
// Use Next.js Image for internal images with valid dimensions
6165
// Use regular img for external images or when dimensions are invalid/missing
62-
const validDimensions = !isExternalImage(src)
63-
? getValidDimensions(width, height)
64-
: null;
66+
const dimensions = getValidDimensions(width, height);
67+
const shouldUseNextImage =
68+
!!dimensions && (!isExternalImage(src) || isAllowedRemoteImage(src));
6569

6670
const handleClick = (e: React.MouseEvent) => {
6771
// If Ctrl/Cmd+click, open image in new tab
@@ -101,13 +105,14 @@ export function ImageLightbox({
101105

102106
// Render the appropriate image component
103107
const renderImage = () => {
104-
if (validDimensions) {
108+
const renderedSrc = getImageUrl(src, imgPath);
109+
if (shouldUseNextImage && dimensions) {
105110
// TypeScript knows validDimensions.width and validDimensions.height are both numbers
106111
return (
107112
<Image
108-
src={src}
109-
width={validDimensions.width}
110-
height={validDimensions.height}
113+
src={renderedSrc}
114+
width={dimensions.width}
115+
height={dimensions.height}
111116
style={{
112117
width: '100%',
113118
height: 'auto',
@@ -122,8 +127,10 @@ export function ImageLightbox({
122127
return (
123128
/* eslint-disable-next-line @next/next/no-img-element */
124129
<img
125-
src={src}
130+
src={renderedSrc}
126131
alt={alt}
132+
loading="lazy"
133+
decoding="async"
127134
style={{
128135
width: '100%',
129136
height: 'auto',
@@ -161,12 +168,12 @@ export function ImageLightbox({
161168

162169
{/* Image container */}
163170
<div className="relative flex items-center justify-center">
164-
{validDimensions ? (
171+
{shouldUseNextImage && dimensions ? (
165172
<Image
166-
src={src}
173+
src={getImageUrl(src, imgPath)}
167174
alt={alt}
168-
width={validDimensions.width}
169-
height={validDimensions.height}
175+
width={dimensions.width}
176+
height={dimensions.height}
170177
className="max-h-[90vh] max-w-[90vw] object-contain"
171178
style={{
172179
width: 'auto',
@@ -178,8 +185,10 @@ export function ImageLightbox({
178185
) : (
179186
/* eslint-disable-next-line @next/next/no-img-element */
180187
<img
181-
src={src}
188+
src={getImageUrl(src, imgPath)}
182189
alt={alt}
190+
loading="lazy"
191+
decoding="async"
183192
className="max-h-[90vh] max-w-[90vw] object-contain"
184193
style={{
185194
width: 'auto',

‎src/config/images.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export const REMOTE_IMAGE_HOSTNAMES = [
2+
'user-images.githubusercontent.com',
3+
'sentry-brand.storage.googleapis.com',
4+
] as const;
5+
6+
export const REMOTE_IMAGE_PATTERNS = REMOTE_IMAGE_HOSTNAMES.map(hostname => ({
7+
protocol: 'https' as const,
8+
hostname,
9+
}));
10+
11+
export function isAllowedRemoteImage(src: string): boolean {
12+
try {
13+
const url = new URL(src);
14+
return (
15+
url.protocol === 'https:' &&
16+
(REMOTE_IMAGE_HOSTNAMES as readonly string[]).includes(url.hostname)
17+
);
18+
} catch (_error) {
19+
return false;
20+
}
21+
}
22+

0 commit comments

Comments
 (0)