@next/eslint-plugin-next 15.0.0-rc.0 → 15.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.
|
@@ -12,6 +12,9 @@ function _array_like_to_array(arr, len) {
|
|
|
12
12
|
function _array_with_holes(arr) {
|
|
13
13
|
if (Array.isArray(arr)) return arr;
|
|
14
14
|
}
|
|
15
|
+
function _array_without_holes(arr) {
|
|
16
|
+
if (Array.isArray(arr)) return _array_like_to_array(arr);
|
|
17
|
+
}
|
|
15
18
|
function _getRequireWildcardCache(nodeInterop) {
|
|
16
19
|
if (typeof WeakMap !== "function") return null;
|
|
17
20
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -53,6 +56,9 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
53
56
|
}
|
|
54
57
|
return newObj;
|
|
55
58
|
}
|
|
59
|
+
function _iterable_to_array(iter) {
|
|
60
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
61
|
+
}
|
|
56
62
|
function _iterable_to_array_limit(arr, i) {
|
|
57
63
|
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
58
64
|
if (_i == null) return;
|
|
@@ -80,9 +86,15 @@ function _iterable_to_array_limit(arr, i) {
|
|
|
80
86
|
function _non_iterable_rest() {
|
|
81
87
|
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
82
88
|
}
|
|
89
|
+
function _non_iterable_spread() {
|
|
90
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
91
|
+
}
|
|
83
92
|
function _sliced_to_array(arr, i) {
|
|
84
93
|
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
85
94
|
}
|
|
95
|
+
function _to_consumable_array(arr) {
|
|
96
|
+
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
|
|
97
|
+
}
|
|
86
98
|
function _unsupported_iterable_to_array(o, minLen) {
|
|
87
99
|
if (!o) return;
|
|
88
100
|
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
@@ -162,6 +174,8 @@ module.exports = (0, _definerule.defineRule)({
|
|
|
162
174
|
return {};
|
|
163
175
|
}
|
|
164
176
|
var pageUrls = (0, _url.getUrlFromPagesDirectories)('/', foundPagesDirs);
|
|
177
|
+
var appDirUrls = (0, _url.getUrlFromAppDirectory)('/', foundAppDirs);
|
|
178
|
+
var allUrls = _to_consumable_array(pageUrls).concat(_to_consumable_array(appDirUrls));
|
|
165
179
|
return {
|
|
166
180
|
JSXOpeningElement: function JSXOpeningElement(node) {
|
|
167
181
|
if (node.name.name !== 'a') {
|
|
@@ -193,8 +207,8 @@ module.exports = (0, _definerule.defineRule)({
|
|
|
193
207
|
if (/^(https?:\/\/|\/\/)/.test(hrefPath)) {
|
|
194
208
|
return;
|
|
195
209
|
}
|
|
196
|
-
|
|
197
|
-
if (
|
|
210
|
+
allUrls.forEach(function(foundUrl) {
|
|
211
|
+
if (foundUrl.test((0, _url.normalizeURL)(hrefPath))) {
|
|
198
212
|
context.report({
|
|
199
213
|
node: node,
|
|
200
214
|
message: "Do not use an `<a>` element to navigate to `".concat(hrefPath, "`. Use `<Link />` from `next/link` instead. See: ").concat(url)
|
|
@@ -8,13 +8,13 @@ Object.defineProperty(exports, "getRootDirs", {
|
|
|
8
8
|
return getRootDirs;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
var
|
|
11
|
+
var _fastglob = require("fast-glob");
|
|
12
12
|
/**
|
|
13
13
|
* Process a Next.js root directory glob.
|
|
14
14
|
*/ var processRootDir = function(rootDir) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
return (0, _fastglob.globSync)(rootDir.replace(/\\/g, '/'), {
|
|
16
|
+
onlyDirectories: true
|
|
17
|
+
});
|
|
18
18
|
};
|
|
19
19
|
var getRootDirs = function(context) {
|
|
20
20
|
var rootDirs = [
|
package/dist/utils/url.js
CHANGED
|
@@ -12,9 +12,15 @@ _export(exports, {
|
|
|
12
12
|
execOnce: function() {
|
|
13
13
|
return execOnce;
|
|
14
14
|
},
|
|
15
|
+
getUrlFromAppDirectory: function() {
|
|
16
|
+
return getUrlFromAppDirectory;
|
|
17
|
+
},
|
|
15
18
|
getUrlFromPagesDirectories: function() {
|
|
16
19
|
return getUrlFromPagesDirectories;
|
|
17
20
|
},
|
|
21
|
+
normalizeAppPath: function() {
|
|
22
|
+
return normalizeAppPath;
|
|
23
|
+
},
|
|
18
24
|
normalizeURL: function() {
|
|
19
25
|
return normalizeURL;
|
|
20
26
|
}
|
|
@@ -117,6 +123,34 @@ var fsReadDirSyncCache = {};
|
|
|
117
123
|
});
|
|
118
124
|
return res;
|
|
119
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Recursively parse app directory for URLs.
|
|
128
|
+
*/ function parseUrlForAppDir(urlprefix, directory) {
|
|
129
|
+
var _fsReadDirSyncCache, _directory;
|
|
130
|
+
var _;
|
|
131
|
+
(_ = (_fsReadDirSyncCache = fsReadDirSyncCache)[_directory = directory]) !== null && _ !== void 0 ? _ : _fsReadDirSyncCache[_directory] = _fs.readdirSync(directory, {
|
|
132
|
+
withFileTypes: true
|
|
133
|
+
});
|
|
134
|
+
var res = [];
|
|
135
|
+
fsReadDirSyncCache[directory].forEach(function(dirent) {
|
|
136
|
+
// TODO: this should account for all page extensions
|
|
137
|
+
// not just js(x) and ts(x)
|
|
138
|
+
if (/(\.(j|t)sx?)$/.test(dirent.name)) {
|
|
139
|
+
if (/^page(\.(j|t)sx?)$/.test(dirent.name)) {
|
|
140
|
+
res.push("".concat(urlprefix).concat(dirent.name.replace(/^page(\.(j|t)sx?)$/, '')));
|
|
141
|
+
} else if (!/^layout(\.(j|t)sx?)$/.test(dirent.name)) {
|
|
142
|
+
res.push("".concat(urlprefix).concat(dirent.name.replace(/(\.(j|t)sx?)$/, '')));
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
var dirPath = _path.join(directory, dirent.name);
|
|
146
|
+
if (dirent.isDirectory(dirPath) && !dirent.isSymbolicLink()) {
|
|
147
|
+
var _res;
|
|
148
|
+
(_res = res).push.apply(_res, _to_consumable_array(parseUrlForPages(urlprefix + dirent.name + '/', dirPath)));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
return res;
|
|
153
|
+
}
|
|
120
154
|
function normalizeURL(url) {
|
|
121
155
|
if (!url) {
|
|
122
156
|
return;
|
|
@@ -131,6 +165,27 @@ function normalizeURL(url) {
|
|
|
131
165
|
url = url.endsWith('/') ? url : url + '/';
|
|
132
166
|
return url;
|
|
133
167
|
}
|
|
168
|
+
function normalizeAppPath(route) {
|
|
169
|
+
return ensureLeadingSlash(route.split('/').reduce(function(pathname, segment, index, segments) {
|
|
170
|
+
// Empty segments are ignored.
|
|
171
|
+
if (!segment) {
|
|
172
|
+
return pathname;
|
|
173
|
+
}
|
|
174
|
+
// Groups are ignored.
|
|
175
|
+
if (isGroupSegment(segment)) {
|
|
176
|
+
return pathname;
|
|
177
|
+
}
|
|
178
|
+
// Parallel segments are ignored.
|
|
179
|
+
if (segment[0] === '@') {
|
|
180
|
+
return pathname;
|
|
181
|
+
}
|
|
182
|
+
// The last segment (if it's a leaf) should be ignored.
|
|
183
|
+
if ((segment === 'page' || segment === 'route') && index === segments.length - 1) {
|
|
184
|
+
return pathname;
|
|
185
|
+
}
|
|
186
|
+
return "".concat(pathname, "/").concat(segment);
|
|
187
|
+
}, ''));
|
|
188
|
+
}
|
|
134
189
|
function getUrlFromPagesDirectories(urlPrefix, directories) {
|
|
135
190
|
return Array.from(// De-duplicate similar pages across multiple directories.
|
|
136
191
|
new Set(directories.flatMap(function(directory) {
|
|
@@ -143,6 +198,18 @@ function getUrlFromPagesDirectories(urlPrefix, directories) {
|
|
|
143
198
|
return new RegExp(urlReg);
|
|
144
199
|
});
|
|
145
200
|
}
|
|
201
|
+
function getUrlFromAppDirectory(urlPrefix, directories) {
|
|
202
|
+
return Array.from(// De-duplicate similar pages across multiple directories.
|
|
203
|
+
new Set(directories.map(function(directory) {
|
|
204
|
+
return parseUrlForAppDir(urlPrefix, directory);
|
|
205
|
+
}).flat().map(// Since the URLs are normalized we add `^` and `$` to the RegExp to make sure they match exactly.
|
|
206
|
+
function(url) {
|
|
207
|
+
return "^".concat(normalizeAppPath(url), "$");
|
|
208
|
+
}))).map(function(urlReg) {
|
|
209
|
+
urlReg = urlReg.replace(/\[.*\]/g, '((?!.+?\\..+?).*?)');
|
|
210
|
+
return new RegExp(urlReg);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
146
213
|
function execOnce(fn) {
|
|
147
214
|
var used = false;
|
|
148
215
|
var result;
|
|
@@ -157,3 +224,9 @@ function execOnce(fn) {
|
|
|
157
224
|
return result;
|
|
158
225
|
};
|
|
159
226
|
}
|
|
227
|
+
function ensureLeadingSlash(route) {
|
|
228
|
+
return route.startsWith('/') ? route : "/".concat(route);
|
|
229
|
+
}
|
|
230
|
+
function isGroupSegment(segment) {
|
|
231
|
+
return segment[0] === '(' && segment.endsWith(')');
|
|
232
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@next/eslint-plugin-next",
|
|
3
|
-
"version": "15.0.0
|
|
3
|
+
"version": "15.0.0",
|
|
4
4
|
"description": "ESLint plugin for Next.js.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dist"
|
|
13
13
|
],
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"glob": "
|
|
15
|
+
"fast-glob": "3.3.1"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"eslint": "8.56.0"
|