Skip to content

Commit 1882acb

Browse files
committed
fix: eslint rule of using img in metadata routes (#74864)
1 parent e204a30 commit 1882acb

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

packages/eslint-plugin-next/src/rules/no-img-element.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path = require('path')
12
import { defineRule } from '../utils/define-rule'
23

34
const url = 'https://nextjs.org/docs/messages/no-img-element'
@@ -15,6 +16,14 @@ export = defineRule({
1516
schema: [],
1617
},
1718
create(context) {
19+
// Get relative path of the file
20+
const relativePath = context.filename
21+
.replace(path.sep, '/')
22+
.replace(context.cwd, '')
23+
.replace(/^\//, '')
24+
25+
const isAppDir = /^(src\/)?app\//.test(relativePath)
26+
1827
return {
1928
JSXOpeningElement(node) {
2029
if (node.name.name !== 'img') {
@@ -29,6 +38,14 @@ export = defineRule({
2938
return
3039
}
3140

41+
// If is metadata route files, ignore
42+
// e.g. opengraph-image.js, twitter-image.js, icon.js
43+
if (
44+
isAppDir &&
45+
/\/opengraph-image|twitter-image|icon\.\w+$/.test(relativePath)
46+
)
47+
return
48+
3249
context.report({
3350
node,
3451
message: `Using \`<img>\` could result in slower LCP and higher bandwidth. Consider using \`<Image />\` from \`next/image\` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: ${url}`,

test/unit/eslint-plugin-next/no-img-element.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,46 @@ const tests = {
5555
);
5656
}
5757
}`,
58+
{
59+
code: `\
60+
import { ImageResponse } from "next/og";
61+
62+
export default function icon() {
63+
return new ImageResponse(
64+
(
65+
<img
66+
alt="avatar"
67+
style={{ borderRadius: "100%" }}
68+
width="100%"
69+
height="100%"
70+
src="https://example.com/image.png"
71+
/>
72+
)
73+
);
74+
}
75+
`,
76+
filename: `src/app/icon.js`,
77+
},
78+
{
79+
code: `\
80+
import { ImageResponse } from "next/og";
81+
82+
export default function Image() {
83+
return new ImageResponse(
84+
(
85+
<img
86+
alt="avatar"
87+
style={{ borderRadius: "100%" }}
88+
width="100%"
89+
height="100%"
90+
src="https://example.com/image.png"
91+
/>
92+
)
93+
);
94+
}
95+
`,
96+
filename: `app/opengraph-image.tsx`,
97+
},
5898
],
5999
invalid: [
60100
{
@@ -91,6 +131,27 @@ const tests = {
91131
}`,
92132
errors: [{ message, type: 'JSXOpeningElement' }],
93133
},
134+
{
135+
code: `\
136+
import { ImageResponse } from "next/og";
137+
138+
export default function Image() {
139+
return new ImageResponse(
140+
(
141+
<img
142+
alt="avatar"
143+
style={{ borderRadius: "100%" }}
144+
width="100%"
145+
height="100%"
146+
src="https://example.com/image.png"
147+
/>
148+
)
149+
);
150+
}
151+
`,
152+
filename: `some/non-metadata-route-image.tsx`,
153+
errors: [{ message, type: 'JSXOpeningElement' }],
154+
},
94155
],
95156
}
96157

0 commit comments

Comments
 (0)