uilint-eslint 0.2.29 → 0.2.30
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.d.ts +11 -0
- package/dist/index.js +162 -47
- package/dist/index.js.map +1 -1
- package/dist/rules/consistent-dark-mode.js.map +1 -1
- package/dist/rules/consistent-spacing.js.map +1 -1
- package/dist/rules/enforce-absolute-imports.js.map +1 -1
- package/dist/rules/no-any-in-props.js.map +1 -1
- package/dist/rules/no-arbitrary-tailwind.js.map +1 -1
- package/dist/rules/no-direct-store-import.js.map +1 -1
- package/dist/rules/no-mixed-component-libraries.js +6 -5
- package/dist/rules/no-mixed-component-libraries.js.map +1 -1
- package/dist/rules/no-prop-drilling-depth.js.map +1 -1
- package/dist/rules/no-secrets-in-code.js.map +1 -1
- package/dist/rules/no-semantic-duplicates.js.map +1 -1
- package/dist/rules/prefer-zustand-state-management.js.map +1 -1
- package/dist/rules/require-input-validation.js.map +1 -1
- package/dist/rules/require-test-coverage.js +9 -15
- package/dist/rules/require-test-coverage.js.map +1 -1
- package/dist/rules/semantic-vision.js.map +1 -1
- package/dist/rules/semantic.js +6 -5
- package/dist/rules/semantic.js.map +1 -1
- package/dist/rules/zustand-use-selectors.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +17 -13
- package/src/rule-registry.ts +6 -5
- package/src/rules/{no-mixed-component-libraries.ts → no-mixed-component-libraries/index.ts} +3 -2
- package/src/rules/no-mixed-component-libraries.test.ts +2 -2
- package/src/rules/{require-test-coverage.ts → require-test-coverage/index.ts} +4 -10
- package/src/{utils → rules/require-test-coverage/lib}/coverage-aggregator.ts +2 -2
- package/src/{utils → rules/require-test-coverage/lib}/dependency-graph.ts +1 -1
- package/src/rules/require-test-coverage/lib/export-resolver.ts +348 -0
- package/src/{utils → rules/require-test-coverage/lib}/jsx-coverage-analyzer.ts +0 -26
- package/src/rules/require-test-coverage.test.ts +1 -1
- package/src/rules/{semantic.ts → semantic/index.ts} +4 -3
- package/src/utils/coverage-aggregator.test.ts +2 -2
- package/src/utils/create-rule.ts +12 -0
- package/src/utils/dependency-graph.test.ts +1 -1
- package/src/utils/file-categorizer.test.ts +1 -1
- package/src/utils/import-graph.test.ts +3 -3
- package/src/utils/jsx-coverage-analyzer.test.ts +1 -1
- /package/src/{utils → rules/no-mixed-component-libraries/lib}/component-parser.ts +0 -0
- /package/src/{utils → rules/no-mixed-component-libraries/lib}/export-resolver.ts +0 -0
- /package/src/{utils → rules/no-mixed-component-libraries/lib}/import-graph.ts +0 -0
- /package/src/{utils → rules/require-test-coverage/lib}/file-categorizer.ts +0 -0
- /package/src/{utils → rules/semantic/lib}/cache.ts +0 -0
- /package/src/{utils → rules/semantic/lib}/styleguide-loader.ts +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -79,6 +79,17 @@ interface RuleMeta {
|
|
|
79
79
|
* Example: ["coverage-aggregator", "dependency-graph"]
|
|
80
80
|
*/
|
|
81
81
|
internalDependencies?: string[];
|
|
82
|
+
/**
|
|
83
|
+
* Whether this rule is directory-based (has lib/ folder with utilities).
|
|
84
|
+
* Directory-based rules are installed as folders with index.ts and lib/ subdirectory.
|
|
85
|
+
* Single-file rules are installed as single .ts files.
|
|
86
|
+
*
|
|
87
|
+
* When true, ESLint config imports will use:
|
|
88
|
+
* ./.uilint/rules/rule-id/index.js
|
|
89
|
+
* When false (default):
|
|
90
|
+
* ./.uilint/rules/rule-id.js
|
|
91
|
+
*/
|
|
92
|
+
isDirectoryBased?: boolean;
|
|
82
93
|
}
|
|
83
94
|
/**
|
|
84
95
|
* Helper to define rule metadata with type safety
|
package/dist/index.js
CHANGED
|
@@ -1108,7 +1108,7 @@ var prefer_zustand_state_management_default = createRule({
|
|
|
1108
1108
|
}
|
|
1109
1109
|
});
|
|
1110
1110
|
|
|
1111
|
-
// src/
|
|
1111
|
+
// src/rules/no-mixed-component-libraries/lib/export-resolver.ts
|
|
1112
1112
|
import { ResolverFactory } from "oxc-resolver";
|
|
1113
1113
|
import { parse } from "@typescript-eslint/typescript-estree";
|
|
1114
1114
|
import { readFileSync, existsSync } from "fs";
|
|
@@ -1302,7 +1302,7 @@ function clearResolverCaches() {
|
|
|
1302
1302
|
resolvedPathCache.clear();
|
|
1303
1303
|
}
|
|
1304
1304
|
|
|
1305
|
-
// src/
|
|
1305
|
+
// src/rules/no-mixed-component-libraries/lib/component-parser.ts
|
|
1306
1306
|
var LIBRARY_PATTERNS = {
|
|
1307
1307
|
shadcn: ["@/components/ui", "@radix-ui/", "components/ui/"],
|
|
1308
1308
|
mui: ["@mui/material", "@mui/icons-material", "@emotion/"],
|
|
@@ -1482,7 +1482,7 @@ function parseComponentBody(filePath, componentName) {
|
|
|
1482
1482
|
return result;
|
|
1483
1483
|
}
|
|
1484
1484
|
|
|
1485
|
-
// src/
|
|
1485
|
+
// src/rules/no-mixed-component-libraries/lib/import-graph.ts
|
|
1486
1486
|
var componentLibraryCache = /* @__PURE__ */ new Map();
|
|
1487
1487
|
function getComponentLibrary(contextFilePath, componentName, importSource) {
|
|
1488
1488
|
const directLibrary = detectLibraryFromSource(importSource);
|
|
@@ -1600,7 +1600,7 @@ function clearCache() {
|
|
|
1600
1600
|
clearResolverCaches();
|
|
1601
1601
|
}
|
|
1602
1602
|
|
|
1603
|
-
// src/rules/no-mixed-component-libraries.ts
|
|
1603
|
+
// src/rules/no-mixed-component-libraries/index.ts
|
|
1604
1604
|
var meta6 = defineRuleMeta({
|
|
1605
1605
|
id: "no-mixed-component-libraries",
|
|
1606
1606
|
name: "No Mixed Component Libraries",
|
|
@@ -1680,7 +1680,8 @@ import { Card } from '@/components/ui/card';
|
|
|
1680
1680
|
- **mui**: Material-UI (\`@mui/material\`, \`@mui/joy\`)
|
|
1681
1681
|
- **chakra**: Chakra UI (\`@chakra-ui/react\`)
|
|
1682
1682
|
- **antd**: Ant Design (\`antd\`)
|
|
1683
|
-
|
|
1683
|
+
`,
|
|
1684
|
+
isDirectoryBased: true
|
|
1684
1685
|
});
|
|
1685
1686
|
var no_mixed_component_libraries_default = createRule({
|
|
1686
1687
|
name: "no-mixed-component-libraries",
|
|
@@ -1807,12 +1808,12 @@ var no_mixed_component_libraries_default = createRule({
|
|
|
1807
1808
|
}
|
|
1808
1809
|
});
|
|
1809
1810
|
|
|
1810
|
-
// src/rules/semantic.ts
|
|
1811
|
+
// src/rules/semantic/index.ts
|
|
1811
1812
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
1812
1813
|
import { spawnSync } from "child_process";
|
|
1813
1814
|
import { dirname as dirname4, join as join4, relative } from "path";
|
|
1814
1815
|
|
|
1815
|
-
// src/
|
|
1816
|
+
// src/rules/semantic/lib/cache.ts
|
|
1816
1817
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
1817
1818
|
import { dirname as dirname2, join as join2 } from "path";
|
|
1818
1819
|
var xxhashInstance = null;
|
|
@@ -1896,7 +1897,7 @@ function clearCache2(projectRoot) {
|
|
|
1896
1897
|
saveCache(projectRoot, { version: CACHE_VERSION, entries: {} });
|
|
1897
1898
|
}
|
|
1898
1899
|
|
|
1899
|
-
// src/
|
|
1900
|
+
// src/rules/semantic/lib/styleguide-loader.ts
|
|
1900
1901
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
1901
1902
|
import { dirname as dirname3, isAbsolute, join as join3, resolve } from "path";
|
|
1902
1903
|
var DEFAULT_STYLEGUIDE_PATHS = [
|
|
@@ -1980,7 +1981,7 @@ function getStyleguide(startDir, explicitPath) {
|
|
|
1980
1981
|
}
|
|
1981
1982
|
}
|
|
1982
1983
|
|
|
1983
|
-
// src/rules/semantic.ts
|
|
1984
|
+
// src/rules/semantic/index.ts
|
|
1984
1985
|
import { UILINT_DEFAULT_OLLAMA_MODEL } from "uilint-core";
|
|
1985
1986
|
import { buildSourceScanPrompt } from "uilint-core";
|
|
1986
1987
|
var meta7 = defineRuleMeta({
|
|
@@ -2067,7 +2068,8 @@ styleguide. It catches semantic issues that pattern-based rules can't detect, li
|
|
|
2067
2068
|
- First run may be slow as the model loads; subsequent runs use cache
|
|
2068
2069
|
- Works best with detailed, specific styleguide documentation
|
|
2069
2070
|
- Set to "off" in CI to avoid slow builds (use pre-commit hooks locally)
|
|
2070
|
-
|
|
2071
|
+
`,
|
|
2072
|
+
isDirectoryBased: true
|
|
2071
2073
|
});
|
|
2072
2074
|
var semantic_default = createRule({
|
|
2073
2075
|
name: "semantic",
|
|
@@ -4708,12 +4710,12 @@ var no_semantic_duplicates_default = createRule({
|
|
|
4708
4710
|
}
|
|
4709
4711
|
});
|
|
4710
4712
|
|
|
4711
|
-
// src/rules/require-test-coverage.ts
|
|
4712
|
-
import { existsSync as
|
|
4713
|
-
import { dirname as
|
|
4713
|
+
// src/rules/require-test-coverage/index.ts
|
|
4714
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10, statSync as statSync2 } from "fs";
|
|
4715
|
+
import { dirname as dirname8, join as join8, basename as basename2, relative as relative4 } from "path";
|
|
4714
4716
|
import { execSync } from "child_process";
|
|
4715
4717
|
|
|
4716
|
-
// src/
|
|
4718
|
+
// src/rules/require-test-coverage/lib/file-categorizer.ts
|
|
4717
4719
|
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
|
|
4718
4720
|
import { basename } from "path";
|
|
4719
4721
|
import { parse as parse2 } from "@typescript-eslint/typescript-estree";
|
|
@@ -4876,8 +4878,127 @@ function analyzeExports(ast) {
|
|
|
4876
4878
|
};
|
|
4877
4879
|
}
|
|
4878
4880
|
|
|
4879
|
-
// src/
|
|
4880
|
-
import { existsSync as
|
|
4881
|
+
// src/rules/require-test-coverage/lib/dependency-graph.ts
|
|
4882
|
+
import { existsSync as existsSync9, statSync } from "fs";
|
|
4883
|
+
|
|
4884
|
+
// src/rules/require-test-coverage/lib/export-resolver.ts
|
|
4885
|
+
import { ResolverFactory as ResolverFactory2 } from "oxc-resolver";
|
|
4886
|
+
import { parse as parse3 } from "@typescript-eslint/typescript-estree";
|
|
4887
|
+
import { readFileSync as readFileSync8, existsSync as existsSync8 } from "fs";
|
|
4888
|
+
import { dirname as dirname7, join as join7 } from "path";
|
|
4889
|
+
var resolverFactory2 = null;
|
|
4890
|
+
var astCache2 = /* @__PURE__ */ new Map();
|
|
4891
|
+
var resolvedPathCache2 = /* @__PURE__ */ new Map();
|
|
4892
|
+
function getResolverFactory2() {
|
|
4893
|
+
if (!resolverFactory2) {
|
|
4894
|
+
resolverFactory2 = new ResolverFactory2({
|
|
4895
|
+
extensions: [".tsx", ".ts", ".jsx", ".js"],
|
|
4896
|
+
mainFields: ["module", "main"],
|
|
4897
|
+
conditionNames: ["import", "require", "node", "default"],
|
|
4898
|
+
// Enable TypeScript path resolution
|
|
4899
|
+
tsconfig: {
|
|
4900
|
+
configFile: "tsconfig.json",
|
|
4901
|
+
references: "auto"
|
|
4902
|
+
}
|
|
4903
|
+
});
|
|
4904
|
+
}
|
|
4905
|
+
return resolverFactory2;
|
|
4906
|
+
}
|
|
4907
|
+
function resolveImportPath2(importSource, fromFile) {
|
|
4908
|
+
const cacheKey = `${fromFile}::${importSource}`;
|
|
4909
|
+
if (resolvedPathCache2.has(cacheKey)) {
|
|
4910
|
+
return resolvedPathCache2.get(cacheKey) ?? null;
|
|
4911
|
+
}
|
|
4912
|
+
if (importSource.startsWith("react") || importSource.startsWith("next") || !importSource.startsWith(".") && !importSource.startsWith("@/") && !importSource.startsWith("~/")) {
|
|
4913
|
+
if (importSource.includes("@mui/") || importSource.includes("@chakra-ui/") || importSource.includes("antd") || importSource.includes("@radix-ui/")) {
|
|
4914
|
+
resolvedPathCache2.set(cacheKey, null);
|
|
4915
|
+
return null;
|
|
4916
|
+
}
|
|
4917
|
+
resolvedPathCache2.set(cacheKey, null);
|
|
4918
|
+
return null;
|
|
4919
|
+
}
|
|
4920
|
+
try {
|
|
4921
|
+
const factory = getResolverFactory2();
|
|
4922
|
+
const fromDir = dirname7(fromFile);
|
|
4923
|
+
const result = factory.sync(fromDir, importSource);
|
|
4924
|
+
if (result.path) {
|
|
4925
|
+
resolvedPathCache2.set(cacheKey, result.path);
|
|
4926
|
+
return result.path;
|
|
4927
|
+
}
|
|
4928
|
+
} catch {
|
|
4929
|
+
const resolved = manualResolve2(importSource, fromFile);
|
|
4930
|
+
resolvedPathCache2.set(cacheKey, resolved);
|
|
4931
|
+
return resolved;
|
|
4932
|
+
}
|
|
4933
|
+
resolvedPathCache2.set(cacheKey, null);
|
|
4934
|
+
return null;
|
|
4935
|
+
}
|
|
4936
|
+
function manualResolve2(importSource, fromFile) {
|
|
4937
|
+
const fromDir = dirname7(fromFile);
|
|
4938
|
+
const extensions = [".tsx", ".ts", ".jsx", ".js"];
|
|
4939
|
+
if (importSource.startsWith("@/")) {
|
|
4940
|
+
const projectRoot = findProjectRoot5(fromFile);
|
|
4941
|
+
if (projectRoot) {
|
|
4942
|
+
const relativePath = importSource.slice(2);
|
|
4943
|
+
for (const ext of extensions) {
|
|
4944
|
+
const candidate = join7(projectRoot, relativePath + ext);
|
|
4945
|
+
if (existsSync8(candidate)) {
|
|
4946
|
+
return candidate;
|
|
4947
|
+
}
|
|
4948
|
+
const indexCandidate = join7(projectRoot, relativePath, `index${ext}`);
|
|
4949
|
+
if (existsSync8(indexCandidate)) {
|
|
4950
|
+
return indexCandidate;
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
if (importSource.startsWith(".")) {
|
|
4956
|
+
for (const ext of extensions) {
|
|
4957
|
+
const candidate = join7(fromDir, importSource + ext);
|
|
4958
|
+
if (existsSync8(candidate)) {
|
|
4959
|
+
return candidate;
|
|
4960
|
+
}
|
|
4961
|
+
const indexCandidate = join7(fromDir, importSource, `index${ext}`);
|
|
4962
|
+
if (existsSync8(indexCandidate)) {
|
|
4963
|
+
return indexCandidate;
|
|
4964
|
+
}
|
|
4965
|
+
}
|
|
4966
|
+
}
|
|
4967
|
+
return null;
|
|
4968
|
+
}
|
|
4969
|
+
function findProjectRoot5(fromFile) {
|
|
4970
|
+
let dir = dirname7(fromFile);
|
|
4971
|
+
const root = "/";
|
|
4972
|
+
while (dir !== root) {
|
|
4973
|
+
if (existsSync8(join7(dir, "tsconfig.json"))) {
|
|
4974
|
+
return dir;
|
|
4975
|
+
}
|
|
4976
|
+
if (existsSync8(join7(dir, "package.json"))) {
|
|
4977
|
+
return dir;
|
|
4978
|
+
}
|
|
4979
|
+
dir = dirname7(dir);
|
|
4980
|
+
}
|
|
4981
|
+
return null;
|
|
4982
|
+
}
|
|
4983
|
+
function parseFile2(filePath) {
|
|
4984
|
+
if (astCache2.has(filePath)) {
|
|
4985
|
+
return astCache2.get(filePath);
|
|
4986
|
+
}
|
|
4987
|
+
try {
|
|
4988
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
4989
|
+
const ast = parse3(content, {
|
|
4990
|
+
jsx: true,
|
|
4991
|
+
loc: true,
|
|
4992
|
+
range: true
|
|
4993
|
+
});
|
|
4994
|
+
astCache2.set(filePath, ast);
|
|
4995
|
+
return ast;
|
|
4996
|
+
} catch {
|
|
4997
|
+
return null;
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
|
|
5001
|
+
// src/rules/require-test-coverage/lib/dependency-graph.ts
|
|
4881
5002
|
var dependencyCache = /* @__PURE__ */ new Map();
|
|
4882
5003
|
function buildDependencyGraph(entryFile, projectRoot) {
|
|
4883
5004
|
const cached = dependencyCache.get(entryFile);
|
|
@@ -4911,7 +5032,7 @@ function collectDependencies(filePath, projectRoot, allDependencies, visited) {
|
|
|
4911
5032
|
visited.add(filePath);
|
|
4912
5033
|
const imports = extractImports2(filePath);
|
|
4913
5034
|
for (const importSource of imports) {
|
|
4914
|
-
const resolvedPath =
|
|
5035
|
+
const resolvedPath = resolveImportPath2(importSource, filePath);
|
|
4915
5036
|
if (!resolvedPath) {
|
|
4916
5037
|
continue;
|
|
4917
5038
|
}
|
|
@@ -4929,10 +5050,10 @@ function collectDependencies(filePath, projectRoot, allDependencies, visited) {
|
|
|
4929
5050
|
}
|
|
4930
5051
|
}
|
|
4931
5052
|
function extractImports2(filePath) {
|
|
4932
|
-
if (!
|
|
5053
|
+
if (!existsSync9(filePath)) {
|
|
4933
5054
|
return [];
|
|
4934
5055
|
}
|
|
4935
|
-
const ast =
|
|
5056
|
+
const ast = parseFile2(filePath);
|
|
4936
5057
|
if (!ast) {
|
|
4937
5058
|
return [];
|
|
4938
5059
|
}
|
|
@@ -4979,7 +5100,7 @@ function extractDynamicImports(ast) {
|
|
|
4979
5100
|
return imports;
|
|
4980
5101
|
}
|
|
4981
5102
|
|
|
4982
|
-
// src/
|
|
5103
|
+
// src/rules/require-test-coverage/lib/coverage-aggregator.ts
|
|
4983
5104
|
function aggregateCoverage(componentFile, projectRoot, coverageData) {
|
|
4984
5105
|
const graph = buildDependencyGraph(componentFile, projectRoot);
|
|
4985
5106
|
const allFiles = /* @__PURE__ */ new Set([componentFile, ...graph.allDependencies]);
|
|
@@ -5087,7 +5208,7 @@ function calculateWeightedCoverage(files) {
|
|
|
5087
5208
|
return Math.round(percentage * 100) / 100;
|
|
5088
5209
|
}
|
|
5089
5210
|
|
|
5090
|
-
// src/
|
|
5211
|
+
// src/rules/require-test-coverage/lib/jsx-coverage-analyzer.ts
|
|
5091
5212
|
function buildDataLoc(filePath, loc) {
|
|
5092
5213
|
return `${filePath}:${loc.start.line}:${loc.start.column}`;
|
|
5093
5214
|
}
|
|
@@ -5547,7 +5668,7 @@ function findImportsUsedInJSX(jsxNode, ancestors) {
|
|
|
5547
5668
|
}
|
|
5548
5669
|
return importPaths;
|
|
5549
5670
|
}
|
|
5550
|
-
function
|
|
5671
|
+
function resolveImportPath3(importPath, currentFilePath, projectRoot) {
|
|
5551
5672
|
if (!importPath.startsWith(".") && !importPath.startsWith("/")) {
|
|
5552
5673
|
return null;
|
|
5553
5674
|
}
|
|
@@ -5586,7 +5707,7 @@ function aggregateImportCoverage(importPaths, coverage, projectRoot, currentFile
|
|
|
5586
5707
|
let totalCovered = 0;
|
|
5587
5708
|
let totalStatements = 0;
|
|
5588
5709
|
for (const importPath of importPaths) {
|
|
5589
|
-
const resolvedPath =
|
|
5710
|
+
const resolvedPath = resolveImportPath3(importPath, currentFilePath, projectRoot);
|
|
5590
5711
|
if (!resolvedPath) {
|
|
5591
5712
|
continue;
|
|
5592
5713
|
}
|
|
@@ -5610,7 +5731,7 @@ function aggregateImportCoverage(importPaths, coverage, projectRoot, currentFile
|
|
|
5610
5731
|
return { covered: totalCovered, total: totalStatements };
|
|
5611
5732
|
}
|
|
5612
5733
|
|
|
5613
|
-
// src/rules/require-test-coverage.ts
|
|
5734
|
+
// src/rules/require-test-coverage/index.ts
|
|
5614
5735
|
function simpleGlobMatch(pattern, path) {
|
|
5615
5736
|
const normalizedPath = path.replace(/\\/g, "/");
|
|
5616
5737
|
const normalizedPattern = pattern.replace(/\\/g, "/");
|
|
@@ -5728,32 +5849,26 @@ export function calculate() { ... } // Warning: No test file found
|
|
|
5728
5849
|
export function fetchData() { ... } // Warning: Coverage below threshold
|
|
5729
5850
|
\`\`\`
|
|
5730
5851
|
`,
|
|
5731
|
-
|
|
5732
|
-
internalDependencies: [
|
|
5733
|
-
"coverage-aggregator",
|
|
5734
|
-
"dependency-graph",
|
|
5735
|
-
"file-categorizer",
|
|
5736
|
-
"jsx-coverage-analyzer"
|
|
5737
|
-
]
|
|
5852
|
+
isDirectoryBased: true
|
|
5738
5853
|
});
|
|
5739
5854
|
var coverageCache = null;
|
|
5740
|
-
function
|
|
5855
|
+
function findProjectRoot6(startPath) {
|
|
5741
5856
|
let current = startPath;
|
|
5742
5857
|
let lastPackageJson = null;
|
|
5743
|
-
while (current !==
|
|
5744
|
-
if (
|
|
5858
|
+
while (current !== dirname8(current)) {
|
|
5859
|
+
if (existsSync10(join8(current, "package.json"))) {
|
|
5745
5860
|
lastPackageJson = current;
|
|
5746
5861
|
}
|
|
5747
|
-
if (
|
|
5862
|
+
if (existsSync10(join8(current, "coverage"))) {
|
|
5748
5863
|
return current;
|
|
5749
5864
|
}
|
|
5750
|
-
current =
|
|
5865
|
+
current = dirname8(current);
|
|
5751
5866
|
}
|
|
5752
5867
|
return lastPackageJson || startPath;
|
|
5753
5868
|
}
|
|
5754
5869
|
function loadCoverage(projectRoot, coveragePath) {
|
|
5755
|
-
const fullPath =
|
|
5756
|
-
if (!
|
|
5870
|
+
const fullPath = join8(projectRoot, coveragePath);
|
|
5871
|
+
if (!existsSync10(fullPath)) {
|
|
5757
5872
|
return null;
|
|
5758
5873
|
}
|
|
5759
5874
|
try {
|
|
@@ -5762,7 +5877,7 @@ function loadCoverage(projectRoot, coveragePath) {
|
|
|
5762
5877
|
if (coverageCache && coverageCache.projectRoot === projectRoot && coverageCache.coveragePath === coveragePath && coverageCache.mtime === mtime) {
|
|
5763
5878
|
return coverageCache.data;
|
|
5764
5879
|
}
|
|
5765
|
-
const content =
|
|
5880
|
+
const content = readFileSync10(fullPath, "utf-8");
|
|
5766
5881
|
const data = JSON.parse(content);
|
|
5767
5882
|
coverageCache = {
|
|
5768
5883
|
projectRoot,
|
|
@@ -5785,17 +5900,17 @@ function calculateCoverage(fileCoverage) {
|
|
|
5785
5900
|
return Math.round(covered / keys.length * 100);
|
|
5786
5901
|
}
|
|
5787
5902
|
function testFileExists(filePath, testPatterns) {
|
|
5788
|
-
const dir =
|
|
5903
|
+
const dir = dirname8(filePath);
|
|
5789
5904
|
const ext = filePath.match(/\.(tsx?|jsx?)$/)?.[0] || ".ts";
|
|
5790
5905
|
const baseName = basename2(filePath, ext);
|
|
5791
5906
|
for (const pattern of testPatterns) {
|
|
5792
5907
|
if (pattern.startsWith("__tests__/")) {
|
|
5793
|
-
const testDir =
|
|
5794
|
-
const testFile =
|
|
5908
|
+
const testDir = join8(dir, "__tests__");
|
|
5909
|
+
const testFile = join8(
|
|
5795
5910
|
testDir,
|
|
5796
5911
|
`${baseName}${pattern.replace("__tests__/", "")}`
|
|
5797
5912
|
);
|
|
5798
|
-
if (
|
|
5913
|
+
if (existsSync10(testFile)) {
|
|
5799
5914
|
return true;
|
|
5800
5915
|
}
|
|
5801
5916
|
for (const testExt of [
|
|
@@ -5804,13 +5919,13 @@ function testFileExists(filePath, testPatterns) {
|
|
|
5804
5919
|
".spec.ts",
|
|
5805
5920
|
".spec.tsx"
|
|
5806
5921
|
]) {
|
|
5807
|
-
if (
|
|
5922
|
+
if (existsSync10(join8(testDir, `${baseName}${testExt}`))) {
|
|
5808
5923
|
return true;
|
|
5809
5924
|
}
|
|
5810
5925
|
}
|
|
5811
5926
|
} else {
|
|
5812
|
-
const testFile =
|
|
5813
|
-
if (
|
|
5927
|
+
const testFile = join8(dir, `${baseName}${pattern}`);
|
|
5928
|
+
if (existsSync10(testFile)) {
|
|
5814
5929
|
return true;
|
|
5815
5930
|
}
|
|
5816
5931
|
}
|
|
@@ -6063,7 +6178,7 @@ var require_test_coverage_default = createRule({
|
|
|
6063
6178
|
const jsxThreshold = options.jsxThreshold ?? 50;
|
|
6064
6179
|
const jsxSeverity = options.jsxSeverity ?? "warn";
|
|
6065
6180
|
const filename = context.filename || context.getFilename();
|
|
6066
|
-
const projectRoot =
|
|
6181
|
+
const projectRoot = findProjectRoot6(dirname8(filename));
|
|
6067
6182
|
const relPath = relative4(projectRoot, filename);
|
|
6068
6183
|
if (shouldIgnore2(relPath, ignorePatterns)) {
|
|
6069
6184
|
return {};
|