eslint-plugin-nextjs 0.1.2 → 1.0.1

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 +399 -264
  4. package/dist/index.js.map +1 -1
  5. package/package.json +18 -12
  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";
@@ -583,10 +660,7 @@ var processRootDir = (rootDir) => {
583
660
  };
584
661
  var getRootDirs = (context) => {
585
662
  let rootDirs = [context.cwd];
586
- const nextSettings = (
587
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
588
- context.settings.next || {}
589
- );
663
+ const nextSettings = context.settings.next || {};
590
664
  const rootDir = nextSettings.rootDir;
591
665
  if (typeof rootDir === "string") {
592
666
  rootDirs = processRootDir(rootDir);
@@ -649,18 +723,18 @@ var parseUrlForAppDir = (urlprefix, directory) => {
649
723
  });
650
724
  return res;
651
725
  };
652
- var normalizeURL = (url21) => {
653
- if (!url21) {
726
+ var normalizeURL = (url22) => {
727
+ if (!url22) {
654
728
  return;
655
729
  }
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;
730
+ url22 = url22.split("?", 1)[0];
731
+ url22 = url22.split("#", 1)[0];
732
+ url22 = url22.replace(/(?<temp1>\/index\.html)$/, "/");
733
+ if (url22 === "") {
734
+ return url22;
661
735
  }
662
- url21 = url21.endsWith("/") ? url21 : `${url21}/`;
663
- return url21;
736
+ url22 = url22.endsWith("/") ? url22 : `${url22}/`;
737
+ return url22;
664
738
  };
665
739
  var normalizeAppPath = (route) => ensureLeadingSlash(
666
740
  route.split("/").reduce((pathname, segment, index, segments) => {
@@ -684,7 +758,7 @@ var getUrlFromPagesDirectories = (urlPrefix, directories) => Array.from(
684
758
  new Set(
685
759
  directories.flatMap((directory) => parseUrlForPages(urlPrefix, directory)).map(
686
760
  // Since the URLs are normalized we add `^` and `$` to the RegExp to make sure they match exactly.
687
- (url21) => `^${normalizeURL(url21)}$`
761
+ (url22) => `^${normalizeURL(url22)}$`
688
762
  )
689
763
  )
690
764
  ).map((urlReg) => {
@@ -696,7 +770,7 @@ var getUrlFromAppDirectory = (urlPrefix, directories) => Array.from(
696
770
  new Set(
697
771
  directories.map((directory) => parseUrlForAppDir(urlPrefix, directory)).flat().map(
698
772
  // Since the URLs are normalized we add `^` and `$` to the RegExp to make sure they match exactly.
699
- (url21) => `^${normalizeAppPath(url21)}$`
773
+ (url22) => `^${normalizeAppPath(url22)}$`
700
774
  )
701
775
  )
702
776
  ).map((urlReg) => {
@@ -725,23 +799,27 @@ var pagesDirWarning = execOnce((pagesDirs) => {
725
799
  });
726
800
  var fsExistsSyncCache = {};
727
801
  var memoize = (fn) => {
728
- const cache = {};
729
- return (...args) => {
802
+ const cache = /* @__PURE__ */ new Map();
803
+ const memoized = (...args) => {
730
804
  const key = JSON.stringify(args);
731
- cache[key] ??= fn(...args);
732
- return cache[key];
805
+ if (!cache.has(key)) {
806
+ cache.set(key, fn(...args));
807
+ }
808
+ const value = cache.get(key);
809
+ return value;
733
810
  };
811
+ return memoized;
734
812
  };
735
813
  var cachedGetUrlFromPagesDirectories = memoize(getUrlFromPagesDirectories);
736
814
  var cachedGetUrlFromAppDirectory = memoize(getUrlFromAppDirectory);
737
- var url13 = "https://nextjs.org/docs/messages/no-html-link-for-pages";
738
- var noHtmlLinkForPages = defineRule({
815
+ var name13 = "no-html-link-for-pages";
816
+ var url13 = `https://nextjs.org/docs/messages/${name13}`;
817
+ var noHtmlLinkForPages = {
739
818
  /**
740
819
  * Creates an ESLint rule listener.
741
820
  */
742
821
  create: (context) => {
743
- const ruleOptions = context.options;
744
- const [customPagesDirectory] = ruleOptions;
822
+ const [customPagesDirectory] = context.options;
745
823
  const rootDirs = getRootDirs(context);
746
824
  const pagesDirs = (customPagesDirectory ? [customPagesDirectory] : rootDirs.map((dir) => [
747
825
  path6.join(dir, "pages"),
@@ -765,26 +843,26 @@ var noHtmlLinkForPages = defineRule({
765
843
  const allUrlRegex = [...pageUrls, ...appDirUrls];
766
844
  return {
767
845
  JSXOpeningElement: (node) => {
768
- if (node.name.name !== "a") {
846
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "a") {
769
847
  return;
770
848
  }
771
849
  if (node.attributes.length === 0) {
772
850
  return;
773
851
  }
774
852
  const target = node.attributes.find(
775
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "target"
853
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "target"
776
854
  );
777
- if (target && target.value.value === "_blank") {
855
+ if (target?.value?.type === "Literal" && target.value.value === "_blank") {
778
856
  return;
779
857
  }
780
858
  const href = node.attributes.find(
781
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "href"
859
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "href"
782
860
  );
783
- if (!href || href.value && href.value.type !== "Literal") {
861
+ if (!href?.value || href.value.type !== "Literal") {
784
862
  return;
785
863
  }
786
864
  const hasDownloadAttr = node.attributes.find(
787
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "download"
865
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "download"
788
866
  );
789
867
  if (hasDownloadAttr) {
790
868
  return;
@@ -796,7 +874,8 @@ var noHtmlLinkForPages = defineRule({
796
874
  allUrlRegex.forEach((foundUrl) => {
797
875
  if (hrefPath && foundUrl.test(normalizeURL(hrefPath))) {
798
876
  context.report({
799
- message: `Do not use an \`<a>\` element to navigate to \`${hrefPath}\`. Use \`<Link />\` from \`next/link\` instead. See: ${url13}`,
877
+ data: { hrefPath, url: url13 },
878
+ messageId: "noHtmlLinkForPages",
800
879
  node
801
880
  });
802
881
  }
@@ -811,6 +890,9 @@ var noHtmlLinkForPages = defineRule({
811
890
  recommended: true,
812
891
  url: url13
813
892
  },
893
+ messages: {
894
+ noHtmlLinkForPages: "Do not use an `<a>` element to navigate to `{{hrefPath}}`. Use `<Link />` from `next/link` instead. See: {{url}}"
895
+ },
814
896
  schema: [
815
897
  {
816
898
  oneOf: [
@@ -829,31 +911,35 @@ var noHtmlLinkForPages = defineRule({
829
911
  ],
830
912
  type: "problem"
831
913
  }
832
- });
914
+ };
833
915
 
834
916
  // src/rules/no-img-element.ts
835
917
  import path7 from "node:path";
836
- var url14 = "https://nextjs.org/docs/messages/no-img-element";
837
- var noImgElement = defineRule({
918
+ var name14 = "no-img-element";
919
+ var url14 = `https://nextjs.org/docs/messages/${name14}`;
920
+ var noImgElement = {
838
921
  create: (context) => {
839
922
  const relativePath = context.filename.replace(path7.sep, "/").replace(context.cwd, "").replace(/^\//, "");
840
923
  const isAppDir = /^(?<temp1>src\/)?app\//.test(relativePath);
841
924
  return {
842
925
  JSXOpeningElement: (node) => {
843
- if (node.name.name !== "img") {
926
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "img") {
844
927
  return;
845
928
  }
846
929
  if (node.attributes.length === 0) {
847
930
  return;
848
931
  }
849
- if (node.parent?.parent?.openingElement?.name?.name === "picture") {
932
+ const parentJSXElement = node.parent;
933
+ const grandParentJSXElement = parentJSXElement?.parent;
934
+ if (grandParentJSXElement?.openingElement?.name?.type === "JSXIdentifier" && grandParentJSXElement?.openingElement?.name?.name === "picture") {
850
935
  return;
851
936
  }
852
937
  if (isAppDir && /\/opengraph-image|twitter-image|icon\.\w+$/.test(relativePath)) {
853
938
  return;
854
939
  }
855
940
  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}`,
941
+ data: { url: url14 },
942
+ messageId: "noImgElement",
857
943
  node
858
944
  });
859
945
  }
@@ -866,16 +952,20 @@ var noImgElement = defineRule({
866
952
  recommended: true,
867
953
  url: url14
868
954
  },
955
+ messages: {
956
+ 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}}"
957
+ },
869
958
  schema: [],
870
959
  type: "problem"
871
960
  }
872
- });
961
+ };
873
962
 
874
963
  // src/rules/no-page-custom-font.ts
875
964
  import { posix as posix2, sep as sep3 } from "node:path";
876
- var url15 = "https://nextjs.org/docs/messages/no-page-custom-font";
965
+ var name15 = "no-page-custom-font";
966
+ var url15 = `https://nextjs.org/docs/messages/${name15}`;
877
967
  var isIdentifierMatch = (id1, id2) => id1 === null && id2 === null || id1 && id2 && id1.name === id2.name;
878
- var noPageCustomFont = defineRule({
968
+ var noPageCustomFont = {
879
969
  create: (context) => {
880
970
  const { sourceCode } = context;
881
971
  const paths = context.filename.split("pages");
@@ -883,12 +973,9 @@ var noPageCustomFont = defineRule({
883
973
  if (!page) {
884
974
  return {};
885
975
  }
886
- const isDocument = (
887
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
888
- page.startsWith(`${sep3}_document`) || page.startsWith(`${posix2.sep}_document`)
889
- );
976
+ const isDocument = page.startsWith(`${sep3}_document`) || page.startsWith(`${posix2.sep}_document`);
890
977
  let documentImportName;
891
- let localDefaultExportId;
978
+ let localDefaultExportId = null;
892
979
  let exportDeclarationType;
893
980
  return {
894
981
  ExportDefaultDeclaration: (node) => {
@@ -897,14 +984,14 @@ var noPageCustomFont = defineRule({
897
984
  localDefaultExportId = node.declaration.id;
898
985
  return;
899
986
  }
900
- if (node.declaration.type === "ClassDeclaration" && node.declaration.superClass && "name" in node.declaration.superClass && node.declaration.superClass.name === documentImportName) {
987
+ if (node.declaration.type === "ClassDeclaration" && node.declaration.superClass && node.declaration.superClass.type === "Identifier" && node.declaration.superClass.name === documentImportName) {
901
988
  localDefaultExportId = node.declaration.id;
902
989
  }
903
990
  },
904
991
  ImportDeclaration: (node) => {
905
992
  if (node.source.value === "next/document") {
906
993
  const documentImport = node.specifiers.find(
907
- ({ type }) => type === "ImportDefaultSpecifier"
994
+ (specifier) => specifier.type === "ImportDefaultSpecifier"
908
995
  );
909
996
  if (documentImport?.local) {
910
997
  documentImportName = documentImport.local.name;
@@ -912,7 +999,7 @@ var noPageCustomFont = defineRule({
912
999
  }
913
1000
  },
914
1001
  JSXOpeningElement: (node) => {
915
- if (node.name.name !== "link") {
1002
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "link") {
916
1003
  return;
917
1004
  }
918
1005
  const ancestors = sourceCode.getAncestors(node);
@@ -920,6 +1007,9 @@ var noPageCustomFont = defineRule({
920
1007
  const program = ancestors.find(
921
1008
  (ancestor) => ancestor.type === "Program"
922
1009
  );
1010
+ if (!program?.tokens) {
1011
+ return;
1012
+ }
923
1013
  for (let i = 0; i <= program.tokens.length - 1; i++) {
924
1014
  if (localDefaultExportId) {
925
1015
  break;
@@ -927,10 +1017,20 @@ var noPageCustomFont = defineRule({
927
1017
  const token = program.tokens[i];
928
1018
  if (token?.type === "Keyword" && token.value === "export") {
929
1019
  const nextToken = program.tokens[i + 1];
930
- if (nextToken && nextToken.type === "Keyword" && nextToken.value === "default") {
1020
+ if (nextToken && nextToken.value === "default") {
931
1021
  const maybeIdentifier = program.tokens[i + 2];
932
1022
  if (maybeIdentifier && maybeIdentifier.type === "Identifier") {
933
- localDefaultExportId = { name: maybeIdentifier.value };
1023
+ localDefaultExportId = {
1024
+ decorators: [],
1025
+ loc: {
1026
+ end: { column: 0, line: 0 },
1027
+ start: { column: 0, line: 0 }
1028
+ },
1029
+ name: maybeIdentifier.value,
1030
+ optional: false,
1031
+ range: [0, 0],
1032
+ type: "Identifier"
1033
+ };
934
1034
  }
935
1035
  }
936
1036
  }
@@ -938,7 +1038,7 @@ var noPageCustomFont = defineRule({
938
1038
  }
939
1039
  const parentComponent = ancestors.find((ancestor) => {
940
1040
  if (exportDeclarationType === "ClassDeclaration") {
941
- return ancestor.type === exportDeclarationType && "superClass" in ancestor && ancestor.superClass && "name" in ancestor.superClass && ancestor.superClass.name === documentImportName;
1041
+ return ancestor.type === exportDeclarationType && "superClass" in ancestor && ancestor.superClass && ancestor.superClass.type === "Identifier" && ancestor.superClass.name === documentImportName;
942
1042
  }
943
1043
  if ("id" in ancestor) {
944
1044
  if (exportDeclarationType === "FunctionDeclaration") {
@@ -958,10 +1058,9 @@ var noPageCustomFont = defineRule({
958
1058
  const hrefValue = attributes.value("href");
959
1059
  const isGoogleFont = typeof hrefValue === "string" && hrefValue.startsWith("https://fonts.googleapis.com/css");
960
1060
  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
1061
  context.report({
964
- message: message2,
1062
+ data: { url: url15 },
1063
+ messageId: isDocument ? "noPageCustomFontOutsideHead" : "noPageCustomFont",
965
1064
  node
966
1065
  });
967
1066
  }
@@ -974,16 +1073,36 @@ var noPageCustomFont = defineRule({
974
1073
  recommended: true,
975
1074
  url: url15
976
1075
  },
1076
+ messages: {
1077
+ noPageCustomFont: "Custom fonts not added in `pages/_document.js` will only load for a single page. This is discouraged. See: {{url}}",
1078
+ noPageCustomFontOutsideHead: "Using `<link />` outside of `<Head>` will disable automatic font optimization. This is discouraged. See: {{url}}"
1079
+ },
977
1080
  schema: [],
978
1081
  type: "problem"
979
1082
  }
980
- });
1083
+ };
981
1084
 
982
1085
  // 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({
1086
+ var name16 = "no-script-component-in-head";
1087
+ var url16 = `https://nextjs.org/docs/messages/${name16}`;
1088
+ var noScriptComponentInHead = {
985
1089
  create: (context) => {
986
1090
  let isNextHead = null;
1091
+ const findNestedScriptComponent = (node) => {
1092
+ if (node.type !== "JSXElement") {
1093
+ return null;
1094
+ }
1095
+ if (node.openingElement.name.type === "JSXIdentifier" && node.openingElement.name.name === "Script") {
1096
+ return node;
1097
+ }
1098
+ for (const child of node.children) {
1099
+ const scriptComponent = findNestedScriptComponent(child);
1100
+ if (scriptComponent) {
1101
+ return scriptComponent;
1102
+ }
1103
+ }
1104
+ return null;
1105
+ };
987
1106
  return {
988
1107
  ImportDeclaration: (node) => {
989
1108
  if (node.source.value === "next/head") {
@@ -994,15 +1113,14 @@ var noScriptComponentInHead = defineRule({
994
1113
  if (!isNextHead) {
995
1114
  return;
996
1115
  }
997
- if (node.openingElement?.name && node.openingElement.name.name !== "Head") {
1116
+ if (node.openingElement.name.type !== "JSXIdentifier" || node.openingElement.name.name !== "Head") {
998
1117
  return;
999
1118
  }
1000
- const scriptTag = node.children.find(
1001
- (child) => child.openingElement?.name && child.openingElement.name.name === "Script"
1002
- );
1119
+ const scriptTag = findNestedScriptComponent(node);
1003
1120
  if (scriptTag) {
1004
1121
  context.report({
1005
- message: `\`next/script\` should not be used in \`next/head\` component. Move \`<Script />\` outside of \`<Head>\` instead. See: ${url16}`,
1122
+ data: { url: url16 },
1123
+ messageId: "noScriptComponentInHead",
1006
1124
  node
1007
1125
  });
1008
1126
  }
@@ -1015,30 +1133,35 @@ var noScriptComponentInHead = defineRule({
1015
1133
  recommended: true,
1016
1134
  url: url16
1017
1135
  },
1136
+ messages: {
1137
+ noScriptComponentInHead: "`next/script` should not be used in `next/head` component. Move `<Script />` outside of `<Head>` instead. See: {{url}}"
1138
+ },
1018
1139
  schema: [],
1019
1140
  type: "problem"
1020
1141
  }
1021
- });
1142
+ };
1022
1143
 
1023
1144
  // src/rules/no-styled-jsx-in-document.ts
1024
1145
  import * as path8 from "node:path";
1025
- var url17 = "https://nextjs.org/docs/messages/no-styled-jsx-in-document";
1026
- var noStyledJsxInDocument = defineRule({
1146
+ var name17 = "no-styled-jsx-in-document";
1147
+ var url17 = `https://nextjs.org/docs/messages/${name17}`;
1148
+ var noStyledJsxInDocument = {
1027
1149
  create: (context) => ({
1028
1150
  JSXOpeningElement: (node) => {
1029
1151
  const document = context.filename.split("pages", 2)[1];
1030
1152
  if (!document) {
1031
1153
  return;
1032
1154
  }
1033
- const { dir, name } = path8.parse(document);
1034
- if (!(name.startsWith("_document") || dir === "/_document" && name === "index")) {
1155
+ const { dir, name: name22 } = path8.parse(document);
1156
+ if (!(name22.startsWith("_document") || dir === "/_document" && name22 === "index")) {
1035
1157
  return;
1036
1158
  }
1037
- if (node.name.name === "style" && node.attributes.find(
1038
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "jsx"
1159
+ if (node.name.type === "JSXIdentifier" && node.name.name === "style" && node.attributes.find(
1160
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "jsx"
1039
1161
  )) {
1040
1162
  context.report({
1041
- message: `\`styled-jsx\` should not be used in \`pages/_document.js\`. See: ${url17}`,
1163
+ data: { url: url17 },
1164
+ messageId: "noStyledJsxInDocument",
1042
1165
  node
1043
1166
  });
1044
1167
  }
@@ -1050,26 +1173,33 @@ var noStyledJsxInDocument = defineRule({
1050
1173
  recommended: true,
1051
1174
  url: url17
1052
1175
  },
1176
+ messages: {
1177
+ noStyledJsxInDocument: "`styled-jsx` should not be used in `pages/_document.js`. See: {{url}}"
1178
+ },
1053
1179
  schema: [],
1054
1180
  type: "problem"
1055
1181
  }
1056
- });
1182
+ };
1057
1183
 
1058
1184
  // src/rules/no-sync-scripts.ts
1059
- var url18 = "https://nextjs.org/docs/messages/no-sync-scripts";
1060
- var noSyncScripts = defineRule({
1185
+ var name18 = "no-sync-scripts";
1186
+ var url18 = `https://nextjs.org/docs/messages/${name18}`;
1187
+ var noSyncScripts = {
1061
1188
  create: (context) => ({
1062
1189
  JSXOpeningElement: (node) => {
1063
- if (node.name.name !== "script") {
1190
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "script") {
1064
1191
  return;
1065
1192
  }
1066
1193
  if (node.attributes.length === 0) {
1067
1194
  return;
1068
1195
  }
1069
- const attributeNames = node.attributes.filter((attr) => attr.type === "JSXAttribute").map((attr) => attr.name.name);
1196
+ const attributeNames = node.attributes.filter(
1197
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier"
1198
+ ).map((attr) => attr.name.name);
1070
1199
  if (attributeNames.includes("src") && !attributeNames.includes("async") && !attributeNames.includes("defer")) {
1071
1200
  context.report({
1072
- message: `Synchronous scripts should not be used. See: ${url18}`,
1201
+ data: { url: url18 },
1202
+ messageId: "noSyncScripts",
1073
1203
  node
1074
1204
  });
1075
1205
  }
@@ -1081,21 +1211,25 @@ var noSyncScripts = defineRule({
1081
1211
  recommended: true,
1082
1212
  url: url18
1083
1213
  },
1214
+ messages: {
1215
+ noSyncScripts: "Synchronous scripts should not be used. See: {{url}}"
1216
+ },
1084
1217
  schema: [],
1085
1218
  type: "problem"
1086
1219
  }
1087
- });
1220
+ };
1088
1221
 
1089
1222
  // 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({
1223
+ var name19 = "no-title-in-document-head";
1224
+ var url19 = `https://nextjs.org/docs/messages/${name19}`;
1225
+ var noTitleInDocumentHead = {
1092
1226
  create: (context) => {
1093
1227
  let headFromNextDocument = false;
1094
1228
  return {
1095
1229
  ImportDeclaration: (node) => {
1096
1230
  if (node.source.value === "next/document") {
1097
1231
  if (node.specifiers.some(
1098
- ({ local }) => local.name === "Head"
1232
+ (specifier) => specifier.type === "ImportSpecifier" && specifier.local.name === "Head"
1099
1233
  )) {
1100
1234
  headFromNextDocument = true;
1101
1235
  }
@@ -1105,15 +1239,16 @@ var noTitleInDocumentHead = defineRule({
1105
1239
  if (!headFromNextDocument) {
1106
1240
  return;
1107
1241
  }
1108
- if (node.openingElement?.name && node.openingElement.name.name !== "Head") {
1242
+ if (node.openingElement.name.type !== "JSXIdentifier" || node.openingElement.name.name !== "Head") {
1109
1243
  return;
1110
1244
  }
1111
1245
  const titleTag = node.children.find(
1112
- (child) => child.openingElement?.name && child.openingElement.name.type === "JSXIdentifier" && child.openingElement.name.name === "title"
1246
+ (child) => child.type === "JSXElement" && child.openingElement.name.type === "JSXIdentifier" && child.openingElement.name.name === "title"
1113
1247
  );
1114
1248
  if (titleTag) {
1115
1249
  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}`,
1250
+ data: { url: url19 },
1251
+ messageId: "noTitleInDocumentHead",
1117
1252
  node: titleTag
1118
1253
  });
1119
1254
  }
@@ -1126,10 +1261,13 @@ var noTitleInDocumentHead = defineRule({
1126
1261
  recommended: true,
1127
1262
  url: url19
1128
1263
  },
1264
+ messages: {
1265
+ 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}}"
1266
+ },
1129
1267
  schema: [],
1130
1268
  type: "problem"
1131
1269
  }
1132
- });
1270
+ };
1133
1271
 
1134
1272
  // src/rules/no-typos.ts
1135
1273
  import * as path9 from "node:path";
@@ -1139,6 +1277,8 @@ var NEXT_EXPORT_FUNCTIONS = [
1139
1277
  "getServerSideProps"
1140
1278
  ];
1141
1279
  var THRESHOLD = 1;
1280
+ var name20 = "no-typos";
1281
+ var url20 = `https://nextjs.org/docs/messages/${name20}`;
1142
1282
  var minDistance = (a, b) => {
1143
1283
  const m = a.length;
1144
1284
  const n = b.length;
@@ -1154,28 +1294,29 @@ var minDistance = (a, b) => {
1154
1294
  const currentRow = [i + 1];
1155
1295
  for (let j = 0; j < n; j++) {
1156
1296
  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);
1297
+ const insertions = (previousRow[j + 1] ?? Infinity) + 1;
1298
+ const deletions = (currentRow[j] ?? Infinity) + 1;
1299
+ const substitutions = (previousRow[j] ?? Infinity) + Number(s1 !== s2);
1160
1300
  currentRow.push(Math.min(insertions, deletions, substitutions));
1161
1301
  }
1162
1302
  previousRow = currentRow;
1163
1303
  }
1164
1304
  return previousRow[previousRow.length - 1];
1165
1305
  };
1166
- var noTypos = defineRule({
1306
+ var noTypos = {
1167
1307
  create: (context) => {
1168
- const checkTypos = (node, name) => {
1169
- if (NEXT_EXPORT_FUNCTIONS.includes(name)) {
1308
+ const checkTypos = (node, functionName) => {
1309
+ if (NEXT_EXPORT_FUNCTIONS.includes(functionName)) {
1170
1310
  return;
1171
1311
  }
1172
1312
  const potentialTypos = NEXT_EXPORT_FUNCTIONS.map((o) => ({
1173
- distance: minDistance(o, name) ?? Infinity,
1313
+ distance: minDistance(o, functionName) ?? Infinity,
1174
1314
  option: o
1175
1315
  })).filter(({ distance }) => distance <= THRESHOLD && distance > 0).sort((a, b) => a.distance - b.distance);
1176
1316
  if (potentialTypos.length) {
1177
1317
  context.report({
1178
- message: `${name} may be a typo. Did you mean ${potentialTypos[0]?.option}?`,
1318
+ data: { functionName, suggestion: potentialTypos[0]?.option ?? "" },
1319
+ messageId: "noTypos",
1179
1320
  node
1180
1321
  });
1181
1322
  }
@@ -1192,15 +1333,16 @@ var noTypos = defineRule({
1192
1333
  }
1193
1334
  switch (decl.type) {
1194
1335
  case "FunctionDeclaration": {
1195
- checkTypos(node, decl.id.name);
1336
+ if (decl.id) {
1337
+ checkTypos(node, decl.id.name);
1338
+ }
1196
1339
  break;
1197
1340
  }
1198
1341
  case "VariableDeclaration": {
1199
1342
  decl.declarations.forEach((d) => {
1200
- if (d.id.type !== "Identifier") {
1201
- return;
1343
+ if (d.id.type === "Identifier") {
1344
+ checkTypos(node, d.id.name);
1202
1345
  }
1203
- checkTypos(node, d.id.name);
1204
1346
  });
1205
1347
  break;
1206
1348
  }
@@ -1214,14 +1356,20 @@ var noTypos = defineRule({
1214
1356
  meta: {
1215
1357
  docs: {
1216
1358
  description: "Prevent common typos in Next.js data fetching functions.",
1217
- recommended: true
1359
+ recommended: true,
1360
+ url: url20
1361
+ },
1362
+ messages: {
1363
+ noTypos: "{{functionName}} may be a typo. Did you mean {{suggestion}}?"
1218
1364
  },
1219
1365
  schema: [],
1220
1366
  type: "problem"
1221
1367
  }
1222
- });
1368
+ };
1223
1369
 
1224
1370
  // src/rules/no-unwanted-polyfillio.ts
1371
+ var name21 = "no-unwanted-polyfillio";
1372
+ var url21 = `https://nextjs.org/docs/messages/${name21}`;
1225
1373
  var NEXT_POLYFILLED_FEATURES = [
1226
1374
  "Array.prototype.@@iterator",
1227
1375
  "Array.prototype.at",
@@ -1296,27 +1444,29 @@ var NEXT_POLYFILLED_FEATURES = [
1296
1444
  "es7"
1297
1445
  // contains polyfilled 'Array.prototype.includes', 'String.prototype.padEnd' and 'String.prototype.padStart'
1298
1446
  ];
1299
- var url20 = "https://nextjs.org/docs/messages/no-unwanted-polyfillio";
1300
- var noUnwantedPolyfillio = defineRule({
1447
+ var noUnwantedPolyfillio = {
1301
1448
  create: (context) => {
1302
1449
  let scriptImport = null;
1303
1450
  return {
1304
1451
  ImportDeclaration: (node) => {
1305
- if (node.source && node.source.value === "next/script") {
1306
- scriptImport = node.specifiers[0].local.name;
1452
+ if (node.source.value === "next/script" && node.specifiers.length > 0) {
1453
+ const specifier = node.specifiers[0];
1454
+ if (specifier && specifier.type === "ImportDefaultSpecifier") {
1455
+ scriptImport = specifier.local.name;
1456
+ }
1307
1457
  }
1308
1458
  },
1309
1459
  JSXOpeningElement: (node) => {
1310
- if (node.name && node.name.name !== "script" && node.name.name !== scriptImport) {
1460
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "script" && node.name.name !== scriptImport) {
1311
1461
  return;
1312
1462
  }
1313
1463
  if (node.attributes.length === 0) {
1314
1464
  return;
1315
1465
  }
1316
1466
  const srcNode = node.attributes.find(
1317
- (attr) => attr.type === "JSXAttribute" && attr.name.name === "src"
1467
+ (attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "src"
1318
1468
  );
1319
- if (!srcNode || srcNode.value.type !== "Literal") {
1469
+ if (!srcNode?.value || srcNode.value.type !== "Literal" || typeof srcNode.value.value !== "string") {
1320
1470
  return;
1321
1471
  }
1322
1472
  const src = srcNode.value.value;
@@ -1324,15 +1474,18 @@ var noUnwantedPolyfillio = defineRule({
1324
1474
  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
1475
  src.startsWith("https://cdnjs.cloudflare.com/polyfill/")) {
1326
1476
  const featureQueryString = new URL(src).searchParams.get("features");
1327
- const featuresRequested = (featureQueryString ?? "").split(",");
1477
+ const featuresRequested = featureQueryString?.split(",") ?? [""];
1328
1478
  const unwantedFeatures = featuresRequested.filter(
1329
1479
  (feature) => NEXT_POLYFILLED_FEATURES.includes(feature)
1330
1480
  );
1331
1481
  if (unwantedFeatures.length > 0) {
1332
1482
  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}`,
1483
+ data: {
1484
+ features: unwantedFeatures.join(", "),
1485
+ url: url21,
1486
+ verb: unwantedFeatures.length > 1 ? "are" : "is"
1487
+ },
1488
+ messageId: "noUnwantedPolyfillio",
1336
1489
  node
1337
1490
  });
1338
1491
  }
@@ -1342,18 +1495,27 @@ var noUnwantedPolyfillio = defineRule({
1342
1495
  },
1343
1496
  meta: {
1344
1497
  docs: {
1345
- category: "HTML",
1346
1498
  description: "Prevent duplicate polyfills from Polyfill.io.",
1347
- recommended: true,
1348
- url: url20
1499
+ url: url21
1500
+ },
1501
+ messages: {
1502
+ noUnwantedPolyfillio: "No duplicate polyfills from Polyfill.io are allowed. {{features}} {{verb}} already shipped with Next.js. See: {{url}}"
1349
1503
  },
1350
1504
  schema: [],
1351
1505
  type: "problem"
1352
1506
  }
1353
- });
1507
+ };
1354
1508
 
1355
1509
  // src/index.ts
1510
+ var pkg = JSON.parse(
1511
+ fs3.readFileSync(new URL("../package.json", import.meta.url), "utf8")
1512
+ );
1356
1513
  var plugin = {
1514
+ meta: {
1515
+ name: pkg.name,
1516
+ version: pkg.version
1517
+ },
1518
+ // rule definitions
1357
1519
  rules: {
1358
1520
  "google-font-display": googleFontDisplay,
1359
1521
  "google-font-preconnect": googleFontPreconnect,
@@ -1379,70 +1541,43 @@ var plugin = {
1379
1541
  }
1380
1542
  };
1381
1543
  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"
1544
+ "nextjs/google-font-display": "warn",
1545
+ "nextjs/google-font-preconnect": "warn",
1546
+ "nextjs/inline-script-id": "warn",
1547
+ "nextjs/next-script-for-ga": "warn",
1548
+ "nextjs/no-assign-module-variable": "warn",
1549
+ "nextjs/no-async-client-component": "warn",
1550
+ "nextjs/no-before-interactive-script-outside-document": "warn",
1551
+ "nextjs/no-css-tags": "warn",
1552
+ "nextjs/no-document-import-in-page": "warn",
1553
+ "nextjs/no-duplicate-head": "warn",
1554
+ "nextjs/no-head-element": "warn",
1555
+ "nextjs/no-head-import-in-document": "warn",
1556
+ "nextjs/no-html-link-for-pages": "warn",
1557
+ "nextjs/no-img-element": "warn",
1558
+ "nextjs/no-page-custom-font": "warn",
1559
+ "nextjs/no-script-component-in-head": "warn",
1560
+ "nextjs/no-styled-jsx-in-document": "warn",
1561
+ "nextjs/no-sync-scripts": "warn",
1562
+ "nextjs/no-title-in-document-head": "warn",
1563
+ "nextjs/no-typos": "warn",
1564
+ "nextjs/no-unwanted-polyfillio": "warn"
1410
1565
  };
1411
- var createRuleConfig = (rules2, isFlat = false) => {
1412
- return {
1413
- plugins: isFlat ? { nextjs: plugin } : ["nextjs"],
1414
- rules: rules2
1415
- };
1566
+ var recommendedConfig = {
1567
+ files: ["**/*.{js,jsx,ts,tsx}"],
1568
+ plugins: {
1569
+ nextjs: plugin
1570
+ },
1571
+ rules: recommendedRules
1416
1572
  };
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 = {
1573
+ var nextjsPlugin = {
1422
1574
  ...plugin,
1423
1575
  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"
1576
+ recommended: recommendedConfig
1577
+ }
1442
1578
  };
1443
- var rules = plugin.rules;
1579
+ var index_default = nextjsPlugin;
1444
1580
  export {
1445
- index_default as default,
1446
- rules
1581
+ index_default as default
1447
1582
  };
1448
1583
  //# sourceMappingURL=index.js.map