eslint-plugin-nextjs 0.1.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +13 -13
  2. package/dist/index.d.ts +3 -6
  3. package/dist/index.js +398 -260
  4. package/dist/index.js.map +1 -1
  5. package/package.json +15 -10
  6. package/dist/index.cjs +0 -1485
  7. package/dist/index.cjs.map +0 -1
  8. package/dist/index.d.cts +0 -11
  9. package/dist/rules/google-font-display.cjs +0 -119
  10. package/dist/rules/google-font-display.cjs.map +0 -1
  11. package/dist/rules/google-font-display.d.cts +0 -8
  12. package/dist/rules/google-font-display.d.ts +0 -8
  13. package/dist/rules/google-font-display.js +0 -92
  14. package/dist/rules/google-font-display.js.map +0 -1
  15. package/dist/rules/google-font-preconnect.cjs +0 -109
  16. package/dist/rules/google-font-preconnect.cjs.map +0 -1
  17. package/dist/rules/google-font-preconnect.d.cts +0 -5
  18. package/dist/rules/google-font-preconnect.d.ts +0 -5
  19. package/dist/rules/google-font-preconnect.js +0 -82
  20. package/dist/rules/google-font-preconnect.js.map +0 -1
  21. package/dist/rules/inline-script-id.cjs +0 -94
  22. package/dist/rules/inline-script-id.cjs.map +0 -1
  23. package/dist/rules/inline-script-id.d.cts +0 -5
  24. package/dist/rules/inline-script-id.d.ts +0 -5
  25. package/dist/rules/inline-script-id.js +0 -67
  26. package/dist/rules/inline-script-id.js.map +0 -1
  27. package/dist/rules/next-script-for-ga.cjs +0 -129
  28. package/dist/rules/next-script-for-ga.cjs.map +0 -1
  29. package/dist/rules/next-script-for-ga.d.cts +0 -5
  30. package/dist/rules/next-script-for-ga.d.ts +0 -5
  31. package/dist/rules/next-script-for-ga.js +0 -102
  32. package/dist/rules/next-script-for-ga.js.map +0 -1
  33. package/dist/rules/no-assign-module-variable.cjs +0 -64
  34. package/dist/rules/no-assign-module-variable.cjs.map +0 -1
  35. package/dist/rules/no-assign-module-variable.d.cts +0 -5
  36. package/dist/rules/no-assign-module-variable.d.ts +0 -5
  37. package/dist/rules/no-assign-module-variable.js +0 -37
  38. package/dist/rules/no-assign-module-variable.js.map +0 -1
  39. package/dist/rules/no-async-client-component.cjs +0 -99
  40. package/dist/rules/no-async-client-component.cjs.map +0 -1
  41. package/dist/rules/no-async-client-component.d.cts +0 -5
  42. package/dist/rules/no-async-client-component.d.ts +0 -5
  43. package/dist/rules/no-async-client-component.js +0 -72
  44. package/dist/rules/no-async-client-component.js.map +0 -1
  45. package/dist/rules/no-before-interactive-script-outside-document.cjs +0 -94
  46. package/dist/rules/no-before-interactive-script-outside-document.cjs.map +0 -1
  47. package/dist/rules/no-before-interactive-script-outside-document.d.cts +0 -5
  48. package/dist/rules/no-before-interactive-script-outside-document.d.ts +0 -5
  49. package/dist/rules/no-before-interactive-script-outside-document.js +0 -59
  50. package/dist/rules/no-before-interactive-script-outside-document.js.map +0 -1
  51. package/dist/rules/no-css-tags.cjs +0 -70
  52. package/dist/rules/no-css-tags.cjs.map +0 -1
  53. package/dist/rules/no-css-tags.d.cts +0 -5
  54. package/dist/rules/no-css-tags.d.ts +0 -5
  55. package/dist/rules/no-css-tags.js +0 -43
  56. package/dist/rules/no-css-tags.js.map +0 -1
  57. package/dist/rules/no-document-import-in-page.cjs +0 -74
  58. package/dist/rules/no-document-import-in-page.cjs.map +0 -1
  59. package/dist/rules/no-document-import-in-page.d.cts +0 -5
  60. package/dist/rules/no-document-import-in-page.d.ts +0 -5
  61. package/dist/rules/no-document-import-in-page.js +0 -39
  62. package/dist/rules/no-document-import-in-page.js.map +0 -1
  63. package/dist/rules/no-duplicate-head.cjs +0 -87
  64. package/dist/rules/no-duplicate-head.cjs.map +0 -1
  65. package/dist/rules/no-duplicate-head.d.cts +0 -5
  66. package/dist/rules/no-duplicate-head.d.ts +0 -5
  67. package/dist/rules/no-duplicate-head.js +0 -60
  68. package/dist/rules/no-duplicate-head.js.map +0 -1
  69. package/dist/rules/no-head-element.cjs +0 -76
  70. package/dist/rules/no-head-element.cjs.map +0 -1
  71. package/dist/rules/no-head-element.d.cts +0 -5
  72. package/dist/rules/no-head-element.d.ts +0 -5
  73. package/dist/rules/no-head-element.js +0 -41
  74. package/dist/rules/no-head-element.js.map +0 -1
  75. package/dist/rules/no-head-import-in-document.cjs +0 -76
  76. package/dist/rules/no-head-import-in-document.cjs.map +0 -1
  77. package/dist/rules/no-head-import-in-document.d.cts +0 -5
  78. package/dist/rules/no-head-import-in-document.d.ts +0 -5
  79. package/dist/rules/no-head-import-in-document.js +0 -41
  80. package/dist/rules/no-head-import-in-document.js.map +0 -1
  81. package/dist/rules/no-html-link-for-pages.cjs +0 -302
  82. package/dist/rules/no-html-link-for-pages.cjs.map +0 -1
  83. package/dist/rules/no-html-link-for-pages.d.cts +0 -5
  84. package/dist/rules/no-html-link-for-pages.d.ts +0 -5
  85. package/dist/rules/no-html-link-for-pages.js +0 -267
  86. package/dist/rules/no-html-link-for-pages.js.map +0 -1
  87. package/dist/rules/no-img-element.cjs +0 -83
  88. package/dist/rules/no-img-element.cjs.map +0 -1
  89. package/dist/rules/no-img-element.d.cts +0 -5
  90. package/dist/rules/no-img-element.d.ts +0 -5
  91. package/dist/rules/no-img-element.js +0 -48
  92. package/dist/rules/no-img-element.js.map +0 -1
  93. package/dist/rules/no-page-custom-font.cjs +0 -184
  94. package/dist/rules/no-page-custom-font.cjs.map +0 -1
  95. package/dist/rules/no-page-custom-font.d.cts +0 -5
  96. package/dist/rules/no-page-custom-font.d.ts +0 -5
  97. package/dist/rules/no-page-custom-font.js +0 -159
  98. package/dist/rules/no-page-custom-font.js.map +0 -1
  99. package/dist/rules/no-script-component-in-head.cjs +0 -74
  100. package/dist/rules/no-script-component-in-head.cjs.map +0 -1
  101. package/dist/rules/no-script-component-in-head.d.cts +0 -5
  102. package/dist/rules/no-script-component-in-head.d.ts +0 -5
  103. package/dist/rules/no-script-component-in-head.js +0 -47
  104. package/dist/rules/no-script-component-in-head.js.map +0 -1
  105. package/dist/rules/no-styled-jsx-in-document.cjs +0 -78
  106. package/dist/rules/no-styled-jsx-in-document.cjs.map +0 -1
  107. package/dist/rules/no-styled-jsx-in-document.d.cts +0 -5
  108. package/dist/rules/no-styled-jsx-in-document.d.ts +0 -5
  109. package/dist/rules/no-styled-jsx-in-document.js +0 -43
  110. package/dist/rules/no-styled-jsx-in-document.js.map +0 -1
  111. package/dist/rules/no-sync-scripts.cjs +0 -64
  112. package/dist/rules/no-sync-scripts.cjs.map +0 -1
  113. package/dist/rules/no-sync-scripts.d.cts +0 -5
  114. package/dist/rules/no-sync-scripts.d.ts +0 -5
  115. package/dist/rules/no-sync-scripts.js +0 -37
  116. package/dist/rules/no-sync-scripts.js.map +0 -1
  117. package/dist/rules/no-title-in-document-head.cjs +0 -78
  118. package/dist/rules/no-title-in-document-head.cjs.map +0 -1
  119. package/dist/rules/no-title-in-document-head.d.cts +0 -5
  120. package/dist/rules/no-title-in-document-head.d.ts +0 -5
  121. package/dist/rules/no-title-in-document-head.js +0 -51
  122. package/dist/rules/no-title-in-document-head.js.map +0 -1
  123. package/dist/rules/no-typos.cjs +0 -133
  124. package/dist/rules/no-typos.cjs.map +0 -1
  125. package/dist/rules/no-typos.d.cts +0 -5
  126. package/dist/rules/no-typos.d.ts +0 -5
  127. package/dist/rules/no-typos.js +0 -98
  128. package/dist/rules/no-typos.js.map +0 -1
  129. package/dist/rules/no-unwanted-polyfillio.cjs +0 -164
  130. package/dist/rules/no-unwanted-polyfillio.cjs.map +0 -1
  131. package/dist/rules/no-unwanted-polyfillio.d.cts +0 -5
  132. package/dist/rules/no-unwanted-polyfillio.d.ts +0 -5
  133. package/dist/rules/no-unwanted-polyfillio.js +0 -137
  134. package/dist/rules/no-unwanted-polyfillio.js.map +0 -1
  135. package/dist/utils/define-rule.cjs +0 -31
  136. package/dist/utils/define-rule.cjs.map +0 -1
  137. package/dist/utils/define-rule.d.cts +0 -5
  138. package/dist/utils/define-rule.d.ts +0 -5
  139. package/dist/utils/define-rule.js +0 -6
  140. package/dist/utils/define-rule.js.map +0 -1
  141. package/dist/utils/get-root-dirs.cjs +0 -60
  142. package/dist/utils/get-root-dirs.cjs.map +0 -1
  143. package/dist/utils/get-root-dirs.d.cts +0 -8
  144. package/dist/utils/get-root-dirs.d.ts +0 -8
  145. package/dist/utils/get-root-dirs.js +0 -25
  146. package/dist/utils/get-root-dirs.js.map +0 -1
  147. package/dist/utils/node-attributes.cjs +0 -67
  148. package/dist/utils/node-attributes.cjs.map +0 -1
  149. package/dist/utils/node-attributes.d.cts +0 -15
  150. package/dist/utils/node-attributes.d.ts +0 -15
  151. package/dist/utils/node-attributes.js +0 -46
  152. package/dist/utils/node-attributes.js.map +0 -1
  153. package/dist/utils/url.cjs +0 -167
  154. package/dist/utils/url.cjs.map +0 -1
  155. package/dist/utils/url.d.cts +0 -35
  156. package/dist/utils/url.d.ts +0 -35
  157. package/dist/utils/url.js +0 -128
  158. package/dist/utils/url.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,5 +1,8 @@
1
- // src/utils/define-rule.ts
2
- var defineRule = (rule) => rule;
1
+ // src/index.ts
2
+ import fs3 from "node:fs";
3
+
4
+ // src/rules/google-font-display.ts
5
+ import { URLSearchParams } from "node:url";
3
6
 
4
7
  // src/utils/node-attributes.ts
5
8
  var NodeAttributes = class {
@@ -45,12 +48,14 @@ var NodeAttributes = class {
45
48
  };
46
49
 
47
50
  // src/rules/google-font-display.ts
48
- var url = "https://nextjs.org/docs/messages/google-font-display";
49
- var googleFontDisplay = defineRule({
51
+ var name = "google-font-display";
52
+ var url = `https://nextjs.org/docs/messages/${name}`;
53
+ var googleFontDisplay = {
50
54
  create: (context) => ({
51
55
  JSXOpeningElement: (node) => {
52
- let message2;
53
- if (node.name.name !== "link") {
56
+ let messageId;
57
+ let data;
58
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "link") {
54
59
  return;
55
60
  }
56
61
  const attributes = new NodeAttributes(node);
@@ -60,17 +65,24 @@ var googleFontDisplay = defineRule({
60
65
  const hrefValue = attributes.value("href");
61
66
  const isGoogleFont = typeof hrefValue === "string" && hrefValue.startsWith("https://fonts.googleapis.com/css");
62
67
  if (isGoogleFont) {
63
- const params = new URLSearchParams(hrefValue.split("?", 2)[1]);
68
+ const queryPart = hrefValue.includes("?") ? hrefValue.substring(hrefValue.indexOf("?") + 1) : "";
69
+ const params = new URLSearchParams(queryPart);
64
70
  const displayValue = params.get("display");
65
71
  if (!params.has("display")) {
66
- message2 = "A font-display parameter is missing (adding `&display=optional` is recommended).";
72
+ messageId = "missingFontDisplay";
73
+ data = { url };
67
74
  } else if (displayValue === "auto" || displayValue === "block" || displayValue === "fallback") {
68
- message2 = `${displayValue[0]?.toUpperCase() + displayValue.slice(1)} is not recommended.`;
75
+ messageId = "notRecommendedFontDisplay";
76
+ data = {
77
+ display: displayValue[0]?.toUpperCase() + displayValue.slice(1),
78
+ url
79
+ };
69
80
  }
70
81
  }
71
- if (message2) {
82
+ if (messageId) {
72
83
  context.report({
73
- message: `${message2} See: ${url}`,
84
+ data,
85
+ messageId,
74
86
  node
75
87
  });
76
88
  }
@@ -82,17 +94,22 @@ var googleFontDisplay = defineRule({
82
94
  recommended: true,
83
95
  url
84
96
  },
97
+ messages: {
98
+ missingFontDisplay: "A font-display parameter is missing (adding `&display=optional` is recommended). See: {{url}}",
99
+ notRecommendedFontDisplay: "{{display}} is not recommended. See: {{url}}"
100
+ },
85
101
  schema: [],
86
102
  type: "problem"
87
103
  }
88
- });
104
+ };
89
105
 
90
106
  // src/rules/google-font-preconnect.ts
91
- var url2 = "https://nextjs.org/docs/messages/google-font-preconnect";
92
- var googleFontPreconnect = defineRule({
107
+ var name2 = "google-font-preconnect";
108
+ var url2 = `https://nextjs.org/docs/messages/${name2}`;
109
+ var googleFontPreconnect = {
93
110
  create: (context) => ({
94
111
  JSXOpeningElement: (node) => {
95
- if (node.name.name !== "link") {
112
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "link") {
96
113
  return;
97
114
  }
98
115
  const attributes = new NodeAttributes(node);
@@ -103,7 +120,8 @@ var googleFontPreconnect = defineRule({
103
120
  const preconnectMissing = !attributes.has("rel") || !attributes.hasValue("rel") || attributes.value("rel") !== "preconnect";
104
121
  if (typeof hrefValue === "string" && hrefValue.startsWith("https://fonts.gstatic.com") && preconnectMissing) {
105
122
  context.report({
106
- message: `\`rel="preconnect"\` is missing from Google Font. See: ${url2}`,
123
+ data: { url: url2 },
124
+ messageId: "missingPreconnect",
107
125
  node
108
126
  });
109
127
  }
@@ -115,27 +133,34 @@ var googleFontPreconnect = defineRule({
115
133
  recommended: true,
116
134
  url: url2
117
135
  },
136
+ messages: {
137
+ missingPreconnect: '`rel="preconnect"` is missing from Google Font. See: {{url}}'
138
+ },
118
139
  schema: [],
119
140
  type: "problem"
120
141
  }
121
- });
142
+ };
122
143
 
123
144
  // src/rules/inline-script-id.ts
124
- var url3 = "https://nextjs.org/docs/messages/inline-script-id";
125
- var inlineScriptId = defineRule({
145
+ var name3 = "inline-script-id";
146
+ var url3 = `https://nextjs.org/docs/messages/${name3}`;
147
+ var inlineScriptId = {
126
148
  create: (context) => {
127
149
  let nextScriptImportName = null;
128
150
  return {
129
151
  ImportDeclaration: (node) => {
130
- if (node.source.value === "next/script") {
131
- nextScriptImportName = node.specifiers[0].local.name;
152
+ if (node.source.value === "next/script" && node.specifiers.length > 0) {
153
+ const specifier = node.specifiers[0];
154
+ if (specifier && specifier.type === "ImportDefaultSpecifier") {
155
+ nextScriptImportName = specifier.local.name;
156
+ }
132
157
  }
133
158
  },
134
159
  JSXElement: (node) => {
135
160
  if (nextScriptImportName === null) {
136
161
  return;
137
162
  }
138
- if (node.openingElement?.name && node.openingElement.name.name !== nextScriptImportName) {
163
+ if (node.openingElement.name.type === "JSXIdentifier" && node.openingElement.name.name !== nextScriptImportName) {
139
164
  return;
140
165
  }
141
166
  const attributeNames = /* @__PURE__ */ new Set();
@@ -145,11 +170,15 @@ var inlineScriptId = defineRule({
145
170
  return;
146
171
  }
147
172
  if (attribute.type === "JSXAttribute") {
148
- attributeNames.add(attribute.name.name);
173
+ if (attribute.name.type === "JSXIdentifier") {
174
+ attributeNames.add(attribute.name.name);
175
+ }
149
176
  } else if (attribute.type === "JSXSpreadAttribute") {
150
- if (attribute.argument?.properties) {
177
+ if (attribute.argument.type === "ObjectExpression") {
151
178
  attribute.argument.properties.forEach((property) => {
152
- attributeNames.add(property.key.name);
179
+ if (property.type === "Property" && property.key.type === "Identifier") {
180
+ attributeNames.add(property.key.name);
181
+ }
153
182
  });
154
183
  } else {
155
184
  hasNonCheckableSpreadAttribute = true;
@@ -162,7 +191,8 @@ var inlineScriptId = defineRule({
162
191
  if (node.children.length > 0 || attributeNames.has("dangerouslySetInnerHTML")) {
163
192
  if (!attributeNames.has("id")) {
164
193
  context.report({
165
- message: `\`next/script\` components with inline content must specify an \`id\` attribute. See: ${url3}`,
194
+ data: { url: url3 },
195
+ messageId: "missingId",
166
196
  node
167
197
  });
168
198
  }
@@ -176,10 +206,13 @@ var inlineScriptId = defineRule({
176
206
  recommended: true,
177
207
  url: url3
178
208
  },
209
+ messages: {
210
+ missingId: "`next/script` components with inline content must specify an `id` attribute. See: {{url}}"
211
+ },
179
212
  schema: [],
180
213
  type: "problem"
181
214
  }
182
- });
215
+ };
183
216
 
184
217
  // src/rules/next-script-for-ga.ts
185
218
  var SUPPORTED_SRCS = [
@@ -190,16 +223,16 @@ var SUPPORTED_HTML_CONTENT_URLS = [
190
223
  "www.google-analytics.com/analytics.js",
191
224
  "www.googletagmanager.com/gtm.js"
192
225
  ];
226
+ var name4 = "next-script-for-ga";
227
+ var url4 = `https://nextjs.org/docs/messages/${name4}`;
193
228
  var description = "Prefer `next/script` component when using the inline script for Google Analytics.";
194
- var url4 = "https://nextjs.org/docs/messages/next-script-for-ga";
195
- var ERROR_MSG = `${description} See: ${url4}`;
196
229
  var containsStr = (str, strList) => {
197
230
  return strList.some((s) => str.includes(s));
198
231
  };
199
- var nextScriptForGa = defineRule({
232
+ var nextScriptForGa = {
200
233
  create: (context) => ({
201
234
  JSXOpeningElement: (node) => {
202
- if (node.name.name !== "script") {
235
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "script") {
203
236
  return;
204
237
  }
205
238
  if (node.attributes.length === 0) {
@@ -207,16 +240,19 @@ var nextScriptForGa = defineRule({
207
240
  }
208
241
  const attributes = new NodeAttributes(node);
209
242
  if (typeof attributes.value("src") === "string" && containsStr(attributes.value("src"), SUPPORTED_SRCS)) {
210
- return context.report({
211
- message: ERROR_MSG,
243
+ context.report({
244
+ data: { url: url4 },
245
+ messageId: "useNextScript",
212
246
  node
213
247
  });
248
+ return;
214
249
  }
215
250
  if (attributes.value("dangerouslySetInnerHTML") && attributes.value("dangerouslySetInnerHTML").length > 0) {
216
251
  const htmlContent = attributes.value("dangerouslySetInnerHTML")[0].value.quasis?.[0].value.raw;
217
252
  if (htmlContent && containsStr(htmlContent, SUPPORTED_HTML_CONTENT_URLS)) {
218
253
  context.report({
219
- message: ERROR_MSG,
254
+ data: { url: url4 },
255
+ messageId: "useNextScript",
220
256
  node
221
257
  });
222
258
  }
@@ -229,19 +265,23 @@ var nextScriptForGa = defineRule({
229
265
  recommended: true,
230
266
  url: url4
231
267
  },
268
+ messages: {
269
+ useNextScript: "Prefer `next/script` component when using the inline script for Google Analytics. See: {{url}}"
270
+ },
232
271
  schema: [],
233
272
  type: "problem"
234
273
  }
235
- });
274
+ };
236
275
 
237
276
  // src/rules/no-assign-module-variable.ts
238
- var url5 = "https://nextjs.org/docs/messages/no-assign-module-variable";
239
- var noAssignModuleVariable = defineRule({
277
+ var name5 = "no-assign-module-variable";
278
+ var url5 = `https://nextjs.org/docs/messages/${name5}`;
279
+ var noAssignModuleVariable = {
240
280
  create: (context) => ({
241
281
  VariableDeclaration: (node) => {
242
282
  const moduleVariableFound = node.declarations.some((declaration) => {
243
- if ("name" in declaration.id) {
244
- return declaration.id.name === "module";
283
+ if (declaration.id.type === "Identifier" && declaration.id.name === "module") {
284
+ return true;
245
285
  }
246
286
  return false;
247
287
  });
@@ -249,7 +289,8 @@ var noAssignModuleVariable = defineRule({
249
289
  return;
250
290
  }
251
291
  context.report({
252
- message: `Do not assign to the variable \`module\`. See: ${url5}`,
292
+ data: { url: url5 },
293
+ messageId: "noAssignModule",
253
294
  node
254
295
  });
255
296
  }
@@ -260,17 +301,20 @@ var noAssignModuleVariable = defineRule({
260
301
  recommended: true,
261
302
  url: url5
262
303
  },
304
+ messages: {
305
+ noAssignModule: "Do not assign to the variable `module`. See: {{url}}"
306
+ },
263
307
  schema: [],
264
308
  type: "problem"
265
309
  }
266
- });
310
+ };
267
311
 
268
312
  // src/rules/no-async-client-component.ts
269
- var url6 = "https://nextjs.org/docs/messages/no-async-client-component";
313
+ var name6 = "no-async-client-component";
314
+ var url6 = `https://nextjs.org/docs/messages/${name6}`;
270
315
  var description2 = "Prevent client components from being async functions.";
271
- var message = `${description2} See: ${url6}`;
272
316
  var isCapitalized = (str) => /[A-Z]/.test(str[0] ?? "");
273
- var noAsyncClientComponent = defineRule({
317
+ var noAsyncClientComponent = {
274
318
  create: (context) => ({
275
319
  Program: (node) => {
276
320
  let isClientComponent = false;
@@ -279,9 +323,10 @@ var noAsyncClientComponent = defineRule({
279
323
  isClientComponent = true;
280
324
  }
281
325
  if (block.type === "ExportDefaultDeclaration" && isClientComponent) {
282
- if (block.declaration?.type === "FunctionDeclaration" && block.declaration.async && isCapitalized(block.declaration.id.name)) {
326
+ if (block.declaration.type === "FunctionDeclaration" && block.declaration.async && block.declaration.id && isCapitalized(block.declaration.id.name)) {
283
327
  context.report({
284
- message,
328
+ data: { url: url6 },
329
+ messageId: "noAsyncClientComponent",
285
330
  node: block
286
331
  });
287
332
  }
@@ -292,7 +337,7 @@ var noAsyncClientComponent = defineRule({
292
337
  return true;
293
338
  }
294
339
  if (localBlock.type === "VariableDeclaration" && localBlock.declarations.find(
295
- (declaration) => declaration.id?.type === "Identifier" && declaration.id.name === targetName
340
+ (declaration) => declaration.id.type === "Identifier" && declaration.id.name === targetName
296
341
  )) {
297
342
  return true;
298
343
  }
@@ -300,17 +345,19 @@ var noAsyncClientComponent = defineRule({
300
345
  });
301
346
  if (functionDeclaration?.type === "FunctionDeclaration" && functionDeclaration.async) {
302
347
  context.report({
303
- message,
348
+ data: { url: url6 },
349
+ messageId: "noAsyncClientComponent",
304
350
  node: functionDeclaration
305
351
  });
306
352
  }
307
353
  if (functionDeclaration?.type === "VariableDeclaration") {
308
354
  const varDeclarator = functionDeclaration.declarations.find(
309
- (declaration) => declaration.id?.type === "Identifier" && declaration.id.name === targetName
355
+ (declaration) => declaration.id.type === "Identifier" && declaration.id.name === targetName
310
356
  );
311
357
  if (varDeclarator?.init?.type === "ArrowFunctionExpression" && varDeclarator.init.async) {
312
358
  context.report({
313
- message,
359
+ data: { url: url6 },
360
+ messageId: "noAsyncClientComponent",
314
361
  node: functionDeclaration
315
362
  });
316
363
  }
@@ -326,16 +373,20 @@ var noAsyncClientComponent = defineRule({
326
373
  recommended: true,
327
374
  url: url6
328
375
  },
376
+ messages: {
377
+ noAsyncClientComponent: "Prevent client components from being async functions. See: {{url}}"
378
+ },
329
379
  schema: [],
330
380
  type: "problem"
331
381
  }
332
- });
382
+ };
333
383
 
334
384
  // src/rules/no-before-interactive-script-outside-document.ts
335
385
  import * as path from "node:path";
336
- var url7 = "https://nextjs.org/docs/messages/no-before-interactive-script-outside-document";
386
+ var name7 = "no-before-interactive-script-outside-document";
387
+ var url7 = `https://nextjs.org/docs/messages/${name7}`;
337
388
  var convertToCorrectSeparator = (str) => str.replaceAll(/[/\\]/g, path.sep);
338
- var noBeforeInteractiveScriptOutsideDocument = defineRule({
389
+ var noBeforeInteractiveScriptOutsideDocument = {
339
390
  create: (context) => {
340
391
  let scriptImportName = null;
341
392
  return {
@@ -351,13 +402,13 @@ var noBeforeInteractiveScriptOutsideDocument = defineRule({
351
402
  if (!scriptImportName) {
352
403
  return;
353
404
  }
354
- if (node.name && node.name.name !== scriptImportName) {
405
+ if (node.name.type === "JSXIdentifier" && node.name.name !== scriptImportName) {
355
406
  return;
356
407
  }
357
408
  const strategy = node.attributes.find(
358
- (child) => child.name && child.name.name === "strategy"
409
+ (child) => child.type === "JSXAttribute" && child.name.type === "JSXIdentifier" && child.name.name === "strategy"
359
410
  );
360
- if (!strategy?.value || strategy.value.value !== "beforeInteractive") {
411
+ if (!strategy?.value || strategy.value.type !== "Literal" || strategy.value.value !== "beforeInteractive") {
361
412
  return;
362
413
  }
363
414
  const document = context.filename.split("pages", 2)[1];
@@ -365,7 +416,8 @@ var noBeforeInteractiveScriptOutsideDocument = defineRule({
365
416
  return;
366
417
  }
367
418
  context.report({
368
- message: `\`next/script\`'s \`beforeInteractive\` strategy should not be used outside of \`pages/_document.js\`. See: ${url7}`,
419
+ data: { url: url7 },
420
+ messageId: "noBeforeInteractiveOutsideDocument",
369
421
  node
370
422
  });
371
423
  }
@@ -377,17 +429,21 @@ var noBeforeInteractiveScriptOutsideDocument = defineRule({
377
429
  recommended: true,
378
430
  url: url7
379
431
  },
432
+ messages: {
433
+ noBeforeInteractiveOutsideDocument: "`next/script`'s `beforeInteractive` strategy should not be used outside of `pages/_document.js`. See: {{url}}"
434
+ },
380
435
  schema: [],
381
436
  type: "problem"
382
437
  }
383
- });
438
+ };
384
439
 
385
440
  // src/rules/no-css-tags.ts
386
- var url8 = "https://nextjs.org/docs/messages/no-css-tags";
387
- var noCssTags = defineRule({
441
+ var name8 = "no-css-tags";
442
+ var url8 = `https://nextjs.org/docs/messages/${name8}`;
443
+ var noCssTags = {
388
444
  create: (context) => ({
389
445
  JSXOpeningElement: (node) => {
390
- if (node.name.name !== "link") {
446
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "link") {
391
447
  return;
392
448
  }
393
449
  if (node.attributes.length === 0) {
@@ -397,12 +453,13 @@ var noCssTags = defineRule({
397
453
  (attr) => attr.type === "JSXAttribute"
398
454
  );
399
455
  if (attributes.find(
400
- (attr) => attr.name.name === "rel" && attr.value.value === "stylesheet"
456
+ (attr) => attr.name.type === "JSXIdentifier" && attr.name.name === "rel" && attr.value && attr.value.type === "Literal" && attr.value.value === "stylesheet"
401
457
  ) && attributes.find(
402
- (attr) => attr.name.name === "href" && attr.value.type === "Literal" && !/^https?/.test(attr.value.value)
458
+ (attr) => attr.name.type === "JSXIdentifier" && attr.name.name === "href" && attr.value && attr.value.type === "Literal" && typeof attr.value.value === "string" && !/^https?/.test(attr.value.value)
403
459
  )) {
404
460
  context.report({
405
- message: `Do not include stylesheets manually. See: ${url8}`,
461
+ data: { url: url8 },
462
+ messageId: "noCssTags",
406
463
  node
407
464
  });
408
465
  }
@@ -414,15 +471,19 @@ var noCssTags = defineRule({
414
471
  recommended: true,
415
472
  url: url8
416
473
  },
474
+ messages: {
475
+ noCssTags: "Do not include stylesheets manually. See: {{url}}"
476
+ },
417
477
  schema: [],
418
478
  type: "problem"
419
479
  }
420
- });
480
+ };
421
481
 
422
482
  // src/rules/no-document-import-in-page.ts
423
483
  import * as path2 from "node:path";
424
- var url9 = "https://nextjs.org/docs/messages/no-document-import-in-page";
425
- var noDocumentImportInPage = defineRule({
484
+ var name9 = "no-document-import-in-page";
485
+ var url9 = `https://nextjs.org/docs/messages/${name9}`;
486
+ var noDocumentImportInPage = {
426
487
  create: (context) => ({
427
488
  ImportDeclaration: (node) => {
428
489
  if (node.source.value !== "next/document") {
@@ -434,7 +495,8 @@ var noDocumentImportInPage = defineRule({
434
495
  return;
435
496
  }
436
497
  context.report({
437
- message: `\`<Document />\` from \`next/document\` should not be imported outside of \`pages/_document.js\`. See: ${url9}`,
498
+ data: { url: url9 },
499
+ messageId: "noDocumentImportInPage",
438
500
  node
439
501
  });
440
502
  }
@@ -445,14 +507,18 @@ var noDocumentImportInPage = defineRule({
445
507
  recommended: true,
446
508
  url: url9
447
509
  },
510
+ messages: {
511
+ noDocumentImportInPage: "`<Document />` from `next/document` should not be imported outside of `pages/_document.js`. See: {{url}}"
512
+ },
448
513
  schema: [],
449
514
  type: "problem"
450
515
  }
451
- });
516
+ };
452
517
 
453
518
  // src/rules/no-duplicate-head.ts
454
- var url10 = "https://nextjs.org/docs/messages/no-duplicate-head";
455
- var noDuplicateHead = defineRule({
519
+ var name10 = "no-duplicate-head";
520
+ var url10 = `https://nextjs.org/docs/messages/${name10}`;
521
+ var noDuplicateHead = {
456
522
  create: (context) => {
457
523
  const { sourceCode } = context;
458
524
  let documentImportName = null;
@@ -460,7 +526,7 @@ var noDuplicateHead = defineRule({
460
526
  ImportDeclaration: (node) => {
461
527
  if (node.source.value === "next/document") {
462
528
  const documentImport = node.specifiers.find(
463
- ({ type }) => type === "ImportDefaultSpecifier"
529
+ (specifier) => specifier.type === "ImportDefaultSpecifier"
464
530
  );
465
531
  if (documentImport?.local) {
466
532
  documentImportName = documentImport.local.name;
@@ -470,21 +536,20 @@ var noDuplicateHead = defineRule({
470
536
  ReturnStatement: (node) => {
471
537
  const ancestors = sourceCode.getAncestors(node);
472
538
  const documentClass = ancestors.find(
473
- (ancestorNode) => ancestorNode.type === "ClassDeclaration" && ancestorNode.superClass && "name" in ancestorNode.superClass && ancestorNode.superClass.name === documentImportName
539
+ (ancestorNode) => ancestorNode.type === "ClassDeclaration" && ancestorNode.superClass && ancestorNode.superClass.type === "Identifier" && ancestorNode.superClass.name === documentImportName
474
540
  );
475
541
  if (!documentClass) {
476
542
  return;
477
543
  }
478
- if (node.argument && "children" in node.argument && // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
479
- node.argument.children) {
544
+ if (node.argument && node.argument.type === "JSXElement") {
480
545
  const headComponents = node.argument.children.filter(
481
- (childrenNode) => childrenNode.openingElement?.name && childrenNode.openingElement.name.name === "Head"
482
- );
546
+ (childrenNode) => childrenNode.type === "JSXElement" && childrenNode.openingElement.name.type === "JSXIdentifier" && childrenNode.openingElement.name.name === "Head"
547
+ ).filter(Boolean);
483
548
  if (headComponents.length > 1) {
484
549
  for (let i = 1; i < headComponents.length; i++) {
485
550
  context.report({
486
- message: `Do not include multiple instances of \`<Head/>\`. See: ${url10}`,
487
- // @ts-expect-error initial override, TODO: fix
551
+ data: { url: url10 },
552
+ messageId: "noDuplicateHead",
488
553
  node: headComponents[i]
489
554
  });
490
555
  }
@@ -499,28 +564,32 @@ var noDuplicateHead = defineRule({
499
564
  recommended: true,
500
565
  url: url10
501
566
  },
567
+ messages: {
568
+ noDuplicateHead: "Do not include multiple instances of `<Head/>`. See: {{url}}"
569
+ },
502
570
  schema: [],
503
571
  type: "problem"
504
572
  }
505
- });
573
+ };
506
574
 
507
575
  // src/rules/no-head-element.ts
508
576
  import path3 from "node:path";
509
- var url11 = "https://nextjs.org/docs/messages/no-head-element";
510
- var noHeadElement = defineRule({
577
+ var name11 = "no-head-element";
578
+ var url11 = `https://nextjs.org/docs/messages/${name11}`;
579
+ var noHeadElement = {
511
580
  create: (context) => ({
512
581
  JSXOpeningElement: (node) => {
513
582
  const paths = context.filename;
514
583
  const isInAppDir = () => (
515
- // TODO: fix
516
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
584
+ // Check if we're in the app directory using either platform separator
517
585
  paths.includes(`app${path3.sep}`) || paths.includes(`app${path3.posix.sep}`)
518
586
  );
519
- if (node.name.name !== "head" || isInAppDir()) {
587
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "head" || isInAppDir()) {
520
588
  return;
521
589
  }
522
590
  context.report({
523
- message: `Do not use \`<head>\` element. Use \`<Head />\` from \`next/head\` instead. See: ${url11}`,
591
+ data: { url: url11 },
592
+ messageId: "noHeadElement",
524
593
  node
525
594
  });
526
595
  }
@@ -532,15 +601,19 @@ var noHeadElement = defineRule({
532
601
  recommended: true,
533
602
  url: url11
534
603
  },
604
+ messages: {
605
+ noHeadElement: "Do not use `<head>` element. Use `<Head />` from `next/head` instead. See: {{url}}"
606
+ },
535
607
  schema: [],
536
608
  type: "problem"
537
609
  }
538
- });
610
+ };
539
611
 
540
612
  // src/rules/no-head-import-in-document.ts
541
613
  import * as path4 from "node:path";
542
- var url12 = "https://nextjs.org/docs/messages/no-head-import-in-document";
543
- var noHeadImportInDocument = defineRule({
614
+ var name12 = "no-head-import-in-document";
615
+ var url12 = `https://nextjs.org/docs/messages/${name12}`;
616
+ var noHeadImportInDocument = {
544
617
  create: (context) => ({
545
618
  ImportDeclaration: (node) => {
546
619
  if (node.source.value !== "next/head") {
@@ -550,10 +623,11 @@ var noHeadImportInDocument = defineRule({
550
623
  if (!document) {
551
624
  return;
552
625
  }
553
- const { dir, name } = path4.parse(document);
554
- if (name.startsWith("_document") || dir === "/_document" && name === "index") {
626
+ const { dir, name: name22 } = path4.parse(document);
627
+ if (name22.startsWith("_document") || dir === "/_document" && name22 === "index") {
555
628
  context.report({
556
- message: `\`next/head\` should not be imported in \`pages${document}\`. Use \`<Head />\` from \`next/document\` instead. See: ${url12}`,
629
+ data: { document, url: url12 },
630
+ messageId: "noHeadImportInDocument",
557
631
  node
558
632
  });
559
633
  }
@@ -565,10 +639,13 @@ var noHeadImportInDocument = defineRule({
565
639
  recommended: true,
566
640
  url: url12
567
641
  },
642
+ messages: {
643
+ noHeadImportInDocument: "`next/head` should not be imported in `pages{{document}}`. Use `<Head />` from `next/document` instead. See: {{url}}"
644
+ },
568
645
  schema: [],
569
646
  type: "problem"
570
647
  }
571
- });
648
+ };
572
649
 
573
650
  // src/rules/no-html-link-for-pages.ts
574
651
  import * as fs2 from "node:fs";
@@ -649,18 +726,18 @@ var parseUrlForAppDir = (urlprefix, directory) => {
649
726
  });
650
727
  return res;
651
728
  };
652
- var normalizeURL = (url21) => {
653
- if (!url21) {
729
+ var normalizeURL = (url22) => {
730
+ if (!url22) {
654
731
  return;
655
732
  }
656
- url21 = url21.split("?", 1)[0];
657
- url21 = url21.split("#", 1)[0];
658
- url21 = url21.replace(/(?<temp1>\/index\.html)$/, "/");
659
- if (url21 === "") {
660
- return url21;
733
+ url22 = url22.split("?", 1)[0];
734
+ url22 = url22.split("#", 1)[0];
735
+ url22 = url22.replace(/(?<temp1>\/index\.html)$/, "/");
736
+ if (url22 === "") {
737
+ return url22;
661
738
  }
662
- url21 = url21.endsWith("/") ? url21 : `${url21}/`;
663
- return url21;
739
+ url22 = url22.endsWith("/") ? url22 : `${url22}/`;
740
+ return url22;
664
741
  };
665
742
  var normalizeAppPath = (route) => ensureLeadingSlash(
666
743
  route.split("/").reduce((pathname, segment, index, segments) => {
@@ -684,7 +761,7 @@ var getUrlFromPagesDirectories = (urlPrefix, directories) => Array.from(
684
761
  new Set(
685
762
  directories.flatMap((directory) => parseUrlForPages(urlPrefix, directory)).map(
686
763
  // Since the URLs are normalized we add `^` and `$` to the RegExp to make sure they match exactly.
687
- (url21) => `^${normalizeURL(url21)}$`
764
+ (url22) => `^${normalizeURL(url22)}$`
688
765
  )
689
766
  )
690
767
  ).map((urlReg) => {
@@ -696,7 +773,7 @@ var getUrlFromAppDirectory = (urlPrefix, directories) => Array.from(
696
773
  new Set(
697
774
  directories.map((directory) => parseUrlForAppDir(urlPrefix, directory)).flat().map(
698
775
  // Since the URLs are normalized we add `^` and `$` to the RegExp to make sure they match exactly.
699
- (url21) => `^${normalizeAppPath(url21)}$`
776
+ (url22) => `^${normalizeAppPath(url22)}$`
700
777
  )
701
778
  )
702
779
  ).map((urlReg) => {
@@ -725,23 +802,27 @@ var pagesDirWarning = execOnce((pagesDirs) => {
725
802
  });
726
803
  var fsExistsSyncCache = {};
727
804
  var memoize = (fn) => {
728
- const cache = {};
729
- return (...args) => {
805
+ const cache = /* @__PURE__ */ new Map();
806
+ const memoized = (...args) => {
730
807
  const key = JSON.stringify(args);
731
- cache[key] ??= fn(...args);
732
- return cache[key];
808
+ if (!cache.has(key)) {
809
+ cache.set(key, fn(...args));
810
+ }
811
+ const value = cache.get(key);
812
+ return value;
733
813
  };
814
+ return memoized;
734
815
  };
735
816
  var cachedGetUrlFromPagesDirectories = memoize(getUrlFromPagesDirectories);
736
817
  var cachedGetUrlFromAppDirectory = memoize(getUrlFromAppDirectory);
737
- var url13 = "https://nextjs.org/docs/messages/no-html-link-for-pages";
738
- var noHtmlLinkForPages = defineRule({
818
+ var name13 = "no-html-link-for-pages";
819
+ var url13 = `https://nextjs.org/docs/messages/${name13}`;
820
+ var noHtmlLinkForPages = {
739
821
  /**
740
822
  * Creates an ESLint rule listener.
741
823
  */
742
824
  create: (context) => {
743
- const ruleOptions = context.options;
744
- const [customPagesDirectory] = ruleOptions;
825
+ const [customPagesDirectory] = context.options;
745
826
  const rootDirs = getRootDirs(context);
746
827
  const pagesDirs = (customPagesDirectory ? [customPagesDirectory] : rootDirs.map((dir) => [
747
828
  path6.join(dir, "pages"),
@@ -765,26 +846,26 @@ var noHtmlLinkForPages = defineRule({
765
846
  const allUrlRegex = [...pageUrls, ...appDirUrls];
766
847
  return {
767
848
  JSXOpeningElement: (node) => {
768
- if (node.name.name !== "a") {
849
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "a") {
769
850
  return;
770
851
  }
771
852
  if (node.attributes.length === 0) {
772
853
  return;
773
854
  }
774
855
  const target = node.attributes.find(
775
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "target"
856
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "target"
776
857
  );
777
- if (target && target.value.value === "_blank") {
858
+ if (target?.value?.type === "Literal" && target.value.value === "_blank") {
778
859
  return;
779
860
  }
780
861
  const href = node.attributes.find(
781
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "href"
862
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "href"
782
863
  );
783
- if (!href || href.value && href.value.type !== "Literal") {
864
+ if (!href?.value || href.value.type !== "Literal") {
784
865
  return;
785
866
  }
786
867
  const hasDownloadAttr = node.attributes.find(
787
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "download"
868
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "download"
788
869
  );
789
870
  if (hasDownloadAttr) {
790
871
  return;
@@ -796,7 +877,8 @@ var noHtmlLinkForPages = defineRule({
796
877
  allUrlRegex.forEach((foundUrl) => {
797
878
  if (hrefPath && foundUrl.test(normalizeURL(hrefPath))) {
798
879
  context.report({
799
- message: `Do not use an \`<a>\` element to navigate to \`${hrefPath}\`. Use \`<Link />\` from \`next/link\` instead. See: ${url13}`,
880
+ data: { hrefPath, url: url13 },
881
+ messageId: "noHtmlLinkForPages",
800
882
  node
801
883
  });
802
884
  }
@@ -811,6 +893,9 @@ var noHtmlLinkForPages = defineRule({
811
893
  recommended: true,
812
894
  url: url13
813
895
  },
896
+ messages: {
897
+ noHtmlLinkForPages: "Do not use an `<a>` element to navigate to `{{hrefPath}}`. Use `<Link />` from `next/link` instead. See: {{url}}"
898
+ },
814
899
  schema: [
815
900
  {
816
901
  oneOf: [
@@ -829,31 +914,35 @@ var noHtmlLinkForPages = defineRule({
829
914
  ],
830
915
  type: "problem"
831
916
  }
832
- });
917
+ };
833
918
 
834
919
  // src/rules/no-img-element.ts
835
920
  import path7 from "node:path";
836
- var url14 = "https://nextjs.org/docs/messages/no-img-element";
837
- var noImgElement = defineRule({
921
+ var name14 = "no-img-element";
922
+ var url14 = `https://nextjs.org/docs/messages/${name14}`;
923
+ var noImgElement = {
838
924
  create: (context) => {
839
925
  const relativePath = context.filename.replace(path7.sep, "/").replace(context.cwd, "").replace(/^\//, "");
840
926
  const isAppDir = /^(?<temp1>src\/)?app\//.test(relativePath);
841
927
  return {
842
928
  JSXOpeningElement: (node) => {
843
- if (node.name.name !== "img") {
929
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "img") {
844
930
  return;
845
931
  }
846
932
  if (node.attributes.length === 0) {
847
933
  return;
848
934
  }
849
- if (node.parent?.parent?.openingElement?.name?.name === "picture") {
935
+ const parentJSXElement = node.parent;
936
+ const grandParentJSXElement = parentJSXElement?.parent;
937
+ if (grandParentJSXElement?.openingElement?.name?.type === "JSXIdentifier" && grandParentJSXElement?.openingElement?.name?.name === "picture") {
850
938
  return;
851
939
  }
852
940
  if (isAppDir && /\/opengraph-image|twitter-image|icon\.\w+$/.test(relativePath)) {
853
941
  return;
854
942
  }
855
943
  context.report({
856
- 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: ${url14}`,
944
+ data: { url: url14 },
945
+ messageId: "noImgElement",
857
946
  node
858
947
  });
859
948
  }
@@ -866,16 +955,20 @@ var noImgElement = defineRule({
866
955
  recommended: true,
867
956
  url: url14
868
957
  },
958
+ messages: {
959
+ noImgElement: "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}}"
960
+ },
869
961
  schema: [],
870
962
  type: "problem"
871
963
  }
872
- });
964
+ };
873
965
 
874
966
  // src/rules/no-page-custom-font.ts
875
967
  import { posix as posix2, sep as sep3 } from "node:path";
876
- var url15 = "https://nextjs.org/docs/messages/no-page-custom-font";
968
+ var name15 = "no-page-custom-font";
969
+ var url15 = `https://nextjs.org/docs/messages/${name15}`;
877
970
  var isIdentifierMatch = (id1, id2) => id1 === null && id2 === null || id1 && id2 && id1.name === id2.name;
878
- var noPageCustomFont = defineRule({
971
+ var noPageCustomFont = {
879
972
  create: (context) => {
880
973
  const { sourceCode } = context;
881
974
  const paths = context.filename.split("pages");
@@ -883,12 +976,9 @@ var noPageCustomFont = defineRule({
883
976
  if (!page) {
884
977
  return {};
885
978
  }
886
- const isDocument = (
887
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
888
- page.startsWith(`${sep3}_document`) || page.startsWith(`${posix2.sep}_document`)
889
- );
979
+ const isDocument = page.startsWith(`${sep3}_document`) || page.startsWith(`${posix2.sep}_document`);
890
980
  let documentImportName;
891
- let localDefaultExportId;
981
+ let localDefaultExportId = null;
892
982
  let exportDeclarationType;
893
983
  return {
894
984
  ExportDefaultDeclaration: (node) => {
@@ -897,14 +987,14 @@ var noPageCustomFont = defineRule({
897
987
  localDefaultExportId = node.declaration.id;
898
988
  return;
899
989
  }
900
- if (node.declaration.type === "ClassDeclaration" && node.declaration.superClass && "name" in node.declaration.superClass && node.declaration.superClass.name === documentImportName) {
990
+ if (node.declaration.type === "ClassDeclaration" && node.declaration.superClass && node.declaration.superClass.type === "Identifier" && node.declaration.superClass.name === documentImportName) {
901
991
  localDefaultExportId = node.declaration.id;
902
992
  }
903
993
  },
904
994
  ImportDeclaration: (node) => {
905
995
  if (node.source.value === "next/document") {
906
996
  const documentImport = node.specifiers.find(
907
- ({ type }) => type === "ImportDefaultSpecifier"
997
+ (specifier) => specifier.type === "ImportDefaultSpecifier"
908
998
  );
909
999
  if (documentImport?.local) {
910
1000
  documentImportName = documentImport.local.name;
@@ -912,7 +1002,7 @@ var noPageCustomFont = defineRule({
912
1002
  }
913
1003
  },
914
1004
  JSXOpeningElement: (node) => {
915
- if (node.name.name !== "link") {
1005
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "link") {
916
1006
  return;
917
1007
  }
918
1008
  const ancestors = sourceCode.getAncestors(node);
@@ -920,6 +1010,9 @@ var noPageCustomFont = defineRule({
920
1010
  const program = ancestors.find(
921
1011
  (ancestor) => ancestor.type === "Program"
922
1012
  );
1013
+ if (!program?.tokens) {
1014
+ return;
1015
+ }
923
1016
  for (let i = 0; i <= program.tokens.length - 1; i++) {
924
1017
  if (localDefaultExportId) {
925
1018
  break;
@@ -927,10 +1020,20 @@ var noPageCustomFont = defineRule({
927
1020
  const token = program.tokens[i];
928
1021
  if (token?.type === "Keyword" && token.value === "export") {
929
1022
  const nextToken = program.tokens[i + 1];
930
- if (nextToken && nextToken.type === "Keyword" && nextToken.value === "default") {
1023
+ if (nextToken && nextToken.value === "default") {
931
1024
  const maybeIdentifier = program.tokens[i + 2];
932
1025
  if (maybeIdentifier && maybeIdentifier.type === "Identifier") {
933
- localDefaultExportId = { name: maybeIdentifier.value };
1026
+ localDefaultExportId = {
1027
+ decorators: [],
1028
+ loc: {
1029
+ end: { column: 0, line: 0 },
1030
+ start: { column: 0, line: 0 }
1031
+ },
1032
+ name: maybeIdentifier.value,
1033
+ optional: false,
1034
+ range: [0, 0],
1035
+ type: "Identifier"
1036
+ };
934
1037
  }
935
1038
  }
936
1039
  }
@@ -938,7 +1041,7 @@ var noPageCustomFont = defineRule({
938
1041
  }
939
1042
  const parentComponent = ancestors.find((ancestor) => {
940
1043
  if (exportDeclarationType === "ClassDeclaration") {
941
- return ancestor.type === exportDeclarationType && "superClass" in ancestor && ancestor.superClass && "name" in ancestor.superClass && ancestor.superClass.name === documentImportName;
1044
+ return ancestor.type === exportDeclarationType && "superClass" in ancestor && ancestor.superClass && ancestor.superClass.type === "Identifier" && ancestor.superClass.name === documentImportName;
942
1045
  }
943
1046
  if ("id" in ancestor) {
944
1047
  if (exportDeclarationType === "FunctionDeclaration") {
@@ -958,10 +1061,9 @@ var noPageCustomFont = defineRule({
958
1061
  const hrefValue = attributes.value("href");
959
1062
  const isGoogleFont = typeof hrefValue === "string" && hrefValue.startsWith("https://fonts.googleapis.com/css");
960
1063
  if (isGoogleFont) {
961
- const end = `This is discouraged. See: ${url15}`;
962
- const message2 = isDocument ? `Using \`<link />\` outside of \`<Head>\` will disable automatic font optimization. ${end}` : `Custom fonts not added in \`pages/_document.js\` will only load for a single page. ${end}`;
963
1064
  context.report({
964
- message: message2,
1065
+ data: { url: url15 },
1066
+ messageId: isDocument ? "noPageCustomFontOutsideHead" : "noPageCustomFont",
965
1067
  node
966
1068
  });
967
1069
  }
@@ -974,16 +1076,36 @@ var noPageCustomFont = defineRule({
974
1076
  recommended: true,
975
1077
  url: url15
976
1078
  },
1079
+ messages: {
1080
+ noPageCustomFont: "Custom fonts not added in `pages/_document.js` will only load for a single page. This is discouraged. See: {{url}}",
1081
+ noPageCustomFontOutsideHead: "Using `<link />` outside of `<Head>` will disable automatic font optimization. This is discouraged. See: {{url}}"
1082
+ },
977
1083
  schema: [],
978
1084
  type: "problem"
979
1085
  }
980
- });
1086
+ };
981
1087
 
982
1088
  // src/rules/no-script-component-in-head.ts
983
- var url16 = "https://nextjs.org/docs/messages/no-script-component-in-head";
984
- var noScriptComponentInHead = defineRule({
1089
+ var name16 = "no-script-component-in-head";
1090
+ var url16 = `https://nextjs.org/docs/messages/${name16}`;
1091
+ var noScriptComponentInHead = {
985
1092
  create: (context) => {
986
1093
  let isNextHead = null;
1094
+ const findNestedScriptComponent = (node) => {
1095
+ if (node.type !== "JSXElement") {
1096
+ return null;
1097
+ }
1098
+ if (node.openingElement.name.type === "JSXIdentifier" && node.openingElement.name.name === "Script") {
1099
+ return node;
1100
+ }
1101
+ for (const child of node.children) {
1102
+ const scriptComponent = findNestedScriptComponent(child);
1103
+ if (scriptComponent) {
1104
+ return scriptComponent;
1105
+ }
1106
+ }
1107
+ return null;
1108
+ };
987
1109
  return {
988
1110
  ImportDeclaration: (node) => {
989
1111
  if (node.source.value === "next/head") {
@@ -994,15 +1116,14 @@ var noScriptComponentInHead = defineRule({
994
1116
  if (!isNextHead) {
995
1117
  return;
996
1118
  }
997
- if (node.openingElement?.name && node.openingElement.name.name !== "Head") {
1119
+ if (node.openingElement.name.type !== "JSXIdentifier" || node.openingElement.name.name !== "Head") {
998
1120
  return;
999
1121
  }
1000
- const scriptTag = node.children.find(
1001
- (child) => child.openingElement?.name && child.openingElement.name.name === "Script"
1002
- );
1122
+ const scriptTag = findNestedScriptComponent(node);
1003
1123
  if (scriptTag) {
1004
1124
  context.report({
1005
- message: `\`next/script\` should not be used in \`next/head\` component. Move \`<Script />\` outside of \`<Head>\` instead. See: ${url16}`,
1125
+ data: { url: url16 },
1126
+ messageId: "noScriptComponentInHead",
1006
1127
  node
1007
1128
  });
1008
1129
  }
@@ -1015,30 +1136,35 @@ var noScriptComponentInHead = defineRule({
1015
1136
  recommended: true,
1016
1137
  url: url16
1017
1138
  },
1139
+ messages: {
1140
+ noScriptComponentInHead: "`next/script` should not be used in `next/head` component. Move `<Script />` outside of `<Head>` instead. See: {{url}}"
1141
+ },
1018
1142
  schema: [],
1019
1143
  type: "problem"
1020
1144
  }
1021
- });
1145
+ };
1022
1146
 
1023
1147
  // src/rules/no-styled-jsx-in-document.ts
1024
1148
  import * as path8 from "node:path";
1025
- var url17 = "https://nextjs.org/docs/messages/no-styled-jsx-in-document";
1026
- var noStyledJsxInDocument = defineRule({
1149
+ var name17 = "no-styled-jsx-in-document";
1150
+ var url17 = `https://nextjs.org/docs/messages/${name17}`;
1151
+ var noStyledJsxInDocument = {
1027
1152
  create: (context) => ({
1028
1153
  JSXOpeningElement: (node) => {
1029
1154
  const document = context.filename.split("pages", 2)[1];
1030
1155
  if (!document) {
1031
1156
  return;
1032
1157
  }
1033
- const { dir, name } = path8.parse(document);
1034
- if (!(name.startsWith("_document") || dir === "/_document" && name === "index")) {
1158
+ const { dir, name: name22 } = path8.parse(document);
1159
+ if (!(name22.startsWith("_document") || dir === "/_document" && name22 === "index")) {
1035
1160
  return;
1036
1161
  }
1037
- if (node.name.name === "style" && node.attributes.find(
1038
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "jsx"
1162
+ if (node.name.type === "JSXIdentifier" && node.name.name === "style" && node.attributes.find(
1163
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "jsx"
1039
1164
  )) {
1040
1165
  context.report({
1041
- message: `\`styled-jsx\` should not be used in \`pages/_document.js\`. See: ${url17}`,
1166
+ data: { url: url17 },
1167
+ messageId: "noStyledJsxInDocument",
1042
1168
  node
1043
1169
  });
1044
1170
  }
@@ -1050,26 +1176,33 @@ var noStyledJsxInDocument = defineRule({
1050
1176
  recommended: true,
1051
1177
  url: url17
1052
1178
  },
1179
+ messages: {
1180
+ noStyledJsxInDocument: "`styled-jsx` should not be used in `pages/_document.js`. See: {{url}}"
1181
+ },
1053
1182
  schema: [],
1054
1183
  type: "problem"
1055
1184
  }
1056
- });
1185
+ };
1057
1186
 
1058
1187
  // src/rules/no-sync-scripts.ts
1059
- var url18 = "https://nextjs.org/docs/messages/no-sync-scripts";
1060
- var noSyncScripts = defineRule({
1188
+ var name18 = "no-sync-scripts";
1189
+ var url18 = `https://nextjs.org/docs/messages/${name18}`;
1190
+ var noSyncScripts = {
1061
1191
  create: (context) => ({
1062
1192
  JSXOpeningElement: (node) => {
1063
- if (node.name.name !== "script") {
1193
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "script") {
1064
1194
  return;
1065
1195
  }
1066
1196
  if (node.attributes.length === 0) {
1067
1197
  return;
1068
1198
  }
1069
- const attributeNames = node.attributes.filter((attr) => attr.type === "JSXAttribute").map((attr) => attr.name.name);
1199
+ const attributeNames = node.attributes.filter(
1200
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier"
1201
+ ).map((attr) => attr.name.name);
1070
1202
  if (attributeNames.includes("src") && !attributeNames.includes("async") && !attributeNames.includes("defer")) {
1071
1203
  context.report({
1072
- message: `Synchronous scripts should not be used. See: ${url18}`,
1204
+ data: { url: url18 },
1205
+ messageId: "noSyncScripts",
1073
1206
  node
1074
1207
  });
1075
1208
  }
@@ -1081,21 +1214,25 @@ var noSyncScripts = defineRule({
1081
1214
  recommended: true,
1082
1215
  url: url18
1083
1216
  },
1217
+ messages: {
1218
+ noSyncScripts: "Synchronous scripts should not be used. See: {{url}}"
1219
+ },
1084
1220
  schema: [],
1085
1221
  type: "problem"
1086
1222
  }
1087
- });
1223
+ };
1088
1224
 
1089
1225
  // src/rules/no-title-in-document-head.ts
1090
- var url19 = "https://nextjs.org/docs/messages/no-title-in-document-head";
1091
- var noTitleInDocumentHead = defineRule({
1226
+ var name19 = "no-title-in-document-head";
1227
+ var url19 = `https://nextjs.org/docs/messages/${name19}`;
1228
+ var noTitleInDocumentHead = {
1092
1229
  create: (context) => {
1093
1230
  let headFromNextDocument = false;
1094
1231
  return {
1095
1232
  ImportDeclaration: (node) => {
1096
1233
  if (node.source.value === "next/document") {
1097
1234
  if (node.specifiers.some(
1098
- ({ local }) => local.name === "Head"
1235
+ (specifier) => specifier.type === "ImportSpecifier" && specifier.local.name === "Head"
1099
1236
  )) {
1100
1237
  headFromNextDocument = true;
1101
1238
  }
@@ -1105,15 +1242,16 @@ var noTitleInDocumentHead = defineRule({
1105
1242
  if (!headFromNextDocument) {
1106
1243
  return;
1107
1244
  }
1108
- if (node.openingElement?.name && node.openingElement.name.name !== "Head") {
1245
+ if (node.openingElement.name.type !== "JSXIdentifier" || node.openingElement.name.name !== "Head") {
1109
1246
  return;
1110
1247
  }
1111
1248
  const titleTag = node.children.find(
1112
- (child) => child.openingElement?.name && child.openingElement.name.type === "JSXIdentifier" && child.openingElement.name.name === "title"
1249
+ (child) => child.type === "JSXElement" && child.openingElement.name.type === "JSXIdentifier" && child.openingElement.name.name === "title"
1113
1250
  );
1114
1251
  if (titleTag) {
1115
1252
  context.report({
1116
- message: `Do not use \`<title>\` element with \`<Head />\` component from \`next/document\`. Titles should defined at the page-level using \`<Head />\` from \`next/head\` instead. See: ${url19}`,
1253
+ data: { url: url19 },
1254
+ messageId: "noTitleInDocumentHead",
1117
1255
  node: titleTag
1118
1256
  });
1119
1257
  }
@@ -1126,10 +1264,13 @@ var noTitleInDocumentHead = defineRule({
1126
1264
  recommended: true,
1127
1265
  url: url19
1128
1266
  },
1267
+ messages: {
1268
+ noTitleInDocumentHead: "Do not use `<title>` element with `<Head />` component from `next/document`. Titles should defined at the page-level using `<Head />` from `next/head` instead. See: {{url}}"
1269
+ },
1129
1270
  schema: [],
1130
1271
  type: "problem"
1131
1272
  }
1132
- });
1273
+ };
1133
1274
 
1134
1275
  // src/rules/no-typos.ts
1135
1276
  import * as path9 from "node:path";
@@ -1139,6 +1280,8 @@ var NEXT_EXPORT_FUNCTIONS = [
1139
1280
  "getServerSideProps"
1140
1281
  ];
1141
1282
  var THRESHOLD = 1;
1283
+ var name20 = "no-typos";
1284
+ var url20 = `https://nextjs.org/docs/messages/${name20}`;
1142
1285
  var minDistance = (a, b) => {
1143
1286
  const m = a.length;
1144
1287
  const n = b.length;
@@ -1154,28 +1297,29 @@ var minDistance = (a, b) => {
1154
1297
  const currentRow = [i + 1];
1155
1298
  for (let j = 0; j < n; j++) {
1156
1299
  const s2 = b[j];
1157
- const insertions = previousRow[j + 1] + 1;
1158
- const deletions = currentRow[j] + 1;
1159
- const substitutions = previousRow[j] + Number(s1 !== s2);
1300
+ const insertions = (previousRow[j + 1] ?? Infinity) + 1;
1301
+ const deletions = (currentRow[j] ?? Infinity) + 1;
1302
+ const substitutions = (previousRow[j] ?? Infinity) + Number(s1 !== s2);
1160
1303
  currentRow.push(Math.min(insertions, deletions, substitutions));
1161
1304
  }
1162
1305
  previousRow = currentRow;
1163
1306
  }
1164
1307
  return previousRow[previousRow.length - 1];
1165
1308
  };
1166
- var noTypos = defineRule({
1309
+ var noTypos = {
1167
1310
  create: (context) => {
1168
- const checkTypos = (node, name) => {
1169
- if (NEXT_EXPORT_FUNCTIONS.includes(name)) {
1311
+ const checkTypos = (node, functionName) => {
1312
+ if (NEXT_EXPORT_FUNCTIONS.includes(functionName)) {
1170
1313
  return;
1171
1314
  }
1172
1315
  const potentialTypos = NEXT_EXPORT_FUNCTIONS.map((o) => ({
1173
- distance: minDistance(o, name) ?? Infinity,
1316
+ distance: minDistance(o, functionName) ?? Infinity,
1174
1317
  option: o
1175
1318
  })).filter(({ distance }) => distance <= THRESHOLD && distance > 0).sort((a, b) => a.distance - b.distance);
1176
1319
  if (potentialTypos.length) {
1177
1320
  context.report({
1178
- message: `${name} may be a typo. Did you mean ${potentialTypos[0]?.option}?`,
1321
+ data: { functionName, suggestion: potentialTypos[0]?.option ?? "" },
1322
+ messageId: "noTypos",
1179
1323
  node
1180
1324
  });
1181
1325
  }
@@ -1192,15 +1336,16 @@ var noTypos = defineRule({
1192
1336
  }
1193
1337
  switch (decl.type) {
1194
1338
  case "FunctionDeclaration": {
1195
- checkTypos(node, decl.id.name);
1339
+ if (decl.id) {
1340
+ checkTypos(node, decl.id.name);
1341
+ }
1196
1342
  break;
1197
1343
  }
1198
1344
  case "VariableDeclaration": {
1199
1345
  decl.declarations.forEach((d) => {
1200
- if (d.id.type !== "Identifier") {
1201
- return;
1346
+ if (d.id.type === "Identifier") {
1347
+ checkTypos(node, d.id.name);
1202
1348
  }
1203
- checkTypos(node, d.id.name);
1204
1349
  });
1205
1350
  break;
1206
1351
  }
@@ -1214,14 +1359,20 @@ var noTypos = defineRule({
1214
1359
  meta: {
1215
1360
  docs: {
1216
1361
  description: "Prevent common typos in Next.js data fetching functions.",
1217
- recommended: true
1362
+ recommended: true,
1363
+ url: url20
1364
+ },
1365
+ messages: {
1366
+ noTypos: "{{functionName}} may be a typo. Did you mean {{suggestion}}?"
1218
1367
  },
1219
1368
  schema: [],
1220
1369
  type: "problem"
1221
1370
  }
1222
- });
1371
+ };
1223
1372
 
1224
1373
  // src/rules/no-unwanted-polyfillio.ts
1374
+ var name21 = "no-unwanted-polyfillio";
1375
+ var url21 = `https://nextjs.org/docs/messages/${name21}`;
1225
1376
  var NEXT_POLYFILLED_FEATURES = [
1226
1377
  "Array.prototype.@@iterator",
1227
1378
  "Array.prototype.at",
@@ -1296,27 +1447,29 @@ var NEXT_POLYFILLED_FEATURES = [
1296
1447
  "es7"
1297
1448
  // contains polyfilled 'Array.prototype.includes', 'String.prototype.padEnd' and 'String.prototype.padStart'
1298
1449
  ];
1299
- var url20 = "https://nextjs.org/docs/messages/no-unwanted-polyfillio";
1300
- var noUnwantedPolyfillio = defineRule({
1450
+ var noUnwantedPolyfillio = {
1301
1451
  create: (context) => {
1302
1452
  let scriptImport = null;
1303
1453
  return {
1304
1454
  ImportDeclaration: (node) => {
1305
- if (node.source && node.source.value === "next/script") {
1306
- scriptImport = node.specifiers[0].local.name;
1455
+ if (node.source.value === "next/script" && node.specifiers.length > 0) {
1456
+ const specifier = node.specifiers[0];
1457
+ if (specifier && specifier.type === "ImportDefaultSpecifier") {
1458
+ scriptImport = specifier.local.name;
1459
+ }
1307
1460
  }
1308
1461
  },
1309
1462
  JSXOpeningElement: (node) => {
1310
- if (node.name && node.name.name !== "script" && node.name.name !== scriptImport) {
1463
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "script" && node.name.name !== scriptImport) {
1311
1464
  return;
1312
1465
  }
1313
1466
  if (node.attributes.length === 0) {
1314
1467
  return;
1315
1468
  }
1316
1469
  const srcNode = node.attributes.find(
1317
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "src"
1470
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "src"
1318
1471
  );
1319
- if (!srcNode || srcNode.value.type !== "Literal") {
1472
+ if (!srcNode?.value || srcNode.value.type !== "Literal" || typeof srcNode.value.value !== "string") {
1320
1473
  return;
1321
1474
  }
1322
1475
  const src = srcNode.value.value;
@@ -1324,15 +1477,18 @@ var noUnwantedPolyfillio = defineRule({
1324
1477
  src.startsWith("https://polyfill-fastly.net/") || src.startsWith("https://polyfill-fastly.io/") || // https://blog.cloudflare.com/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk
1325
1478
  src.startsWith("https://cdnjs.cloudflare.com/polyfill/")) {
1326
1479
  const featureQueryString = new URL(src).searchParams.get("features");
1327
- const featuresRequested = (featureQueryString ?? "").split(",");
1480
+ const featuresRequested = featureQueryString?.split(",") ?? [""];
1328
1481
  const unwantedFeatures = featuresRequested.filter(
1329
1482
  (feature) => NEXT_POLYFILLED_FEATURES.includes(feature)
1330
1483
  );
1331
1484
  if (unwantedFeatures.length > 0) {
1332
1485
  context.report({
1333
- message: `No duplicate polyfills from Polyfill.io are allowed. ${unwantedFeatures.join(
1334
- ", "
1335
- )} ${unwantedFeatures.length > 1 ? "are" : "is"} already shipped with Next.js. See: ${url20}`,
1486
+ data: {
1487
+ features: unwantedFeatures.join(", "),
1488
+ url: url21,
1489
+ verb: unwantedFeatures.length > 1 ? "are" : "is"
1490
+ },
1491
+ messageId: "noUnwantedPolyfillio",
1336
1492
  node
1337
1493
  });
1338
1494
  }
@@ -1342,18 +1498,27 @@ var noUnwantedPolyfillio = defineRule({
1342
1498
  },
1343
1499
  meta: {
1344
1500
  docs: {
1345
- category: "HTML",
1346
1501
  description: "Prevent duplicate polyfills from Polyfill.io.",
1347
- recommended: true,
1348
- url: url20
1502
+ url: url21
1503
+ },
1504
+ messages: {
1505
+ noUnwantedPolyfillio: "No duplicate polyfills from Polyfill.io are allowed. {{features}} {{verb}} already shipped with Next.js. See: {{url}}"
1349
1506
  },
1350
1507
  schema: [],
1351
1508
  type: "problem"
1352
1509
  }
1353
- });
1510
+ };
1354
1511
 
1355
1512
  // src/index.ts
1513
+ var pkg = JSON.parse(
1514
+ fs3.readFileSync(new URL("../package.json", import.meta.url), "utf8")
1515
+ );
1356
1516
  var plugin = {
1517
+ meta: {
1518
+ name: pkg.name,
1519
+ version: pkg.version
1520
+ },
1521
+ // rule definitions
1357
1522
  rules: {
1358
1523
  "google-font-display": googleFontDisplay,
1359
1524
  "google-font-preconnect": googleFontPreconnect,
@@ -1379,70 +1544,43 @@ var plugin = {
1379
1544
  }
1380
1545
  };
1381
1546
  var recommendedRules = {
1382
- // warnings
1383
- "google-font-display": "warn",
1384
- "google-font-preconnect": "warn",
1385
- // errors
1386
- "inline-script-id": "error",
1387
- "next-script-for-ga": "warn",
1388
- "no-assign-module-variable": "error",
1389
- "no-async-client-component": "warn",
1390
- "no-before-interactive-script-outside-document": "warn",
1391
- "no-css-tags": "warn",
1392
- "no-document-import-in-page": "error",
1393
- "no-duplicate-head": "error",
1394
- "no-head-element": "warn",
1395
- "no-head-import-in-document": "error",
1396
- "no-html-link-for-pages": "warn",
1397
- "no-img-element": "warn",
1398
- "no-page-custom-font": "warn",
1399
- "no-script-component-in-head": "error",
1400
- "no-styled-jsx-in-document": "warn",
1401
- "no-sync-scripts": "warn",
1402
- "no-title-in-document-head": "warn",
1403
- "no-typos": "warn",
1404
- "no-unwanted-polyfillio": "warn"
1405
- };
1406
- var coreWebVitalsRules = {
1407
- ...recommendedRules,
1408
- "no-html-link-for-pages": "error",
1409
- "no-sync-scripts": "error"
1547
+ "nextjs/google-font-display": "warn",
1548
+ "nextjs/google-font-preconnect": "warn",
1549
+ "nextjs/inline-script-id": "warn",
1550
+ "nextjs/next-script-for-ga": "warn",
1551
+ "nextjs/no-assign-module-variable": "warn",
1552
+ "nextjs/no-async-client-component": "warn",
1553
+ "nextjs/no-before-interactive-script-outside-document": "warn",
1554
+ "nextjs/no-css-tags": "warn",
1555
+ "nextjs/no-document-import-in-page": "warn",
1556
+ "nextjs/no-duplicate-head": "warn",
1557
+ "nextjs/no-head-element": "warn",
1558
+ "nextjs/no-head-import-in-document": "warn",
1559
+ "nextjs/no-html-link-for-pages": "warn",
1560
+ "nextjs/no-img-element": "warn",
1561
+ "nextjs/no-page-custom-font": "warn",
1562
+ "nextjs/no-script-component-in-head": "warn",
1563
+ "nextjs/no-styled-jsx-in-document": "warn",
1564
+ "nextjs/no-sync-scripts": "warn",
1565
+ "nextjs/no-title-in-document-head": "warn",
1566
+ "nextjs/no-typos": "warn",
1567
+ "nextjs/no-unwanted-polyfillio": "warn"
1410
1568
  };
1411
- var createRuleConfig = (rules2, isFlat = false) => {
1412
- return {
1413
- plugins: isFlat ? { nextjs: plugin } : ["nextjs"],
1414
- rules: rules2
1415
- };
1569
+ var recommendedConfig = {
1570
+ files: ["**/*.{js,jsx,ts,tsx}"],
1571
+ plugins: {
1572
+ nextjs: plugin
1573
+ },
1574
+ rules: recommendedRules
1416
1575
  };
1417
- var recommendedFlatConfig = createRuleConfig(recommendedRules, true);
1418
- var recommendedLegacyConfig = createRuleConfig(recommendedRules, false);
1419
- var coreWebVitalsFlatConfig = createRuleConfig(coreWebVitalsRules, true);
1420
- var coreWebVitalsLegacyConfig = createRuleConfig(coreWebVitalsRules, false);
1421
- var index_default = {
1576
+ var nextjsPlugin = {
1422
1577
  ...plugin,
1423
1578
  configs: {
1424
- /**
1425
- * Legacy config (ESLint < v9) with Core Web Vitals rules (recommended with some warnings upgrade to errors)
1426
- */
1427
- "core-web-vitals": coreWebVitalsLegacyConfig,
1428
- /**
1429
- * Flat config (ESLint v9+) with Core Web Vitals rules (recommended with some warnings upgrade to errors)
1430
- */
1431
- "core-web-vitals/flat": coreWebVitalsFlatConfig,
1432
- /**
1433
- * Legacy config (ESLint < v9) with recommended rules
1434
- */
1435
- recommended: recommendedLegacyConfig,
1436
- /**
1437
- * Flat config (ESLint v9+) with recommended rules
1438
- */
1439
- "recommended/flat": recommendedFlatConfig
1440
- },
1441
- name: "nextjs"
1579
+ recommended: recommendedConfig
1580
+ }
1442
1581
  };
1443
- var rules = plugin.rules;
1582
+ var index_default = nextjsPlugin;
1444
1583
  export {
1445
- index_default as default,
1446
- rules
1584
+ index_default as default
1447
1585
  };
1448
1586
  //# sourceMappingURL=index.js.map