@sarj/eslint-plugin 16.14.2 → 16.14.3
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.
- package/dist/index.cjs +30 -52
- package/dist/index.js +8 -30
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
52
52
|
// package.json
|
|
53
53
|
var package_default = {
|
|
54
54
|
name: "@sarj/eslint-plugin",
|
|
55
|
-
version: "16.14.
|
|
55
|
+
version: "16.14.3",
|
|
56
56
|
packageManager: "npm@12.2.0",
|
|
57
57
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
58
58
|
type: "module",
|
|
@@ -382,6 +382,7 @@ function deepFreeze(value) {
|
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
// src/rules/_paths.ts
|
|
385
|
+
var import_node_path = require("path");
|
|
385
386
|
var LINE_TERMINATOR_RE = /[\n\r\u2028\u2029]/u;
|
|
386
387
|
var SCRIPT_FILE_RE = /(?:^|[\\/])scripts[\\/]|\.mjs$/;
|
|
387
388
|
var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
@@ -465,6 +466,10 @@ function leadingCommentBodies(sourceText) {
|
|
|
465
466
|
function isScriptFile(filename) {
|
|
466
467
|
return SCRIPT_FILE_RE.test(filename);
|
|
467
468
|
}
|
|
469
|
+
function matchesAnyPattern(filename, patterns) {
|
|
470
|
+
const normalized = filename.replaceAll("\\", "/");
|
|
471
|
+
return patterns.some((pattern) => import_node_path.posix.matchesGlob(normalized, pattern.replaceAll("\\", "/")));
|
|
472
|
+
}
|
|
468
473
|
function commentLineEnd(sourceText, start) {
|
|
469
474
|
const end = sourceText.slice(start).search(LINE_TERMINATOR_RE);
|
|
470
475
|
return end === -1 ? sourceText.length : start + end;
|
|
@@ -5842,15 +5847,6 @@ var NO_ENUM_DOCUMENTATION = {
|
|
|
5842
5847
|
{ id: "generated-header", scenarioId: "native-header-boundary", title: "Respect a native generated banner", outcome: "no-match", files: [{ path: "src/status.ts", source: '// auto-generated file\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 0, public: true }
|
|
5843
5848
|
]
|
|
5844
5849
|
};
|
|
5845
|
-
function matchesAnyPattern(filename, patterns) {
|
|
5846
|
-
for (const pattern of patterns) {
|
|
5847
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
5848
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
5849
|
-
return true;
|
|
5850
|
-
}
|
|
5851
|
-
}
|
|
5852
|
-
return false;
|
|
5853
|
-
}
|
|
5854
5850
|
var no_enum_default = createRule({
|
|
5855
5851
|
name: "no-enum",
|
|
5856
5852
|
documentation: NO_ENUM_DOCUMENTATION,
|
|
@@ -6515,15 +6511,6 @@ var GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
|
|
|
6515
6511
|
]);
|
|
6516
6512
|
var CLIENT_ONLY_MODULES = /^(react|react-dom|react-native|svelte|vue|preact|solid-js)(\/|$)|^next\/(navigation|router|link|image)$/;
|
|
6517
6513
|
var RACE_METHODS = /* @__PURE__ */ new Set(["race", "any"]);
|
|
6518
|
-
function matchesAnyPattern2(filename, patterns) {
|
|
6519
|
-
for (const pattern of patterns) {
|
|
6520
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
6521
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
6522
|
-
return true;
|
|
6523
|
-
}
|
|
6524
|
-
}
|
|
6525
|
-
return false;
|
|
6526
|
-
}
|
|
6527
6514
|
function isSetTimeoutCallee(callee) {
|
|
6528
6515
|
callee = unwrapExpression(callee);
|
|
6529
6516
|
if (callee.type === import_utils37.AST_NODE_TYPES.Identifier) {
|
|
@@ -6629,7 +6616,7 @@ var no_hand_rolled_sleep_default = createRule({
|
|
|
6629
6616
|
return {};
|
|
6630
6617
|
}
|
|
6631
6618
|
const allowIn = optionsArg?.allowIn ?? [];
|
|
6632
|
-
if (allowIn.length > 0 &&
|
|
6619
|
+
if (allowIn.length > 0 && matchesAnyPattern(filename, allowIn)) {
|
|
6633
6620
|
return {};
|
|
6634
6621
|
}
|
|
6635
6622
|
const checkClientModules = optionsArg?.checkClientModules ?? false;
|
|
@@ -16398,7 +16385,7 @@ function unwrapTransparentExport(node) {
|
|
|
16398
16385
|
var import_utils95 = require("@typescript-eslint/utils");
|
|
16399
16386
|
var import_typescript_estree = require("@typescript-eslint/typescript-estree");
|
|
16400
16387
|
var import_node_fs = require("fs");
|
|
16401
|
-
var
|
|
16388
|
+
var import_node_path2 = require("path");
|
|
16402
16389
|
var import_jsonc_parser = require("jsonc-parser");
|
|
16403
16390
|
var PREFER_SHADCN_PRIMITIVES_DOCUMENTATION = {
|
|
16404
16391
|
summary: "Require visible raw JSX controls to use the corresponding shared shadcn primitive.",
|
|
@@ -16460,9 +16447,9 @@ var AMBIGUOUS_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
|
16460
16447
|
var MAX_PROJECT_FILE_BYTES = 1048576;
|
|
16461
16448
|
var PROJECT_PRIMITIVES_CACHE = /* @__PURE__ */ new Map();
|
|
16462
16449
|
function detectProjectPrimitives(filename, requested) {
|
|
16463
|
-
const packageRoot = findPackageRoot((0,
|
|
16450
|
+
const packageRoot = findPackageRoot((0, import_node_path2.dirname)(filename));
|
|
16464
16451
|
if (packageRoot === null) return { available: /* @__PURE__ */ new Set(), uiRoot: null };
|
|
16465
|
-
const manifest = readJsonc((0,
|
|
16452
|
+
const manifest = readJsonc((0, import_node_path2.join)(packageRoot, "components.json"));
|
|
16466
16453
|
const alias = stringProperty(manifest, "aliases", "ui");
|
|
16467
16454
|
const unresolvedUiRoot = alias === null ? null : resolveAlias(packageRoot, alias);
|
|
16468
16455
|
if (unresolvedUiRoot === null) return { available: /* @__PURE__ */ new Set(), uiRoot: null };
|
|
@@ -16474,14 +16461,14 @@ function detectProjectPrimitives(filename, requested) {
|
|
|
16474
16461
|
for (const [capability, moduleName] of Object.entries(CAPABILITIES)) {
|
|
16475
16462
|
if (!requested.has(capability)) continue;
|
|
16476
16463
|
moduleCandidates.set(capability, ["tsx", "ts", "jsx", "js"].flatMap((extension) => [
|
|
16477
|
-
(0,
|
|
16478
|
-
(0,
|
|
16464
|
+
(0, import_node_path2.join)(uiRoot, `${moduleName}.${extension}`),
|
|
16465
|
+
(0, import_node_path2.join)(uiRoot, moduleName, `index.${extension}`)
|
|
16479
16466
|
]));
|
|
16480
16467
|
}
|
|
16481
16468
|
const fingerprint = [
|
|
16482
|
-
(0,
|
|
16483
|
-
(0,
|
|
16484
|
-
(0,
|
|
16469
|
+
(0, import_node_path2.join)(packageRoot, "components.json"),
|
|
16470
|
+
(0, import_node_path2.join)(packageRoot, "tsconfig.json"),
|
|
16471
|
+
(0, import_node_path2.join)(packageRoot, "jsconfig.json"),
|
|
16485
16472
|
...[...moduleCandidates.values()].flat()
|
|
16486
16473
|
].map(fileFingerprint).join("|");
|
|
16487
16474
|
const cacheKey = `${packageRoot}:${[...requested].sort().join(",")}`;
|
|
@@ -16508,8 +16495,8 @@ function fileFingerprint(path) {
|
|
|
16508
16495
|
}
|
|
16509
16496
|
}
|
|
16510
16497
|
function isWithin2(root, candidate2) {
|
|
16511
|
-
const path = (0,
|
|
16512
|
-
return path === "" || !path.startsWith(`..${
|
|
16498
|
+
const path = (0, import_node_path2.relative)(root, candidate2);
|
|
16499
|
+
return path === "" || !path.startsWith(`..${import_node_path2.sep}`) && path !== ".." && !(0, import_node_path2.isAbsolute)(path);
|
|
16513
16500
|
}
|
|
16514
16501
|
function safeContainedDirectory(root, candidate2) {
|
|
16515
16502
|
try {
|
|
@@ -16523,10 +16510,10 @@ function safeContainedDirectory(root, candidate2) {
|
|
|
16523
16510
|
}
|
|
16524
16511
|
function findPackageRoot(startDir) {
|
|
16525
16512
|
let dir = startDir;
|
|
16526
|
-
const filesystemRoot = (0,
|
|
16513
|
+
const filesystemRoot = (0, import_node_path2.parse)(dir).root;
|
|
16527
16514
|
for (; ; ) {
|
|
16528
|
-
if ((0, import_node_fs.existsSync)((0,
|
|
16529
|
-
const parent = (0,
|
|
16515
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path2.join)(dir, "package.json"))) return dir;
|
|
16516
|
+
const parent = (0, import_node_path2.dirname)(dir);
|
|
16530
16517
|
if (dir === filesystemRoot || parent === dir) return null;
|
|
16531
16518
|
dir = parent;
|
|
16532
16519
|
}
|
|
@@ -16563,9 +16550,9 @@ function stringProperty(value, ...keys) {
|
|
|
16563
16550
|
return typeof current === "string" && current.trim() !== "" ? current : null;
|
|
16564
16551
|
}
|
|
16565
16552
|
function resolveAlias(packageRoot, alias) {
|
|
16566
|
-
if ((0,
|
|
16567
|
-
if (alias.startsWith(".")) return (0,
|
|
16568
|
-
const configPath = ["tsconfig.json", "jsconfig.json"].map((name) => (0,
|
|
16553
|
+
if ((0, import_node_path2.isAbsolute)(alias)) return null;
|
|
16554
|
+
if (alias.startsWith(".")) return (0, import_node_path2.resolve)(packageRoot, alias);
|
|
16555
|
+
const configPath = ["tsconfig.json", "jsconfig.json"].map((name) => (0, import_node_path2.join)(packageRoot, name)).find(import_node_fs.existsSync);
|
|
16569
16556
|
if (configPath === void 0) return null;
|
|
16570
16557
|
const config = readJsonc(configPath);
|
|
16571
16558
|
if (typeof config !== "object" || config === null) return null;
|
|
@@ -16578,7 +16565,7 @@ function resolveAlias(packageRoot, alias) {
|
|
|
16578
16565
|
const matches = matchingAliasTargets(paths, alias);
|
|
16579
16566
|
const [match] = matches;
|
|
16580
16567
|
if (matches.length !== 1 || match === void 0) return null;
|
|
16581
|
-
return (0,
|
|
16568
|
+
return (0, import_node_path2.resolve)(packageRoot, baseUrl, match);
|
|
16582
16569
|
}
|
|
16583
16570
|
function exportsPrimitive(path, exportName) {
|
|
16584
16571
|
try {
|
|
@@ -22666,15 +22653,6 @@ var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
|
22666
22653
|
}
|
|
22667
22654
|
]
|
|
22668
22655
|
};
|
|
22669
|
-
function matchesAnyPattern3(filename, patterns) {
|
|
22670
|
-
for (const pattern of patterns) {
|
|
22671
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
22672
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
22673
|
-
return true;
|
|
22674
|
-
}
|
|
22675
|
-
}
|
|
22676
|
-
return false;
|
|
22677
|
-
}
|
|
22678
22656
|
function emptySignal(expression, resolvesToGlobal) {
|
|
22679
22657
|
const value = unwrapExpression(expression);
|
|
22680
22658
|
if (value.type === import_utils121.AST_NODE_TYPES.Literal && value.value === null)
|
|
@@ -22755,7 +22733,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
22755
22733
|
return {};
|
|
22756
22734
|
}
|
|
22757
22735
|
const allowIn = optionsArg?.allowIn ?? [];
|
|
22758
|
-
if (allowIn.length > 0 &&
|
|
22736
|
+
if (allowIn.length > 0 && matchesAnyPattern(context.filename, allowIn)) {
|
|
22759
22737
|
return {};
|
|
22760
22738
|
}
|
|
22761
22739
|
function resolvesToGlobal(identifier) {
|
|
@@ -24871,7 +24849,7 @@ var import_utils131 = require("@typescript-eslint/utils");
|
|
|
24871
24849
|
|
|
24872
24850
|
// src/rules/_is-framework-entrypoint.ts
|
|
24873
24851
|
var import_node_fs2 = require("fs");
|
|
24874
|
-
var
|
|
24852
|
+
var import_node_path3 = require("path");
|
|
24875
24853
|
var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]);
|
|
24876
24854
|
var NEXT_COMPONENT = /^(?:src\/)?app\/(?:.*\/)?(?:page|layout|loading|not-found|template|error|global-error|default|forbidden|unauthorized)\.[jt]sx?$/u;
|
|
24877
24855
|
var NEXT_METADATA = /^(?:src\/)?app\/(?:.*\/)?(?:(?:opengraph-image|twitter-image|icon|apple-icon)\.[jt]sx?|(?:robots|sitemap|manifest)\.[jt]s)$/u;
|
|
@@ -24881,7 +24859,7 @@ function isFrameworkEntrypoint(filename, exportKey) {
|
|
|
24881
24859
|
if (!/(?:^|\/)(?:app|pages)\/|(?:^|\/)(?:middleware|proxy|instrumentation)\.[jt]s$/u.test(normalized)) return false;
|
|
24882
24860
|
const owner = packageOwner(normalized);
|
|
24883
24861
|
if (owner === null) return false;
|
|
24884
|
-
const path = (0,
|
|
24862
|
+
const path = (0, import_node_path3.relative)(owner.root, normalized).replaceAll("\\", "/");
|
|
24885
24863
|
if (declaresFramework(owner.metadata, "next") && isNextEntrypoint(path, exportKey)) return true;
|
|
24886
24864
|
return declaresFramework(owner.metadata, "astro") && isAstroEntrypoint(path, exportKey);
|
|
24887
24865
|
}
|
|
@@ -24903,14 +24881,14 @@ function isAstroEntrypoint(path, exportKey) {
|
|
|
24903
24881
|
);
|
|
24904
24882
|
}
|
|
24905
24883
|
function packageOwner(filename) {
|
|
24906
|
-
let root = (0,
|
|
24884
|
+
let root = (0, import_node_path3.dirname)(filename);
|
|
24907
24885
|
while (true) {
|
|
24908
24886
|
try {
|
|
24909
|
-
return { root, metadata: JSON.parse((0, import_node_fs2.readFileSync)((0,
|
|
24887
|
+
return { root, metadata: JSON.parse((0, import_node_fs2.readFileSync)((0, import_node_path3.join)(root, "package.json"), "utf8")) };
|
|
24910
24888
|
} catch (error) {
|
|
24911
24889
|
if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") return null;
|
|
24912
24890
|
}
|
|
24913
|
-
const parent = (0,
|
|
24891
|
+
const parent = (0, import_node_path3.dirname)(root);
|
|
24914
24892
|
if (parent === root) return null;
|
|
24915
24893
|
root = parent;
|
|
24916
24894
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@sarj/eslint-plugin",
|
|
4
|
-
version: "16.14.
|
|
4
|
+
version: "16.14.3",
|
|
5
5
|
packageManager: "npm@12.2.0",
|
|
6
6
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
7
7
|
type: "module",
|
|
@@ -331,6 +331,7 @@ function deepFreeze(value) {
|
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
// src/rules/_paths.ts
|
|
334
|
+
import { posix } from "path";
|
|
334
335
|
var LINE_TERMINATOR_RE = /[\n\r\u2028\u2029]/u;
|
|
335
336
|
var SCRIPT_FILE_RE = /(?:^|[\\/])scripts[\\/]|\.mjs$/;
|
|
336
337
|
var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
@@ -414,6 +415,10 @@ function leadingCommentBodies(sourceText) {
|
|
|
414
415
|
function isScriptFile(filename) {
|
|
415
416
|
return SCRIPT_FILE_RE.test(filename);
|
|
416
417
|
}
|
|
418
|
+
function matchesAnyPattern(filename, patterns) {
|
|
419
|
+
const normalized = filename.replaceAll("\\", "/");
|
|
420
|
+
return patterns.some((pattern) => posix.matchesGlob(normalized, pattern.replaceAll("\\", "/")));
|
|
421
|
+
}
|
|
417
422
|
function commentLineEnd(sourceText, start) {
|
|
418
423
|
const end = sourceText.slice(start).search(LINE_TERMINATOR_RE);
|
|
419
424
|
return end === -1 ? sourceText.length : start + end;
|
|
@@ -5803,15 +5808,6 @@ var NO_ENUM_DOCUMENTATION = {
|
|
|
5803
5808
|
{ id: "generated-header", scenarioId: "native-header-boundary", title: "Respect a native generated banner", outcome: "no-match", files: [{ path: "src/status.ts", source: '// auto-generated file\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 0, public: true }
|
|
5804
5809
|
]
|
|
5805
5810
|
};
|
|
5806
|
-
function matchesAnyPattern(filename, patterns) {
|
|
5807
|
-
for (const pattern of patterns) {
|
|
5808
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
5809
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
5810
|
-
return true;
|
|
5811
|
-
}
|
|
5812
|
-
}
|
|
5813
|
-
return false;
|
|
5814
|
-
}
|
|
5815
5811
|
var no_enum_default = createRule({
|
|
5816
5812
|
name: "no-enum",
|
|
5817
5813
|
documentation: NO_ENUM_DOCUMENTATION,
|
|
@@ -6476,15 +6472,6 @@ var GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
|
|
|
6476
6472
|
]);
|
|
6477
6473
|
var CLIENT_ONLY_MODULES = /^(react|react-dom|react-native|svelte|vue|preact|solid-js)(\/|$)|^next\/(navigation|router|link|image)$/;
|
|
6478
6474
|
var RACE_METHODS = /* @__PURE__ */ new Set(["race", "any"]);
|
|
6479
|
-
function matchesAnyPattern2(filename, patterns) {
|
|
6480
|
-
for (const pattern of patterns) {
|
|
6481
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
6482
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
6483
|
-
return true;
|
|
6484
|
-
}
|
|
6485
|
-
}
|
|
6486
|
-
return false;
|
|
6487
|
-
}
|
|
6488
6475
|
function isSetTimeoutCallee(callee) {
|
|
6489
6476
|
callee = unwrapExpression(callee);
|
|
6490
6477
|
if (callee.type === AST_NODE_TYPES32.Identifier) {
|
|
@@ -6590,7 +6577,7 @@ var no_hand_rolled_sleep_default = createRule({
|
|
|
6590
6577
|
return {};
|
|
6591
6578
|
}
|
|
6592
6579
|
const allowIn = optionsArg?.allowIn ?? [];
|
|
6593
|
-
if (allowIn.length > 0 &&
|
|
6580
|
+
if (allowIn.length > 0 && matchesAnyPattern(filename, allowIn)) {
|
|
6594
6581
|
return {};
|
|
6595
6582
|
}
|
|
6596
6583
|
const checkClientModules = optionsArg?.checkClientModules ?? false;
|
|
@@ -22684,15 +22671,6 @@ var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
|
22684
22671
|
}
|
|
22685
22672
|
]
|
|
22686
22673
|
};
|
|
22687
|
-
function matchesAnyPattern3(filename, patterns) {
|
|
22688
|
-
for (const pattern of patterns) {
|
|
22689
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
22690
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
22691
|
-
return true;
|
|
22692
|
-
}
|
|
22693
|
-
}
|
|
22694
|
-
return false;
|
|
22695
|
-
}
|
|
22696
22674
|
function emptySignal(expression, resolvesToGlobal) {
|
|
22697
22675
|
const value = unwrapExpression(expression);
|
|
22698
22676
|
if (value.type === AST_NODE_TYPES104.Literal && value.value === null)
|
|
@@ -22773,7 +22751,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
22773
22751
|
return {};
|
|
22774
22752
|
}
|
|
22775
22753
|
const allowIn = optionsArg?.allowIn ?? [];
|
|
22776
|
-
if (allowIn.length > 0 &&
|
|
22754
|
+
if (allowIn.length > 0 && matchesAnyPattern(context.filename, allowIn)) {
|
|
22777
22755
|
return {};
|
|
22778
22756
|
}
|
|
22779
22757
|
function resolvesToGlobal(identifier) {
|