pasika 0.5.3 → 0.5.5
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/eslint/pasika/index.js +474 -449
- package/package.json +1 -1
|
@@ -907,6 +907,224 @@ var unknownUtilityRule = {
|
|
|
907
907
|
}
|
|
908
908
|
};
|
|
909
909
|
|
|
910
|
+
// eslint/rules/enforce-cn-merge.ts
|
|
911
|
+
import path8 from "path";
|
|
912
|
+
|
|
913
|
+
// eslint/project/index.ts
|
|
914
|
+
import { readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
915
|
+
import path7 from "path";
|
|
916
|
+
|
|
917
|
+
// eslint/project/parse-module.ts
|
|
918
|
+
import path6 from "path";
|
|
919
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
920
|
+
import ts2 from "typescript";
|
|
921
|
+
var isPascalCase3 = (name) => /^[A-Z][A-Za-z0-9]*$/.test(name);
|
|
922
|
+
var isHookName = (name) => /^use[A-Z]/.test(name);
|
|
923
|
+
var isSchemaName = (name) => /[Ss]chema$/.test(name);
|
|
924
|
+
function lineOf(sourceFile, node) {
|
|
925
|
+
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
926
|
+
}
|
|
927
|
+
function returnsJsx(node) {
|
|
928
|
+
let found = false;
|
|
929
|
+
const visit = (child) => {
|
|
930
|
+
if (found) return;
|
|
931
|
+
if (ts2.isJsxElement(child) || ts2.isJsxSelfClosingElement(child) || ts2.isJsxFragment(child) || ts2.isJsxOpeningFragment(child)) {
|
|
932
|
+
found = true;
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
ts2.forEachChild(child, visit);
|
|
936
|
+
};
|
|
937
|
+
ts2.forEachChild(node, visit);
|
|
938
|
+
return found;
|
|
939
|
+
}
|
|
940
|
+
function classifyFunction(name, isTsx, hasJsx) {
|
|
941
|
+
if (isHookName(name)) return "hook";
|
|
942
|
+
if (isTsx && isPascalCase3(name) && hasJsx) return "component";
|
|
943
|
+
return "function";
|
|
944
|
+
}
|
|
945
|
+
function classifyValue(name, initializer, isTsx) {
|
|
946
|
+
const isFunctionLike = initializer !== void 0 && (ts2.isArrowFunction(initializer) || ts2.isFunctionExpression(initializer) || ts2.isFunctionDeclaration(initializer));
|
|
947
|
+
if (isHookName(name)) return "hook";
|
|
948
|
+
if (isSchemaName(name)) return "schema";
|
|
949
|
+
if (isTsx && isPascalCase3(name) && (initializer === void 0 || returnsJsx(initializer) || isFunctionLike)) {
|
|
950
|
+
return "component";
|
|
951
|
+
}
|
|
952
|
+
if (isFunctionLike) return "function";
|
|
953
|
+
return "constant";
|
|
954
|
+
}
|
|
955
|
+
function parseModule(file) {
|
|
956
|
+
const text = readFileSync2(file, "utf8");
|
|
957
|
+
const isTsx = file.endsWith(".tsx") || file.endsWith(".jsx");
|
|
958
|
+
const sourceFile = ts2.createSourceFile(file, text, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
|
|
959
|
+
const imports = [];
|
|
960
|
+
const exports = [];
|
|
961
|
+
const addImport = (specifierNode, names, node) => {
|
|
962
|
+
if (!ts2.isStringLiteral(specifierNode)) return;
|
|
963
|
+
imports.push({ specifier: specifierNode.text, names, line: lineOf(sourceFile, node) });
|
|
964
|
+
};
|
|
965
|
+
for (const statement of sourceFile.statements) {
|
|
966
|
+
if (ts2.isImportDeclaration(statement)) {
|
|
967
|
+
const names = [];
|
|
968
|
+
const bindings = statement.importClause?.namedBindings;
|
|
969
|
+
if (statement.importClause?.name) names.push(statement.importClause.name.text);
|
|
970
|
+
if (bindings && ts2.isNamedImports(bindings)) {
|
|
971
|
+
for (const element of bindings.elements) names.push(element.propertyName?.text ?? element.name.text);
|
|
972
|
+
}
|
|
973
|
+
addImport(statement.moduleSpecifier, names, statement);
|
|
974
|
+
continue;
|
|
975
|
+
}
|
|
976
|
+
if (ts2.isExportDeclaration(statement)) {
|
|
977
|
+
if (statement.moduleSpecifier) {
|
|
978
|
+
const names = [];
|
|
979
|
+
if (statement.exportClause && ts2.isNamedExports(statement.exportClause)) {
|
|
980
|
+
for (const element of statement.exportClause.elements) {
|
|
981
|
+
names.push(element.propertyName?.text ?? element.name.text);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
addImport(statement.moduleSpecifier, names, statement);
|
|
985
|
+
}
|
|
986
|
+
if (statement.exportClause && ts2.isNamedExports(statement.exportClause)) {
|
|
987
|
+
for (const element of statement.exportClause.elements) {
|
|
988
|
+
exports.push({ name: element.name.text, kind: "other", line: lineOf(sourceFile, element) });
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
continue;
|
|
992
|
+
}
|
|
993
|
+
const isExported2 = ts2.canHaveModifiers(statement) ? (ts2.getModifiers(statement) ?? []).some((modifier) => modifier.kind === ts2.SyntaxKind.ExportKeyword) : false;
|
|
994
|
+
if (!isExported2) continue;
|
|
995
|
+
if (ts2.isFunctionDeclaration(statement) && statement.name) {
|
|
996
|
+
const name = statement.name.text;
|
|
997
|
+
exports.push({
|
|
998
|
+
name,
|
|
999
|
+
kind: classifyFunction(name, isTsx, returnsJsx(statement)),
|
|
1000
|
+
line: lineOf(sourceFile, statement)
|
|
1001
|
+
});
|
|
1002
|
+
continue;
|
|
1003
|
+
}
|
|
1004
|
+
if (ts2.isVariableStatement(statement)) {
|
|
1005
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
1006
|
+
if (!ts2.isIdentifier(declaration.name)) continue;
|
|
1007
|
+
exports.push({
|
|
1008
|
+
name: declaration.name.text,
|
|
1009
|
+
kind: classifyValue(declaration.name.text, declaration.initializer, isTsx),
|
|
1010
|
+
line: lineOf(sourceFile, declaration)
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
continue;
|
|
1014
|
+
}
|
|
1015
|
+
if (ts2.isTypeAliasDeclaration(statement) || ts2.isInterfaceDeclaration(statement)) {
|
|
1016
|
+
exports.push({ name: statement.name.text, kind: "type", line: lineOf(sourceFile, statement) });
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
return { file: path6.resolve(file), imports, exports };
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// eslint/project/index.ts
|
|
1023
|
+
var MODULE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
1024
|
+
var INDEX_BASENAMES = ["index.ts", "index.tsx", "index.mts", "index.cts", "index.js", "index.jsx"];
|
|
1025
|
+
var REVALIDATE_AFTER_MS = 2e3;
|
|
1026
|
+
var symbolKey = (file, name) => `${file}\0${name}`;
|
|
1027
|
+
function listSourceFiles(dir) {
|
|
1028
|
+
let entries;
|
|
1029
|
+
try {
|
|
1030
|
+
entries = readdirSync2(dir);
|
|
1031
|
+
} catch {
|
|
1032
|
+
return [];
|
|
1033
|
+
}
|
|
1034
|
+
return entries.flatMap((entry) => {
|
|
1035
|
+
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
1036
|
+
const entryPath = path7.join(dir, entry);
|
|
1037
|
+
let stats;
|
|
1038
|
+
try {
|
|
1039
|
+
stats = statSync2(entryPath);
|
|
1040
|
+
} catch {
|
|
1041
|
+
return [];
|
|
1042
|
+
}
|
|
1043
|
+
if (stats.isDirectory()) return listSourceFiles(entryPath);
|
|
1044
|
+
return MODULE_EXTENSIONS.includes(path7.extname(entry)) ? [entryPath] : [];
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
function fingerprint(files) {
|
|
1048
|
+
let total = 0;
|
|
1049
|
+
for (const file of files) {
|
|
1050
|
+
try {
|
|
1051
|
+
total += statSync2(file).mtimeMs;
|
|
1052
|
+
} catch {
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
return `${String(files.length)}:${String(total)}`;
|
|
1056
|
+
}
|
|
1057
|
+
function resolveSpecifier(fromFile, specifier, sourceRoot) {
|
|
1058
|
+
let base;
|
|
1059
|
+
if (specifier.startsWith("@/")) {
|
|
1060
|
+
base = path7.resolve(sourceRoot, specifier.slice(2));
|
|
1061
|
+
} else if (specifier.startsWith(".")) {
|
|
1062
|
+
base = path7.resolve(path7.dirname(fromFile), specifier);
|
|
1063
|
+
} else {
|
|
1064
|
+
return void 0;
|
|
1065
|
+
}
|
|
1066
|
+
const candidates = [
|
|
1067
|
+
base,
|
|
1068
|
+
...MODULE_EXTENSIONS.map((extension) => `${base}${extension}`),
|
|
1069
|
+
...INDEX_BASENAMES.map((name) => path7.join(base, name))
|
|
1070
|
+
];
|
|
1071
|
+
for (const candidate of candidates) {
|
|
1072
|
+
try {
|
|
1073
|
+
if (statSync2(candidate).isFile()) return candidate;
|
|
1074
|
+
} catch {
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
return void 0;
|
|
1078
|
+
}
|
|
1079
|
+
function build(sourceRoot, files) {
|
|
1080
|
+
const modules = /* @__PURE__ */ new Map();
|
|
1081
|
+
const consumers = /* @__PURE__ */ new Map();
|
|
1082
|
+
const symbolConsumers = /* @__PURE__ */ new Map();
|
|
1083
|
+
for (const file of files) {
|
|
1084
|
+
try {
|
|
1085
|
+
modules.set(file, parseModule(file));
|
|
1086
|
+
} catch {
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
for (const [file, module] of modules) {
|
|
1090
|
+
for (const moduleImport of module.imports) {
|
|
1091
|
+
const target = resolveSpecifier(file, moduleImport.specifier, sourceRoot);
|
|
1092
|
+
if (!target || !modules.has(target)) continue;
|
|
1093
|
+
const fileConsumers = consumers.get(target) ?? /* @__PURE__ */ new Set();
|
|
1094
|
+
fileConsumers.add(file);
|
|
1095
|
+
consumers.set(target, fileConsumers);
|
|
1096
|
+
for (const name of moduleImport.names) {
|
|
1097
|
+
const key = symbolKey(target, name);
|
|
1098
|
+
const nameConsumers = symbolConsumers.get(key) ?? /* @__PURE__ */ new Set();
|
|
1099
|
+
nameConsumers.add(file);
|
|
1100
|
+
symbolConsumers.set(key, nameConsumers);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
return { sourceRoot, modules, consumers, symbolConsumers };
|
|
1105
|
+
}
|
|
1106
|
+
var cache;
|
|
1107
|
+
function getProjectIndex(sourceRoot) {
|
|
1108
|
+
const now = Date.now();
|
|
1109
|
+
if (cache?.index.sourceRoot === sourceRoot && now - cache.checkedAt < REVALIDATE_AFTER_MS) {
|
|
1110
|
+
return cache.index;
|
|
1111
|
+
}
|
|
1112
|
+
try {
|
|
1113
|
+
if (!statSync2(sourceRoot).isDirectory()) return void 0;
|
|
1114
|
+
} catch {
|
|
1115
|
+
return void 0;
|
|
1116
|
+
}
|
|
1117
|
+
const files = listSourceFiles(sourceRoot).sort((left, right) => left.localeCompare(right));
|
|
1118
|
+
const currentFingerprint = fingerprint(files);
|
|
1119
|
+
if (cache?.index.sourceRoot === sourceRoot && cache.fingerprint === currentFingerprint) {
|
|
1120
|
+
cache.checkedAt = now;
|
|
1121
|
+
return cache.index;
|
|
1122
|
+
}
|
|
1123
|
+
const index = build(sourceRoot, files);
|
|
1124
|
+
cache = { index, checkedAt: now, fingerprint: currentFingerprint };
|
|
1125
|
+
return index;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
910
1128
|
// eslint/rules/enforce-cn-merge.ts
|
|
911
1129
|
function classCount(str) {
|
|
912
1130
|
return str.split(/\s+/).filter(Boolean).length;
|
|
@@ -935,11 +1153,22 @@ function stringArguments(node) {
|
|
|
935
1153
|
var enforceCnMergeRule = {
|
|
936
1154
|
meta: { schema: [], type: "problem", docs: { description: "Enforce cn() for conditional class merging." } },
|
|
937
1155
|
create(context) {
|
|
1156
|
+
const packageComponents = /* @__PURE__ */ new Set();
|
|
1157
|
+
const index = getProjectIndex(sourceRootOf(context));
|
|
1158
|
+
const module = index?.modules.get(path8.resolve(context.filename));
|
|
1159
|
+
for (const moduleImport of module?.imports ?? []) {
|
|
1160
|
+
if (moduleImport.specifier.startsWith(".") || moduleImport.specifier.startsWith("@/")) continue;
|
|
1161
|
+
for (const name of moduleImport.names) {
|
|
1162
|
+
if (/^[A-Z]/.test(name)) packageComponents.add(name);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
938
1165
|
return {
|
|
939
1166
|
JSXAttribute(node) {
|
|
940
1167
|
const attributeName = node.name?.name ?? "";
|
|
941
1168
|
const element = node.parent.parent;
|
|
942
|
-
const
|
|
1169
|
+
const componentName = element.openingElement?.name;
|
|
1170
|
+
const isComponentProp = isComponentName(componentName);
|
|
1171
|
+
const isPackageComponent = componentName?.type === "JSXIdentifier" && packageComponents.has(componentName.name);
|
|
943
1172
|
if (isComponentProp && attributeName !== "className" && attributeName.endsWith("ClassName")) {
|
|
944
1173
|
context.report({
|
|
945
1174
|
node,
|
|
@@ -951,6 +1180,7 @@ var enforceCnMergeRule = {
|
|
|
951
1180
|
const valueNode = node.value;
|
|
952
1181
|
if (!valueNode) return;
|
|
953
1182
|
if (isComponentProp && attributeName === "className") {
|
|
1183
|
+
if (isPackageComponent) return;
|
|
954
1184
|
const expression = valueNode.type === "JSXExpressionContainer" ? valueNode.expression : valueNode;
|
|
955
1185
|
const invalidClass = stringArguments(expression).flatMap((value) => value.split(/\s+/).filter(Boolean)).find((className) => !isOuterLayoutClass(className));
|
|
956
1186
|
if (invalidClass) {
|
|
@@ -1085,322 +1315,107 @@ var enforceCvaVariantPropsRule = {
|
|
|
1085
1315
|
}
|
|
1086
1316
|
}
|
|
1087
1317
|
},
|
|
1088
|
-
TSTypeAliasDeclaration(node) {
|
|
1089
|
-
const aliasName = node.id?.name;
|
|
1090
|
-
if (!aliasName?.endsWith("Props")) return;
|
|
1091
|
-
if (node.typeAnnotation?.type !== "TSTypeLiteral") return;
|
|
1092
|
-
for (const member of node.typeAnnotation.members ?? []) {
|
|
1093
|
-
if (member.type !== "TSPropertySignature") continue;
|
|
1094
|
-
const keyName2 = member.key?.type === "Identifier" ? member.key.name : void 0;
|
|
1095
|
-
if (!keyName2) continue;
|
|
1096
|
-
const typeAnn = member.typeAnnotation?.typeAnnotation;
|
|
1097
|
-
if (typeAnn?.type !== "TSUnionType") continue;
|
|
1098
|
-
const allStringLiterals = (typeAnn.types ?? []).every(
|
|
1099
|
-
(t) => t.type === "TSLiteralType" && (t.literal?.type === "StringLiteral" || t.literal?.type === "Literal" && typeof t.literal.value === "string")
|
|
1100
|
-
);
|
|
1101
|
-
if (allStringLiterals && (typeAnn.types?.length ?? 0) >= 2) {
|
|
1102
|
-
for (const variantNames of cvaDefinitions.values()) {
|
|
1103
|
-
if (variantNames.includes(keyName2)) {
|
|
1104
|
-
context.report({
|
|
1105
|
-
node,
|
|
1106
|
-
message: `Variant prop "${keyName2}" duplicates CVA variant values. Use VariantProps<typeof variants> instead of manually writing union types. See docs/styling-guide/rules/component-variant-rule.md`
|
|
1107
|
-
});
|
|
1108
|
-
return;
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
};
|
|
1115
|
-
}
|
|
1116
|
-
};
|
|
1117
|
-
|
|
1118
|
-
// eslint/rules/enforce-barrel-exports.ts
|
|
1119
|
-
import path6 from "path";
|
|
1120
|
-
import fs from "fs";
|
|
1121
|
-
function isPascalCase3(str) {
|
|
1122
|
-
return /^[A-Z][A-Za-z0-9]*$/.test(str);
|
|
1123
|
-
}
|
|
1124
|
-
function isKebabCase2(str) {
|
|
1125
|
-
return /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(str);
|
|
1126
|
-
}
|
|
1127
|
-
var SUPPORT_FOLDERS = /* @__PURE__ */ new Set(["types", "schemas", "hooks", "constants", "utils", "config", "locales"]);
|
|
1128
|
-
var enforceBarrelExportsRule = {
|
|
1129
|
-
meta: {
|
|
1130
|
-
schema: [],
|
|
1131
|
-
type: "problem",
|
|
1132
|
-
docs: {
|
|
1133
|
-
description: "Enforce index.ts barrels only re-export the parent component."
|
|
1134
|
-
}
|
|
1135
|
-
},
|
|
1136
|
-
create(context) {
|
|
1137
|
-
const filename = context.filename;
|
|
1138
|
-
if (!filename) return {};
|
|
1139
|
-
const baseName = path6.basename(filename);
|
|
1140
|
-
if (baseName !== "index.ts" && baseName !== "index.cts" && baseName !== "index.mts") return {};
|
|
1141
|
-
const dirPath = path6.dirname(filename);
|
|
1142
|
-
const folderName = path6.basename(dirPath);
|
|
1143
|
-
const parentFolderName = path6.basename(path6.dirname(dirPath));
|
|
1144
|
-
if (SUPPORT_FOLDERS.has(folderName)) return {};
|
|
1145
|
-
if (!isPascalCase3(folderName) && !isKebabCase2(folderName)) return {};
|
|
1146
|
-
const matchingTsx = fs.existsSync(path6.join(dirPath, `${folderName}.tsx`)) ? folderName : null;
|
|
1147
|
-
if (!matchingTsx) return {};
|
|
1148
|
-
if (!isPascalCase3(parentFolderName) && !isKebabCase2(parentFolderName)) return {};
|
|
1149
|
-
const reExportedNames = /* @__PURE__ */ new Set();
|
|
1150
|
-
return {
|
|
1151
|
-
ExportNamedDeclaration(node) {
|
|
1152
|
-
if (!node.source) return;
|
|
1153
|
-
for (const spec of node.specifiers) {
|
|
1154
|
-
if (spec.exported.type === "Identifier") {
|
|
1155
|
-
reExportedNames.add(spec.exported.name);
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
},
|
|
1159
|
-
"Program:exit"() {
|
|
1160
|
-
if (reExportedNames.size === 0) return;
|
|
1161
|
-
if (!reExportedNames.has(matchingTsx)) {
|
|
1162
|
-
context.report({
|
|
1163
|
-
loc: { line: 1, column: 0 },
|
|
1164
|
-
message: `index.ts in "${folderName}/" must re-export "${matchingTsx}". See docs/code-organization-guide/rules/folder-nesting-rule.md`
|
|
1165
|
-
});
|
|
1166
|
-
return;
|
|
1167
|
-
}
|
|
1168
|
-
const nonParentExports = [...reExportedNames].filter((n) => n !== matchingTsx);
|
|
1169
|
-
if (nonParentExports.length > 0) {
|
|
1170
|
-
context.report({
|
|
1171
|
-
loc: { line: 1, column: 0 },
|
|
1172
|
-
message: `index.ts must not re-export exclusive children: ${nonParentExports.join(", ")}. Only "${matchingTsx}" may be re-exported. See docs/code-organization-guide/rules/folder-nesting-rule.md`
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
};
|
|
1177
|
-
}
|
|
1178
|
-
};
|
|
1179
|
-
|
|
1180
|
-
// eslint/rules/component-placement.ts
|
|
1181
|
-
import path10 from "path";
|
|
1182
|
-
|
|
1183
|
-
// eslint/project/index.ts
|
|
1184
|
-
import { readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
1185
|
-
import path8 from "path";
|
|
1186
|
-
|
|
1187
|
-
// eslint/project/parse-module.ts
|
|
1188
|
-
import path7 from "path";
|
|
1189
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
1190
|
-
import ts2 from "typescript";
|
|
1191
|
-
var isPascalCase4 = (name) => /^[A-Z][A-Za-z0-9]*$/.test(name);
|
|
1192
|
-
var isHookName = (name) => /^use[A-Z]/.test(name);
|
|
1193
|
-
var isSchemaName = (name) => /[Ss]chema$/.test(name);
|
|
1194
|
-
function lineOf(sourceFile, node) {
|
|
1195
|
-
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
1196
|
-
}
|
|
1197
|
-
function returnsJsx(node) {
|
|
1198
|
-
let found = false;
|
|
1199
|
-
const visit = (child) => {
|
|
1200
|
-
if (found) return;
|
|
1201
|
-
if (ts2.isJsxElement(child) || ts2.isJsxSelfClosingElement(child) || ts2.isJsxFragment(child) || ts2.isJsxOpeningFragment(child)) {
|
|
1202
|
-
found = true;
|
|
1203
|
-
return;
|
|
1204
|
-
}
|
|
1205
|
-
ts2.forEachChild(child, visit);
|
|
1206
|
-
};
|
|
1207
|
-
ts2.forEachChild(node, visit);
|
|
1208
|
-
return found;
|
|
1209
|
-
}
|
|
1210
|
-
function classifyFunction(name, isTsx, hasJsx) {
|
|
1211
|
-
if (isHookName(name)) return "hook";
|
|
1212
|
-
if (isTsx && isPascalCase4(name) && hasJsx) return "component";
|
|
1213
|
-
return "function";
|
|
1214
|
-
}
|
|
1215
|
-
function classifyValue(name, initializer, isTsx) {
|
|
1216
|
-
const isFunctionLike = initializer !== void 0 && (ts2.isArrowFunction(initializer) || ts2.isFunctionExpression(initializer) || ts2.isFunctionDeclaration(initializer));
|
|
1217
|
-
if (isHookName(name)) return "hook";
|
|
1218
|
-
if (isSchemaName(name)) return "schema";
|
|
1219
|
-
if (isTsx && isPascalCase4(name) && (initializer === void 0 || returnsJsx(initializer) || isFunctionLike)) {
|
|
1220
|
-
return "component";
|
|
1221
|
-
}
|
|
1222
|
-
if (isFunctionLike) return "function";
|
|
1223
|
-
return "constant";
|
|
1224
|
-
}
|
|
1225
|
-
function parseModule(file) {
|
|
1226
|
-
const text = readFileSync2(file, "utf8");
|
|
1227
|
-
const isTsx = file.endsWith(".tsx") || file.endsWith(".jsx");
|
|
1228
|
-
const sourceFile = ts2.createSourceFile(file, text, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
|
|
1229
|
-
const imports = [];
|
|
1230
|
-
const exports = [];
|
|
1231
|
-
const addImport = (specifierNode, names, node) => {
|
|
1232
|
-
if (!ts2.isStringLiteral(specifierNode)) return;
|
|
1233
|
-
imports.push({ specifier: specifierNode.text, names, line: lineOf(sourceFile, node) });
|
|
1234
|
-
};
|
|
1235
|
-
for (const statement of sourceFile.statements) {
|
|
1236
|
-
if (ts2.isImportDeclaration(statement)) {
|
|
1237
|
-
const names = [];
|
|
1238
|
-
const bindings = statement.importClause?.namedBindings;
|
|
1239
|
-
if (statement.importClause?.name) names.push(statement.importClause.name.text);
|
|
1240
|
-
if (bindings && ts2.isNamedImports(bindings)) {
|
|
1241
|
-
for (const element of bindings.elements) names.push(element.propertyName?.text ?? element.name.text);
|
|
1242
|
-
}
|
|
1243
|
-
addImport(statement.moduleSpecifier, names, statement);
|
|
1244
|
-
continue;
|
|
1245
|
-
}
|
|
1246
|
-
if (ts2.isExportDeclaration(statement)) {
|
|
1247
|
-
if (statement.moduleSpecifier) {
|
|
1248
|
-
const names = [];
|
|
1249
|
-
if (statement.exportClause && ts2.isNamedExports(statement.exportClause)) {
|
|
1250
|
-
for (const element of statement.exportClause.elements) {
|
|
1251
|
-
names.push(element.propertyName?.text ?? element.name.text);
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
addImport(statement.moduleSpecifier, names, statement);
|
|
1255
|
-
}
|
|
1256
|
-
if (statement.exportClause && ts2.isNamedExports(statement.exportClause)) {
|
|
1257
|
-
for (const element of statement.exportClause.elements) {
|
|
1258
|
-
exports.push({ name: element.name.text, kind: "other", line: lineOf(sourceFile, element) });
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
continue;
|
|
1262
|
-
}
|
|
1263
|
-
const isExported2 = ts2.canHaveModifiers(statement) ? (ts2.getModifiers(statement) ?? []).some((modifier) => modifier.kind === ts2.SyntaxKind.ExportKeyword) : false;
|
|
1264
|
-
if (!isExported2) continue;
|
|
1265
|
-
if (ts2.isFunctionDeclaration(statement) && statement.name) {
|
|
1266
|
-
const name = statement.name.text;
|
|
1267
|
-
exports.push({
|
|
1268
|
-
name,
|
|
1269
|
-
kind: classifyFunction(name, isTsx, returnsJsx(statement)),
|
|
1270
|
-
line: lineOf(sourceFile, statement)
|
|
1271
|
-
});
|
|
1272
|
-
continue;
|
|
1273
|
-
}
|
|
1274
|
-
if (ts2.isVariableStatement(statement)) {
|
|
1275
|
-
for (const declaration of statement.declarationList.declarations) {
|
|
1276
|
-
if (!ts2.isIdentifier(declaration.name)) continue;
|
|
1277
|
-
exports.push({
|
|
1278
|
-
name: declaration.name.text,
|
|
1279
|
-
kind: classifyValue(declaration.name.text, declaration.initializer, isTsx),
|
|
1280
|
-
line: lineOf(sourceFile, declaration)
|
|
1281
|
-
});
|
|
1282
|
-
}
|
|
1283
|
-
continue;
|
|
1284
|
-
}
|
|
1285
|
-
if (ts2.isTypeAliasDeclaration(statement) || ts2.isInterfaceDeclaration(statement)) {
|
|
1286
|
-
exports.push({ name: statement.name.text, kind: "type", line: lineOf(sourceFile, statement) });
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
return { file: path7.resolve(file), imports, exports };
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
// eslint/project/index.ts
|
|
1293
|
-
var MODULE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
1294
|
-
var INDEX_BASENAMES = ["index.ts", "index.tsx", "index.mts", "index.cts", "index.js", "index.jsx"];
|
|
1295
|
-
var REVALIDATE_AFTER_MS = 2e3;
|
|
1296
|
-
var symbolKey = (file, name) => `${file}\0${name}`;
|
|
1297
|
-
function listSourceFiles(dir) {
|
|
1298
|
-
let entries;
|
|
1299
|
-
try {
|
|
1300
|
-
entries = readdirSync2(dir);
|
|
1301
|
-
} catch {
|
|
1302
|
-
return [];
|
|
1303
|
-
}
|
|
1304
|
-
return entries.flatMap((entry) => {
|
|
1305
|
-
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
1306
|
-
const entryPath = path8.join(dir, entry);
|
|
1307
|
-
let stats;
|
|
1308
|
-
try {
|
|
1309
|
-
stats = statSync2(entryPath);
|
|
1310
|
-
} catch {
|
|
1311
|
-
return [];
|
|
1312
|
-
}
|
|
1313
|
-
if (stats.isDirectory()) return listSourceFiles(entryPath);
|
|
1314
|
-
return MODULE_EXTENSIONS.includes(path8.extname(entry)) ? [entryPath] : [];
|
|
1315
|
-
});
|
|
1316
|
-
}
|
|
1317
|
-
function fingerprint(files) {
|
|
1318
|
-
let total = 0;
|
|
1319
|
-
for (const file of files) {
|
|
1320
|
-
try {
|
|
1321
|
-
total += statSync2(file).mtimeMs;
|
|
1322
|
-
} catch {
|
|
1323
|
-
}
|
|
1318
|
+
TSTypeAliasDeclaration(node) {
|
|
1319
|
+
const aliasName = node.id?.name;
|
|
1320
|
+
if (!aliasName?.endsWith("Props")) return;
|
|
1321
|
+
if (node.typeAnnotation?.type !== "TSTypeLiteral") return;
|
|
1322
|
+
for (const member of node.typeAnnotation.members ?? []) {
|
|
1323
|
+
if (member.type !== "TSPropertySignature") continue;
|
|
1324
|
+
const keyName2 = member.key?.type === "Identifier" ? member.key.name : void 0;
|
|
1325
|
+
if (!keyName2) continue;
|
|
1326
|
+
const typeAnn = member.typeAnnotation?.typeAnnotation;
|
|
1327
|
+
if (typeAnn?.type !== "TSUnionType") continue;
|
|
1328
|
+
const allStringLiterals = (typeAnn.types ?? []).every(
|
|
1329
|
+
(t) => t.type === "TSLiteralType" && (t.literal?.type === "StringLiteral" || t.literal?.type === "Literal" && typeof t.literal.value === "string")
|
|
1330
|
+
);
|
|
1331
|
+
if (allStringLiterals && (typeAnn.types?.length ?? 0) >= 2) {
|
|
1332
|
+
for (const variantNames of cvaDefinitions.values()) {
|
|
1333
|
+
if (variantNames.includes(keyName2)) {
|
|
1334
|
+
context.report({
|
|
1335
|
+
node,
|
|
1336
|
+
message: `Variant prop "${keyName2}" duplicates CVA variant values. Use VariantProps<typeof variants> instead of manually writing union types. See docs/styling-guide/rules/component-variant-rule.md`
|
|
1337
|
+
});
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1324
1345
|
}
|
|
1325
|
-
|
|
1346
|
+
};
|
|
1347
|
+
|
|
1348
|
+
// eslint/rules/enforce-barrel-exports.ts
|
|
1349
|
+
import path9 from "path";
|
|
1350
|
+
import fs from "fs";
|
|
1351
|
+
function isPascalCase4(str) {
|
|
1352
|
+
return /^[A-Z][A-Za-z0-9]*$/.test(str);
|
|
1326
1353
|
}
|
|
1327
|
-
function
|
|
1328
|
-
|
|
1329
|
-
if (specifier.startsWith("@/")) {
|
|
1330
|
-
base = path8.resolve(sourceRoot, specifier.slice(2));
|
|
1331
|
-
} else if (specifier.startsWith(".")) {
|
|
1332
|
-
base = path8.resolve(path8.dirname(fromFile), specifier);
|
|
1333
|
-
} else {
|
|
1334
|
-
return void 0;
|
|
1335
|
-
}
|
|
1336
|
-
const candidates = [
|
|
1337
|
-
base,
|
|
1338
|
-
...MODULE_EXTENSIONS.map((extension) => `${base}${extension}`),
|
|
1339
|
-
...INDEX_BASENAMES.map((name) => path8.join(base, name))
|
|
1340
|
-
];
|
|
1341
|
-
for (const candidate of candidates) {
|
|
1342
|
-
try {
|
|
1343
|
-
if (statSync2(candidate).isFile()) return candidate;
|
|
1344
|
-
} catch {
|
|
1345
|
-
}
|
|
1346
|
-
}
|
|
1347
|
-
return void 0;
|
|
1354
|
+
function isKebabCase2(str) {
|
|
1355
|
+
return /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/.test(str);
|
|
1348
1356
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
} catch {
|
|
1357
|
+
var SUPPORT_FOLDERS = /* @__PURE__ */ new Set(["types", "schemas", "hooks", "constants", "utils", "config", "locales"]);
|
|
1358
|
+
var enforceBarrelExportsRule = {
|
|
1359
|
+
meta: {
|
|
1360
|
+
schema: [],
|
|
1361
|
+
type: "problem",
|
|
1362
|
+
docs: {
|
|
1363
|
+
description: "Enforce index.ts barrels only re-export the parent component."
|
|
1357
1364
|
}
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1365
|
+
},
|
|
1366
|
+
create(context) {
|
|
1367
|
+
const filename = context.filename;
|
|
1368
|
+
if (!filename) return {};
|
|
1369
|
+
const baseName = path9.basename(filename);
|
|
1370
|
+
if (baseName !== "index.ts" && baseName !== "index.cts" && baseName !== "index.mts") return {};
|
|
1371
|
+
const dirPath = path9.dirname(filename);
|
|
1372
|
+
const folderName = path9.basename(dirPath);
|
|
1373
|
+
const parentFolderName = path9.basename(path9.dirname(dirPath));
|
|
1374
|
+
if (SUPPORT_FOLDERS.has(folderName)) return {};
|
|
1375
|
+
if (!isPascalCase4(folderName) && !isKebabCase2(folderName)) return {};
|
|
1376
|
+
const matchingTsx = fs.existsSync(path9.join(dirPath, `${folderName}.tsx`)) ? folderName : null;
|
|
1377
|
+
if (!matchingTsx) return {};
|
|
1378
|
+
if (!isPascalCase4(parentFolderName) && !isKebabCase2(parentFolderName)) return {};
|
|
1379
|
+
const reExportedNames = /* @__PURE__ */ new Set();
|
|
1380
|
+
return {
|
|
1381
|
+
ExportNamedDeclaration(node) {
|
|
1382
|
+
if (!node.source) return;
|
|
1383
|
+
for (const spec of node.specifiers) {
|
|
1384
|
+
if (spec.exported.type === "Identifier") {
|
|
1385
|
+
reExportedNames.add(spec.exported.name);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
},
|
|
1389
|
+
"Program:exit"() {
|
|
1390
|
+
if (reExportedNames.size === 0) return;
|
|
1391
|
+
if (!reExportedNames.has(matchingTsx)) {
|
|
1392
|
+
context.report({
|
|
1393
|
+
loc: { line: 1, column: 0 },
|
|
1394
|
+
message: `index.ts in "${folderName}/" must re-export "${matchingTsx}". See docs/code-organization-guide/rules/folder-nesting-rule.md`
|
|
1395
|
+
});
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
const nonParentExports = [...reExportedNames].filter((n) => n !== matchingTsx);
|
|
1399
|
+
if (nonParentExports.length > 0) {
|
|
1400
|
+
context.report({
|
|
1401
|
+
loc: { line: 1, column: 0 },
|
|
1402
|
+
message: `index.ts must not re-export exclusive children: ${nonParentExports.join(", ")}. Only "${matchingTsx}" may be re-exported. See docs/code-organization-guide/rules/folder-nesting-rule.md`
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1371
1405
|
}
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
return { sourceRoot, modules, consumers, symbolConsumers };
|
|
1375
|
-
}
|
|
1376
|
-
var cache;
|
|
1377
|
-
function getProjectIndex(sourceRoot) {
|
|
1378
|
-
const now = Date.now();
|
|
1379
|
-
if (cache?.index.sourceRoot === sourceRoot && now - cache.checkedAt < REVALIDATE_AFTER_MS) {
|
|
1380
|
-
return cache.index;
|
|
1381
|
-
}
|
|
1382
|
-
try {
|
|
1383
|
-
if (!statSync2(sourceRoot).isDirectory()) return void 0;
|
|
1384
|
-
} catch {
|
|
1385
|
-
return void 0;
|
|
1386
|
-
}
|
|
1387
|
-
const files = listSourceFiles(sourceRoot).sort((left, right) => left.localeCompare(right));
|
|
1388
|
-
const currentFingerprint = fingerprint(files);
|
|
1389
|
-
if (cache?.index.sourceRoot === sourceRoot && cache.fingerprint === currentFingerprint) {
|
|
1390
|
-
cache.checkedAt = now;
|
|
1391
|
-
return cache.index;
|
|
1406
|
+
};
|
|
1392
1407
|
}
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1408
|
+
};
|
|
1409
|
+
|
|
1410
|
+
// eslint/rules/component-placement.ts
|
|
1411
|
+
import path11 from "path";
|
|
1397
1412
|
|
|
1398
1413
|
// eslint/project/ccf.ts
|
|
1399
|
-
import
|
|
1414
|
+
import path10 from "path";
|
|
1400
1415
|
var SUPPORT_FOLDERS2 = /* @__PURE__ */ new Set(["hooks", "types", "schemas", "constants", "utils"]);
|
|
1401
1416
|
function segmentsOf(file, sourceRoot) {
|
|
1402
|
-
const relative =
|
|
1403
|
-
return relative.startsWith("..") ? [] : relative.split(
|
|
1417
|
+
const relative = path10.relative(sourceRoot, file);
|
|
1418
|
+
return relative.startsWith("..") ? [] : relative.split(path10.sep);
|
|
1404
1419
|
}
|
|
1405
1420
|
function folderSegmentsOf(file, sourceRoot) {
|
|
1406
1421
|
return segmentsOf(file, sourceRoot).slice(0, -1);
|
|
@@ -1479,7 +1494,7 @@ function resolveSupportPlacement(supportFile, supportFolder, index) {
|
|
|
1479
1494
|
}
|
|
1480
1495
|
function describeConsumers(consumers, sourceRoot) {
|
|
1481
1496
|
const shown = 3;
|
|
1482
|
-
const names = consumers.map((consumer) =>
|
|
1497
|
+
const names = consumers.map((consumer) => path10.relative(path10.dirname(sourceRoot), consumer).split(path10.sep).join("/")).sort((left, right) => left.localeCompare(right));
|
|
1483
1498
|
if (names.length <= shown) return names.join(", ");
|
|
1484
1499
|
return `${names.slice(0, shown).join(", ")} and ${String(names.length - shown)} more`;
|
|
1485
1500
|
}
|
|
@@ -1505,7 +1520,7 @@ var componentPlacementRule = {
|
|
|
1505
1520
|
const sourceRoot = sourceRootOf(context);
|
|
1506
1521
|
const index = getProjectIndex(sourceRoot);
|
|
1507
1522
|
if (!index) return {};
|
|
1508
|
-
const componentFile =
|
|
1523
|
+
const componentFile = path11.resolve(filename);
|
|
1509
1524
|
const segments = segmentsOf(componentFile, sourceRoot);
|
|
1510
1525
|
if (segments.length === 0) return {};
|
|
1511
1526
|
if (isUnderApp(segments) || isConfigModule(segments)) return {};
|
|
@@ -1538,7 +1553,7 @@ var componentPlacementRule = {
|
|
|
1538
1553
|
};
|
|
1539
1554
|
|
|
1540
1555
|
// eslint/rules/support-file-placement.ts
|
|
1541
|
-
import
|
|
1556
|
+
import path12 from "path";
|
|
1542
1557
|
var CONFIG_OWNED_FOLDERS = /* @__PURE__ */ new Set(["types", "constants"]);
|
|
1543
1558
|
var REASON_TEXT2 = {
|
|
1544
1559
|
"app-consumer": "a file under src/app/ imports it, so it belongs to the app-wide support folder",
|
|
@@ -1558,7 +1573,7 @@ var supportFilePlacementRule = {
|
|
|
1558
1573
|
},
|
|
1559
1574
|
create(context) {
|
|
1560
1575
|
const sourceRoot = sourceRootOf(context);
|
|
1561
|
-
const supportFile =
|
|
1576
|
+
const supportFile = path12.resolve(context.filename);
|
|
1562
1577
|
const currentFolder = folderSegmentsOf(supportFile, sourceRoot);
|
|
1563
1578
|
const supportFolder = currentFolder[currentFolder.length - 1];
|
|
1564
1579
|
if (supportFolder === void 0 || !SUPPORT_FOLDERS2.has(supportFolder)) return {};
|
|
@@ -1583,11 +1598,12 @@ var supportFilePlacementRule = {
|
|
|
1583
1598
|
|
|
1584
1599
|
// eslint/rules/application-structure.ts
|
|
1585
1600
|
import fs2 from "fs";
|
|
1586
|
-
import
|
|
1601
|
+
import path13 from "path";
|
|
1587
1602
|
var MODULE_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
1588
1603
|
var ROUTING_FILES = /* @__PURE__ */ new Set([
|
|
1589
1604
|
"default",
|
|
1590
1605
|
"error",
|
|
1606
|
+
"global-error",
|
|
1591
1607
|
"instrumentation",
|
|
1592
1608
|
"layout",
|
|
1593
1609
|
"loading",
|
|
@@ -1595,7 +1611,15 @@ var ROUTING_FILES = /* @__PURE__ */ new Set([
|
|
|
1595
1611
|
"not-found",
|
|
1596
1612
|
"page",
|
|
1597
1613
|
"route",
|
|
1598
|
-
"template"
|
|
1614
|
+
"template",
|
|
1615
|
+
// File conventions Next.js requires to keep their exact names in src/app/
|
|
1616
|
+
"apple-icon",
|
|
1617
|
+
"icon",
|
|
1618
|
+
"manifest",
|
|
1619
|
+
"opengraph-image",
|
|
1620
|
+
"robots",
|
|
1621
|
+
"sitemap",
|
|
1622
|
+
"twitter-image"
|
|
1599
1623
|
]);
|
|
1600
1624
|
var EXPECTED_SUPPORT_FOLDER = {
|
|
1601
1625
|
hook: "hooks",
|
|
@@ -1612,7 +1636,7 @@ function report2(context, message) {
|
|
|
1612
1636
|
};
|
|
1613
1637
|
}
|
|
1614
1638
|
function isCodeFile(filename) {
|
|
1615
|
-
return MODULE_EXTENSIONS2.has(
|
|
1639
|
+
return MODULE_EXTENSIONS2.has(path13.extname(filename));
|
|
1616
1640
|
}
|
|
1617
1641
|
function isRootSupportFolder(folder) {
|
|
1618
1642
|
return SUPPORT_FOLDERS2.has(folder);
|
|
@@ -1633,7 +1657,7 @@ function expectedSupportFolder(kinds) {
|
|
|
1633
1657
|
function configModuleRoot(filename, sourceRoot) {
|
|
1634
1658
|
const segments = segmentsOf(filename, sourceRoot);
|
|
1635
1659
|
if (segments[0] !== "config" || segments.length < 3) return void 0;
|
|
1636
|
-
return
|
|
1660
|
+
return path13.join(sourceRoot, "config", segments[1] ?? "");
|
|
1637
1661
|
}
|
|
1638
1662
|
function componentFolderStart(segments) {
|
|
1639
1663
|
if (segments[0] === "features") return 2;
|
|
@@ -1646,12 +1670,12 @@ function componentFolderViolation(segments, sourceRoot) {
|
|
|
1646
1670
|
for (let depth = segments.length - 2; depth >= start; depth -= 1) {
|
|
1647
1671
|
const folder = segments[depth];
|
|
1648
1672
|
if (!folder || SUPPORT_FOLDERS2.has(folder)) continue;
|
|
1649
|
-
const folderPath =
|
|
1673
|
+
const folderPath = path13.join(sourceRoot, ...segments.slice(0, depth + 1));
|
|
1650
1674
|
const label = `src/${segments.slice(0, depth + 1).join("/")}/`;
|
|
1651
|
-
if (!fs2.existsSync(
|
|
1675
|
+
if (!fs2.existsSync(path13.join(folderPath, `${folder}.tsx`))) {
|
|
1652
1676
|
return `A folder that is not a support folder must be a component folder; add "${folder}.tsx" to ${label} or move its files into a support folder.`;
|
|
1653
1677
|
}
|
|
1654
|
-
if (!fs2.existsSync(
|
|
1678
|
+
if (!fs2.existsSync(path13.join(folderPath, "index.ts"))) {
|
|
1655
1679
|
return `A component folder must have an index.ts that named-re-exports its component; add index.ts to ${label}.`;
|
|
1656
1680
|
}
|
|
1657
1681
|
}
|
|
@@ -1666,7 +1690,7 @@ var applicationStructureRule = {
|
|
|
1666
1690
|
}
|
|
1667
1691
|
},
|
|
1668
1692
|
create(context) {
|
|
1669
|
-
const filename =
|
|
1693
|
+
const filename = path13.resolve(context.filename);
|
|
1670
1694
|
const sourceRoot = sourceRootOf(context);
|
|
1671
1695
|
const segments = segmentsOf(filename, sourceRoot);
|
|
1672
1696
|
if (segments.length === 0) return {};
|
|
@@ -1697,42 +1721,43 @@ var applicationStructureRule = {
|
|
|
1697
1721
|
);
|
|
1698
1722
|
}
|
|
1699
1723
|
const moduleRoot = configModuleRoot(filename, sourceRoot);
|
|
1700
|
-
if (moduleRoot && !fs2.existsSync(
|
|
1724
|
+
if (moduleRoot && !fs2.existsSync(path13.join(moduleRoot, "index.ts"))) {
|
|
1701
1725
|
return report2(
|
|
1702
1726
|
context,
|
|
1703
|
-
`Add src/config/${
|
|
1727
|
+
`Add src/config/${path13.basename(moduleRoot)}/index.ts as the configuration module entry point.`
|
|
1704
1728
|
);
|
|
1705
1729
|
}
|
|
1706
|
-
if (moduleRoot && segments.length === 3 &&
|
|
1730
|
+
if (moduleRoot && segments.length === 3 && path13.basename(filename) !== "index.ts") {
|
|
1707
1731
|
const kinds2 = exportedKinds(filename);
|
|
1708
1732
|
const expected2 = expectedSupportFolder(kinds2);
|
|
1709
1733
|
if (expected2 !== void 0) {
|
|
1710
1734
|
return report2(
|
|
1711
1735
|
context,
|
|
1712
|
-
`Move this configuration support file into src/config/${
|
|
1736
|
+
`Move this configuration support file into src/config/${path13.basename(moduleRoot)}/${expected2}/.`
|
|
1713
1737
|
);
|
|
1714
1738
|
}
|
|
1715
1739
|
}
|
|
1716
1740
|
}
|
|
1717
1741
|
if (topLevel === "app" && isCodeFile(filename)) {
|
|
1718
|
-
const basename =
|
|
1719
|
-
const currentFolder2 =
|
|
1742
|
+
const basename = path13.basename(filename, path13.extname(filename));
|
|
1743
|
+
const currentFolder2 = path13.basename(path13.dirname(filename));
|
|
1720
1744
|
if (SUPPORT_FOLDERS2.has(currentFolder2)) {
|
|
1721
1745
|
return report2(
|
|
1722
1746
|
context,
|
|
1723
1747
|
"src/app/ may contain routing files and framework assets, but ordinary components and support files must live outside src/app/."
|
|
1724
1748
|
);
|
|
1725
1749
|
}
|
|
1726
|
-
if (!ROUTING_FILES.has(basename) &&
|
|
1750
|
+
if (!ROUTING_FILES.has(basename) && path13.extname(filename) !== ".css") {
|
|
1727
1751
|
return report2(
|
|
1728
1752
|
context,
|
|
1729
1753
|
"src/app/ may contain routing files and framework assets, but ordinary components and support files must live outside src/app/."
|
|
1730
1754
|
);
|
|
1731
1755
|
}
|
|
1756
|
+
if (ROUTING_FILES.has(basename) || path13.extname(filename) === ".css") return {};
|
|
1732
1757
|
}
|
|
1733
|
-
const currentFolder =
|
|
1758
|
+
const currentFolder = path13.basename(path13.dirname(filename));
|
|
1734
1759
|
const kinds = exportedKinds(filename);
|
|
1735
|
-
const isConfigModuleRoot = topLevel === "config" && segments.length === 3 &&
|
|
1760
|
+
const isConfigModuleRoot = topLevel === "config" && segments.length === 3 && path13.basename(filename) === "index.ts";
|
|
1736
1761
|
if (isConfigModuleRoot) return {};
|
|
1737
1762
|
if (!SUPPORT_FOLDERS2.has(currentFolder)) {
|
|
1738
1763
|
const expected2 = expectedSupportFolder(kinds);
|
|
@@ -1749,7 +1774,7 @@ var applicationStructureRule = {
|
|
|
1749
1774
|
if (kinds.has("component")) {
|
|
1750
1775
|
return report2(
|
|
1751
1776
|
context,
|
|
1752
|
-
`A support folder must not contain a component; move ${
|
|
1777
|
+
`A support folder must not contain a component; move ${path13.basename(filename)} beside ${currentFolder}/.`
|
|
1753
1778
|
);
|
|
1754
1779
|
}
|
|
1755
1780
|
const expected = expectedSupportFolder(kinds);
|
|
@@ -1766,7 +1791,7 @@ var applicationStructureRule = {
|
|
|
1766
1791
|
};
|
|
1767
1792
|
|
|
1768
1793
|
// eslint/rules/named-exports.ts
|
|
1769
|
-
import
|
|
1794
|
+
import path14 from "path";
|
|
1770
1795
|
var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
|
|
1771
1796
|
// App Router routing files
|
|
1772
1797
|
"default",
|
|
@@ -1788,9 +1813,9 @@ var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
|
|
|
1788
1813
|
"twitter-image"
|
|
1789
1814
|
]);
|
|
1790
1815
|
function isFrameworkDefaultExportFile(filename) {
|
|
1791
|
-
const normalized = filename.replaceAll(
|
|
1816
|
+
const normalized = filename.replaceAll(path14.sep, "/");
|
|
1792
1817
|
if (!normalized.includes("/src/app/")) return false;
|
|
1793
|
-
const basename =
|
|
1818
|
+
const basename = path14.basename(filename, path14.extname(filename));
|
|
1794
1819
|
return FRAMEWORK_DEFAULT_EXPORT_FILES.has(basename);
|
|
1795
1820
|
}
|
|
1796
1821
|
var namedExportsRule = {
|
|
@@ -1815,7 +1840,7 @@ var namedExportsRule = {
|
|
|
1815
1840
|
};
|
|
1816
1841
|
|
|
1817
1842
|
// eslint/rules/data-testid-case.ts
|
|
1818
|
-
import
|
|
1843
|
+
import path15 from "path";
|
|
1819
1844
|
var NEXT_ROUTING_FILES2 = /* @__PURE__ */ new Set([
|
|
1820
1845
|
"page",
|
|
1821
1846
|
"layout",
|
|
@@ -1839,9 +1864,9 @@ var dataTestIdCaseRule = {
|
|
|
1839
1864
|
}
|
|
1840
1865
|
},
|
|
1841
1866
|
create(context) {
|
|
1842
|
-
const filename =
|
|
1867
|
+
const filename = path15.resolve(context.filename);
|
|
1843
1868
|
if (!filename.endsWith(".tsx")) return {};
|
|
1844
|
-
const base =
|
|
1869
|
+
const base = path15.basename(filename, path15.extname(filename));
|
|
1845
1870
|
if (NEXT_ROUTING_FILES2.has(base)) return {};
|
|
1846
1871
|
const text = context.sourceCode.text;
|
|
1847
1872
|
const components = parseComponentInfo(text, filename);
|
|
@@ -1883,7 +1908,7 @@ function toKebabCase(value) {
|
|
|
1883
1908
|
|
|
1884
1909
|
// eslint/rules/support-folder-shape.ts
|
|
1885
1910
|
import fs3 from "fs";
|
|
1886
|
-
import
|
|
1911
|
+
import path16 from "path";
|
|
1887
1912
|
var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
|
|
1888
1913
|
var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
|
|
1889
1914
|
var supportFolderShapeRule = {
|
|
@@ -1895,12 +1920,12 @@ var supportFolderShapeRule = {
|
|
|
1895
1920
|
}
|
|
1896
1921
|
},
|
|
1897
1922
|
create(context) {
|
|
1898
|
-
const filename =
|
|
1899
|
-
const baseName =
|
|
1923
|
+
const filename = path16.resolve(context.filename);
|
|
1924
|
+
const baseName = path16.basename(filename);
|
|
1900
1925
|
if (!INDEX_NAMES.has(baseName)) return {};
|
|
1901
|
-
const folder =
|
|
1926
|
+
const folder = path16.basename(path16.dirname(filename));
|
|
1902
1927
|
if (!SUPPORT_FOLDERS3.has(folder)) return {};
|
|
1903
|
-
const directory =
|
|
1928
|
+
const directory = path16.dirname(filename);
|
|
1904
1929
|
let entries;
|
|
1905
1930
|
try {
|
|
1906
1931
|
entries = fs3.readdirSync(directory);
|
|
@@ -1918,7 +1943,7 @@ var supportFolderShapeRule = {
|
|
|
1918
1943
|
const exportPattern = /export\s+(?:\{[^}]*\}|\*[^;]*)\s+from\s+["'](?<specifier>\.[^"']+)["']/g;
|
|
1919
1944
|
for (const match of source.matchAll(exportPattern)) {
|
|
1920
1945
|
const specifier = match.groups?.specifier;
|
|
1921
|
-
if (specifier) exportedFiles.add(
|
|
1946
|
+
if (specifier) exportedFiles.add(path16.basename(specifier));
|
|
1922
1947
|
}
|
|
1923
1948
|
const missing = siblingModules.filter((entry) => {
|
|
1924
1949
|
const stem = entry.replace(/\.(?:[cm]?tsx?|jsx?)$/, "");
|
|
@@ -1935,7 +1960,7 @@ var supportFolderShapeRule = {
|
|
|
1935
1960
|
};
|
|
1936
1961
|
|
|
1937
1962
|
// eslint/rules/import-through-index.ts
|
|
1938
|
-
import
|
|
1963
|
+
import path17 from "path";
|
|
1939
1964
|
var importThroughIndexRule = {
|
|
1940
1965
|
meta: {
|
|
1941
1966
|
schema: [],
|
|
@@ -1945,7 +1970,7 @@ var importThroughIndexRule = {
|
|
|
1945
1970
|
}
|
|
1946
1971
|
},
|
|
1947
1972
|
create(context) {
|
|
1948
|
-
const filename =
|
|
1973
|
+
const filename = path17.resolve(context.filename);
|
|
1949
1974
|
const sourceRoot = sourceRootOf2(context, filename);
|
|
1950
1975
|
return {
|
|
1951
1976
|
Program(node) {
|
|
@@ -1957,7 +1982,7 @@ var importThroughIndexRule = {
|
|
|
1957
1982
|
(segment) => ["constants", "types", "schemas"].includes(segment)
|
|
1958
1983
|
);
|
|
1959
1984
|
const supportFolder = supportFolderIndex >= 0 ? targetSegments[supportFolderIndex] : void 0;
|
|
1960
|
-
if (!supportFolder ||
|
|
1985
|
+
if (!supportFolder || path17.basename(target).startsWith("index.")) continue;
|
|
1961
1986
|
const folderIndex = targetSegments.slice(0, supportFolderIndex + 1);
|
|
1962
1987
|
const expected = `@/${folderIndex.join("/")}`;
|
|
1963
1988
|
context.report({
|
|
@@ -1979,14 +2004,14 @@ function importSpecifiers(source) {
|
|
|
1979
2004
|
return specifiers;
|
|
1980
2005
|
}
|
|
1981
2006
|
function sourceRootOf2(context, filename) {
|
|
1982
|
-
const marker = `${
|
|
2007
|
+
const marker = `${path17.sep}src${path17.sep}`;
|
|
1983
2008
|
const srcIndex = filename.lastIndexOf(marker);
|
|
1984
2009
|
if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
|
|
1985
|
-
return
|
|
2010
|
+
return path17.resolve(context.cwd ?? process.cwd(), "src");
|
|
1986
2011
|
}
|
|
1987
2012
|
|
|
1988
2013
|
// eslint/rules/util-file-name.ts
|
|
1989
|
-
import
|
|
2014
|
+
import path18 from "path";
|
|
1990
2015
|
function toKebabCase2(value) {
|
|
1991
2016
|
return value.replace(/(?<lower>[a-z0-9])(?<upper>[A-Z])/g, "$<lower>-$<upper>").replace(/(?<first>[A-Z])(?<rest>[A-Z][a-z])/g, "$<first>-$<rest>").toLowerCase();
|
|
1992
2017
|
}
|
|
@@ -1999,7 +2024,7 @@ var utilFileNameRule = {
|
|
|
1999
2024
|
}
|
|
2000
2025
|
},
|
|
2001
2026
|
create(context) {
|
|
2002
|
-
const filename =
|
|
2027
|
+
const filename = path18.resolve(context.filename);
|
|
2003
2028
|
const segments = filename.replace(/\\/g, "/").split("/");
|
|
2004
2029
|
if (!segments.includes("utils")) return {};
|
|
2005
2030
|
let module;
|
|
@@ -2013,13 +2038,13 @@ var utilFileNameRule = {
|
|
|
2013
2038
|
const functionName = functions[0]?.name;
|
|
2014
2039
|
if (!functionName) return {};
|
|
2015
2040
|
const expected = toKebabCase2(functionName);
|
|
2016
|
-
const actual =
|
|
2041
|
+
const actual = path18.basename(filename, path18.extname(filename));
|
|
2017
2042
|
if (!expected || actual === expected) return {};
|
|
2018
2043
|
return {
|
|
2019
2044
|
Program(node) {
|
|
2020
2045
|
context.report({
|
|
2021
2046
|
node,
|
|
2022
|
-
message: `A utility file exporting ${functionName} must be named ${expected}.${
|
|
2047
|
+
message: `A utility file exporting ${functionName} must be named ${expected}.${path18.extname(filename).slice(1)}.`
|
|
2023
2048
|
});
|
|
2024
2049
|
}
|
|
2025
2050
|
};
|
|
@@ -2027,7 +2052,7 @@ var utilFileNameRule = {
|
|
|
2027
2052
|
};
|
|
2028
2053
|
|
|
2029
2054
|
// eslint/rules/no-util-barrel.ts
|
|
2030
|
-
import
|
|
2055
|
+
import path19 from "path";
|
|
2031
2056
|
var noUtilBarrelRule = {
|
|
2032
2057
|
meta: {
|
|
2033
2058
|
schema: [],
|
|
@@ -2037,7 +2062,7 @@ var noUtilBarrelRule = {
|
|
|
2037
2062
|
}
|
|
2038
2063
|
},
|
|
2039
2064
|
create(context) {
|
|
2040
|
-
const filename =
|
|
2065
|
+
const filename = path19.resolve(context.filename);
|
|
2041
2066
|
const sourceRoot = sourceRootOf3(context, filename);
|
|
2042
2067
|
return {
|
|
2043
2068
|
Program(node) {
|
|
@@ -2046,7 +2071,7 @@ var noUtilBarrelRule = {
|
|
|
2046
2071
|
if (!target) continue;
|
|
2047
2072
|
const segments = target.replace(/\\/g, "/").split("/");
|
|
2048
2073
|
const utilsIndex = segments.lastIndexOf("utils");
|
|
2049
|
-
if (utilsIndex < 0 || !
|
|
2074
|
+
if (utilsIndex < 0 || !path19.basename(target).startsWith("index.")) continue;
|
|
2050
2075
|
context.report({
|
|
2051
2076
|
node,
|
|
2052
2077
|
message: `Import utilities directly instead of through "${specifier}". See docs/code-organization-guide/rules/utilities-rule.md`
|
|
@@ -2066,10 +2091,10 @@ function importSpecifiers2(source) {
|
|
|
2066
2091
|
return specifiers;
|
|
2067
2092
|
}
|
|
2068
2093
|
function sourceRootOf3(context, filename) {
|
|
2069
|
-
const marker = `${
|
|
2094
|
+
const marker = `${path19.sep}src${path19.sep}`;
|
|
2070
2095
|
const srcIndex = filename.lastIndexOf(marker);
|
|
2071
2096
|
if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
|
|
2072
|
-
return
|
|
2097
|
+
return path19.resolve(context.cwd ?? process.cwd(), "src");
|
|
2073
2098
|
}
|
|
2074
2099
|
|
|
2075
2100
|
// eslint/rules/jsx-hygiene.ts
|
|
@@ -2445,12 +2470,12 @@ var cvaBooleanVariantsRule = {
|
|
|
2445
2470
|
};
|
|
2446
2471
|
|
|
2447
2472
|
// eslint/rules/cross-feature-import.ts
|
|
2448
|
-
import
|
|
2473
|
+
import path20 from "path";
|
|
2449
2474
|
var FEATURES_SEGMENT = "features";
|
|
2450
2475
|
function featureNameOf(resolvedPath, sourceRoot) {
|
|
2451
|
-
const relative =
|
|
2476
|
+
const relative = path20.relative(sourceRoot, resolvedPath);
|
|
2452
2477
|
if (relative.startsWith("..")) return void 0;
|
|
2453
|
-
const segments = relative.split(
|
|
2478
|
+
const segments = relative.split(path20.sep);
|
|
2454
2479
|
if (segments[0] !== FEATURES_SEGMENT || segments.length < 2) return void 0;
|
|
2455
2480
|
return segments[1];
|
|
2456
2481
|
}
|
|
@@ -2466,9 +2491,9 @@ var crossFeatureImportRule = {
|
|
|
2466
2491
|
const filename = context.filename;
|
|
2467
2492
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
2468
2493
|
const sourceRoot = sourceRootOf(context);
|
|
2469
|
-
const fileRelative =
|
|
2494
|
+
const fileRelative = path20.relative(sourceRoot, filename);
|
|
2470
2495
|
if (fileRelative.startsWith("..")) return {};
|
|
2471
|
-
const fileSegments = fileRelative.split(
|
|
2496
|
+
const fileSegments = fileRelative.split(path20.sep);
|
|
2472
2497
|
const isInCompositions = fileSegments[0] === "compositions";
|
|
2473
2498
|
const isInApp = fileSegments[0] === "app";
|
|
2474
2499
|
const isConfig = fileSegments[0] === "config";
|
|
@@ -2482,9 +2507,9 @@ var crossFeatureImportRule = {
|
|
|
2482
2507
|
if (typeof source.value !== "string") return;
|
|
2483
2508
|
let resolved;
|
|
2484
2509
|
if (source.value.startsWith("@/")) {
|
|
2485
|
-
resolved =
|
|
2510
|
+
resolved = path20.resolve(sourceRoot, source.value.slice(2));
|
|
2486
2511
|
} else if (source.value.startsWith(".")) {
|
|
2487
|
-
resolved =
|
|
2512
|
+
resolved = path20.resolve(path20.dirname(filename), source.value);
|
|
2488
2513
|
}
|
|
2489
2514
|
if (!resolved) return;
|
|
2490
2515
|
const feature = featureNameOf(resolved, sourceRoot);
|
|
@@ -2503,7 +2528,7 @@ var crossFeatureImportRule = {
|
|
|
2503
2528
|
};
|
|
2504
2529
|
|
|
2505
2530
|
// eslint/rules/pure-function-extract.ts
|
|
2506
|
-
import
|
|
2531
|
+
import path21 from "path";
|
|
2507
2532
|
function isComponentLikeName(name) {
|
|
2508
2533
|
return /^[A-Z]/.test(name);
|
|
2509
2534
|
}
|
|
@@ -2532,9 +2557,9 @@ var pureFunctionExtractRule = {
|
|
|
2532
2557
|
const filename = context.filename;
|
|
2533
2558
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
2534
2559
|
const sourceRoot = sourceRootOf(context);
|
|
2535
|
-
const relative =
|
|
2560
|
+
const relative = path21.relative(sourceRoot, filename);
|
|
2536
2561
|
if (relative.startsWith("..")) return {};
|
|
2537
|
-
const segments = relative.split(
|
|
2562
|
+
const segments = relative.split(path21.sep);
|
|
2538
2563
|
if (segments[0] === "utils") return {};
|
|
2539
2564
|
if (segments[0] === "app") return {};
|
|
2540
2565
|
const supportFolders = /* @__PURE__ */ new Set(["hooks", "types", "schemas", "constants", "utils"]);
|
|
@@ -2574,7 +2599,7 @@ var pureFunctionExtractRule = {
|
|
|
2574
2599
|
};
|
|
2575
2600
|
|
|
2576
2601
|
// eslint/rules/hook-complexity.ts
|
|
2577
|
-
import
|
|
2602
|
+
import path22 from "path";
|
|
2578
2603
|
import ts4 from "typescript";
|
|
2579
2604
|
var REACT_HOOKS = /* @__PURE__ */ new Set([
|
|
2580
2605
|
"useState",
|
|
@@ -2627,9 +2652,9 @@ var hookComplexityRule = {
|
|
|
2627
2652
|
create(context) {
|
|
2628
2653
|
const filename = context.filename;
|
|
2629
2654
|
const sourceRoot = sourceRootOf(context);
|
|
2630
|
-
const relative =
|
|
2655
|
+
const relative = path22.relative(sourceRoot, filename);
|
|
2631
2656
|
if (relative.startsWith("..")) return {};
|
|
2632
|
-
const segments = relative.split(
|
|
2657
|
+
const segments = relative.split(path22.sep);
|
|
2633
2658
|
const sourceText = context.sourceCode.text;
|
|
2634
2659
|
function checkHook(node, name, body, exported) {
|
|
2635
2660
|
if (!exported) return;
|
|
@@ -2671,9 +2696,9 @@ var hookComplexityRule = {
|
|
|
2671
2696
|
};
|
|
2672
2697
|
|
|
2673
2698
|
// eslint/rules/locale-dotted-path.ts
|
|
2674
|
-
import
|
|
2699
|
+
import path23 from "path";
|
|
2675
2700
|
function isInLocalesDir(filename) {
|
|
2676
|
-
const segments =
|
|
2701
|
+
const segments = path23.resolve(filename).split(path23.sep);
|
|
2677
2702
|
const srcIdx = segments.lastIndexOf("src");
|
|
2678
2703
|
return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
|
|
2679
2704
|
}
|
|
@@ -2722,9 +2747,9 @@ var localeDottedPathRule = {
|
|
|
2722
2747
|
};
|
|
2723
2748
|
|
|
2724
2749
|
// eslint/rules/locales-location.ts
|
|
2725
|
-
import
|
|
2750
|
+
import path24 from "path";
|
|
2726
2751
|
function isLocalesFile(filename) {
|
|
2727
|
-
const segments =
|
|
2752
|
+
const segments = path24.resolve(filename).split(path24.sep);
|
|
2728
2753
|
const srcIdx = segments.lastIndexOf("src");
|
|
2729
2754
|
return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
|
|
2730
2755
|
}
|
|
@@ -2743,7 +2768,7 @@ var localesLocationRule = {
|
|
|
2743
2768
|
create(context) {
|
|
2744
2769
|
if (isLocalesFile(context.filename)) return {};
|
|
2745
2770
|
const filename = context.filename;
|
|
2746
|
-
const segments =
|
|
2771
|
+
const segments = path24.resolve(filename).split(path24.sep);
|
|
2747
2772
|
const srcIdx = segments.lastIndexOf("src");
|
|
2748
2773
|
if (srcIdx === -1) return {};
|
|
2749
2774
|
const folder = segments[srcIdx + 1];
|
|
@@ -2765,7 +2790,7 @@ var localesLocationRule = {
|
|
|
2765
2790
|
};
|
|
2766
2791
|
|
|
2767
2792
|
// eslint/rules/hook-extraction.ts
|
|
2768
|
-
import
|
|
2793
|
+
import path25 from "path";
|
|
2769
2794
|
var hookExtractionRule = {
|
|
2770
2795
|
meta: {
|
|
2771
2796
|
schema: [],
|
|
@@ -2776,7 +2801,7 @@ var hookExtractionRule = {
|
|
|
2776
2801
|
},
|
|
2777
2802
|
create(context) {
|
|
2778
2803
|
const sourceRoot = sourceRootOf(context);
|
|
2779
|
-
const file =
|
|
2804
|
+
const file = path25.resolve(context.filename);
|
|
2780
2805
|
const segments = segmentsOf(file, sourceRoot);
|
|
2781
2806
|
if (segments.length === 0) return {};
|
|
2782
2807
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -2802,7 +2827,7 @@ var hookExtractionRule = {
|
|
|
2802
2827
|
};
|
|
2803
2828
|
|
|
2804
2829
|
// eslint/rules/value-extraction.ts
|
|
2805
|
-
import
|
|
2830
|
+
import path26 from "path";
|
|
2806
2831
|
var valueExtractionRule = {
|
|
2807
2832
|
meta: {
|
|
2808
2833
|
schema: [],
|
|
@@ -2813,7 +2838,7 @@ var valueExtractionRule = {
|
|
|
2813
2838
|
},
|
|
2814
2839
|
create(context) {
|
|
2815
2840
|
const sourceRoot = sourceRootOf(context);
|
|
2816
|
-
const file =
|
|
2841
|
+
const file = path26.resolve(context.filename);
|
|
2817
2842
|
const segments = segmentsOf(file, sourceRoot);
|
|
2818
2843
|
if (segments.length === 0 || segments[0] !== "app") return {};
|
|
2819
2844
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -2834,7 +2859,7 @@ var valueExtractionRule = {
|
|
|
2834
2859
|
};
|
|
2835
2860
|
|
|
2836
2861
|
// eslint/rules/config-extraction.ts
|
|
2837
|
-
import
|
|
2862
|
+
import path27 from "path";
|
|
2838
2863
|
var configExtractionRule = {
|
|
2839
2864
|
meta: {
|
|
2840
2865
|
schema: [],
|
|
@@ -2845,7 +2870,7 @@ var configExtractionRule = {
|
|
|
2845
2870
|
},
|
|
2846
2871
|
create(context) {
|
|
2847
2872
|
const sourceRoot = sourceRootOf(context);
|
|
2848
|
-
const file =
|
|
2873
|
+
const file = path27.resolve(context.filename);
|
|
2849
2874
|
const segments = segmentsOf(file, sourceRoot);
|
|
2850
2875
|
if (segments.length < 3 || segments[0] !== "config") return {};
|
|
2851
2876
|
if (SUPPORT_FOLDERS2.has(segments[2] ?? "")) return {};
|
|
@@ -2883,7 +2908,7 @@ var configExtractionRule = {
|
|
|
2883
2908
|
};
|
|
2884
2909
|
|
|
2885
2910
|
// eslint/rules/component-nesting.ts
|
|
2886
|
-
import
|
|
2911
|
+
import path28 from "path";
|
|
2887
2912
|
var componentNestingRule = {
|
|
2888
2913
|
meta: {
|
|
2889
2914
|
schema: [],
|
|
@@ -2894,7 +2919,7 @@ var componentNestingRule = {
|
|
|
2894
2919
|
},
|
|
2895
2920
|
create(context) {
|
|
2896
2921
|
const sourceRoot = sourceRootOf(context);
|
|
2897
|
-
const file =
|
|
2922
|
+
const file = path28.resolve(context.filename);
|
|
2898
2923
|
const segments = segmentsOf(file, sourceRoot);
|
|
2899
2924
|
if (segments.length !== 4 || segments[0] !== "features") return {};
|
|
2900
2925
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -2927,7 +2952,7 @@ var componentNestingRule = {
|
|
|
2927
2952
|
};
|
|
2928
2953
|
|
|
2929
2954
|
// eslint/rules/stay-flat.ts
|
|
2930
|
-
import
|
|
2955
|
+
import path29 from "path";
|
|
2931
2956
|
var stayFlatRule = {
|
|
2932
2957
|
meta: {
|
|
2933
2958
|
schema: [],
|
|
@@ -2938,7 +2963,7 @@ var stayFlatRule = {
|
|
|
2938
2963
|
},
|
|
2939
2964
|
create(context) {
|
|
2940
2965
|
const sourceRoot = sourceRootOf(context);
|
|
2941
|
-
const file =
|
|
2966
|
+
const file = path29.resolve(context.filename);
|
|
2942
2967
|
const segments = segmentsOf(file, sourceRoot);
|
|
2943
2968
|
if (segments.length !== 3 || segments[0] !== "features") return {};
|
|
2944
2969
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -2978,7 +3003,7 @@ var stayFlatRule = {
|
|
|
2978
3003
|
};
|
|
2979
3004
|
|
|
2980
3005
|
// eslint/rules/type-extraction.ts
|
|
2981
|
-
import
|
|
3006
|
+
import path30 from "path";
|
|
2982
3007
|
var typeExtractionRule = {
|
|
2983
3008
|
meta: {
|
|
2984
3009
|
schema: [],
|
|
@@ -2989,7 +3014,7 @@ var typeExtractionRule = {
|
|
|
2989
3014
|
},
|
|
2990
3015
|
create(context) {
|
|
2991
3016
|
const sourceRoot = sourceRootOf(context);
|
|
2992
|
-
const file =
|
|
3017
|
+
const file = path30.resolve(context.filename);
|
|
2993
3018
|
const segments = segmentsOf(file, sourceRoot);
|
|
2994
3019
|
if (segments.length === 0) return {};
|
|
2995
3020
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -3035,7 +3060,7 @@ var typeExtractionRule = {
|
|
|
3035
3060
|
};
|
|
3036
3061
|
|
|
3037
3062
|
// eslint/rules/locale-placement.ts
|
|
3038
|
-
import
|
|
3063
|
+
import path31 from "path";
|
|
3039
3064
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3040
3065
|
import ts5 from "typescript";
|
|
3041
3066
|
var LOCALE_ACCESS = /\blocales\.(?<key>[A-Za-z_$][\w$]*)/g;
|
|
@@ -3083,7 +3108,7 @@ var localePlacementRule = {
|
|
|
3083
3108
|
},
|
|
3084
3109
|
create(context) {
|
|
3085
3110
|
const sourceRoot = sourceRootOf(context);
|
|
3086
|
-
const file =
|
|
3111
|
+
const file = path31.resolve(context.filename);
|
|
3087
3112
|
const segments = segmentsOf(file, sourceRoot);
|
|
3088
3113
|
if (segments.length === 0) return {};
|
|
3089
3114
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -3161,7 +3186,7 @@ var localePlacementRule = {
|
|
|
3161
3186
|
};
|
|
3162
3187
|
|
|
3163
3188
|
// eslint/rules/sole-state-owner.ts
|
|
3164
|
-
import
|
|
3189
|
+
import path32 from "path";
|
|
3165
3190
|
import ts6 from "typescript";
|
|
3166
3191
|
function findStateHooks(node) {
|
|
3167
3192
|
const hooks = [];
|
|
@@ -3241,7 +3266,7 @@ var soleStateOwnerRule = {
|
|
|
3241
3266
|
}
|
|
3242
3267
|
},
|
|
3243
3268
|
create(context) {
|
|
3244
|
-
const filename =
|
|
3269
|
+
const filename = path32.resolve(context.filename);
|
|
3245
3270
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
3246
3271
|
const text = context.sourceCode.text;
|
|
3247
3272
|
const components = parseComponentInfo(text, filename);
|
|
@@ -3320,7 +3345,7 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
3320
3345
|
}
|
|
3321
3346
|
|
|
3322
3347
|
// eslint/rules/locale-key-shape.ts
|
|
3323
|
-
import
|
|
3348
|
+
import path33 from "path";
|
|
3324
3349
|
var MAX_KEY_LENGTH = 30;
|
|
3325
3350
|
var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
|
|
3326
3351
|
"Button",
|
|
@@ -3370,7 +3395,7 @@ var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
|
|
|
3370
3395
|
var CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
|
|
3371
3396
|
var ENGLISH = /^[A-Za-z0-9_]*$/;
|
|
3372
3397
|
function isLocalesFile2(filename) {
|
|
3373
|
-
const segments =
|
|
3398
|
+
const segments = path33.resolve(filename).split(path33.sep);
|
|
3374
3399
|
const srcIdx = segments.lastIndexOf("src");
|
|
3375
3400
|
return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
|
|
3376
3401
|
}
|
|
@@ -3441,7 +3466,7 @@ var localeKeyShapeRule = {
|
|
|
3441
3466
|
};
|
|
3442
3467
|
|
|
3443
3468
|
// eslint/rules/shared-style-dedup.ts
|
|
3444
|
-
import
|
|
3469
|
+
import path34 from "path";
|
|
3445
3470
|
import { readFileSync as readFileSync4, statSync as statSync3 } from "fs";
|
|
3446
3471
|
var CLASS_NAME = /className="(?<classes>[^"]+)"/g;
|
|
3447
3472
|
var comboCache;
|
|
@@ -3483,7 +3508,7 @@ var sharedStyleDedupRule = {
|
|
|
3483
3508
|
},
|
|
3484
3509
|
create(context) {
|
|
3485
3510
|
const sourceRoot = sourceRootOf(context);
|
|
3486
|
-
const file =
|
|
3511
|
+
const file = path34.resolve(context.filename);
|
|
3487
3512
|
const segments = segmentsOf(file, sourceRoot);
|
|
3488
3513
|
if (segments.length === 0) return {};
|
|
3489
3514
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -3687,7 +3712,7 @@ var zodSchemaValidationRule = {
|
|
|
3687
3712
|
};
|
|
3688
3713
|
|
|
3689
3714
|
// eslint/rules/source-under-src.ts
|
|
3690
|
-
import
|
|
3715
|
+
import path35 from "path";
|
|
3691
3716
|
var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
|
|
3692
3717
|
".agents",
|
|
3693
3718
|
".cache",
|
|
@@ -3728,14 +3753,14 @@ var sourceUnderSrcRule = {
|
|
|
3728
3753
|
}
|
|
3729
3754
|
},
|
|
3730
3755
|
create(context) {
|
|
3731
|
-
const filename =
|
|
3756
|
+
const filename = path35.resolve(context.filename);
|
|
3732
3757
|
if (!MODULE_EXTENSION.test(filename)) return {};
|
|
3733
|
-
const relative =
|
|
3758
|
+
const relative = path35.relative(context.cwd, filename).replace(/\\/g, "/");
|
|
3734
3759
|
if (relative === "src" || relative.startsWith("src/")) return {};
|
|
3735
3760
|
const topLevel = relative.split("/")[0] ?? "";
|
|
3736
3761
|
if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
|
|
3737
3762
|
if (!relative.includes("/")) {
|
|
3738
|
-
const basename =
|
|
3763
|
+
const basename = path35.basename(filename);
|
|
3739
3764
|
if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
|
|
3740
3765
|
}
|
|
3741
3766
|
return {
|
|
@@ -3752,7 +3777,7 @@ var sourceUnderSrcRule = {
|
|
|
3752
3777
|
|
|
3753
3778
|
// eslint/rules/zirka-baseline.ts
|
|
3754
3779
|
import fs4 from "fs";
|
|
3755
|
-
import
|
|
3780
|
+
import path36 from "path";
|
|
3756
3781
|
var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
|
|
3757
3782
|
var PRETTIER_CONFIGS = [
|
|
3758
3783
|
"prettier.config.mjs",
|
|
@@ -3771,10 +3796,10 @@ var zirkaBaselineRule = {
|
|
|
3771
3796
|
}
|
|
3772
3797
|
},
|
|
3773
3798
|
create(context) {
|
|
3774
|
-
const filename =
|
|
3775
|
-
const basename =
|
|
3799
|
+
const filename = path36.resolve(context.filename);
|
|
3800
|
+
const basename = path36.basename(filename);
|
|
3776
3801
|
if (!ESLINT_CONFIG.test(basename)) return {};
|
|
3777
|
-
const projectRoot =
|
|
3802
|
+
const projectRoot = path36.dirname(filename);
|
|
3778
3803
|
const report3 = (message) => {
|
|
3779
3804
|
context.report({
|
|
3780
3805
|
node: context.sourceCode.ast,
|
|
@@ -3789,7 +3814,7 @@ var zirkaBaselineRule = {
|
|
|
3789
3814
|
'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
|
|
3790
3815
|
);
|
|
3791
3816
|
}
|
|
3792
|
-
const tsconfigPath =
|
|
3817
|
+
const tsconfigPath = path36.join(projectRoot, "tsconfig.json");
|
|
3793
3818
|
if (!fs4.existsSync(tsconfigPath)) {
|
|
3794
3819
|
report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
|
|
3795
3820
|
} else {
|
|
@@ -3807,13 +3832,13 @@ var zirkaBaselineRule = {
|
|
|
3807
3832
|
report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
|
|
3808
3833
|
}
|
|
3809
3834
|
}
|
|
3810
|
-
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs4.existsSync(
|
|
3835
|
+
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs4.existsSync(path36.join(projectRoot, name)));
|
|
3811
3836
|
if (!prettierConfigFile) {
|
|
3812
3837
|
report3(
|
|
3813
3838
|
"No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
|
|
3814
3839
|
);
|
|
3815
3840
|
} else {
|
|
3816
|
-
const content = fs4.readFileSync(
|
|
3841
|
+
const content = fs4.readFileSync(path36.join(projectRoot, prettierConfigFile), "utf8");
|
|
3817
3842
|
if (!content.includes("zirka")) {
|
|
3818
3843
|
report3(
|
|
3819
3844
|
"The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
|
|
@@ -3883,7 +3908,7 @@ var docKindSuffixRule = {
|
|
|
3883
3908
|
};
|
|
3884
3909
|
|
|
3885
3910
|
// eslint/rules/documentation/title-matches-file-name.ts
|
|
3886
|
-
import
|
|
3911
|
+
import path37 from "path";
|
|
3887
3912
|
function toExpectedFileName(title) {
|
|
3888
3913
|
return `${title.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}.md`;
|
|
3889
3914
|
}
|
|
@@ -3903,7 +3928,7 @@ var titleMatchesFileNameRule = {
|
|
|
3903
3928
|
if (!filename.endsWith(".md")) return;
|
|
3904
3929
|
const title = getTextContent(node).trim();
|
|
3905
3930
|
const expectedFileName = toExpectedFileName(title);
|
|
3906
|
-
const actualFileName =
|
|
3931
|
+
const actualFileName = path37.basename(filename);
|
|
3907
3932
|
if (!title) {
|
|
3908
3933
|
context.report({
|
|
3909
3934
|
node,
|
|
@@ -4310,7 +4335,7 @@ var referenceBlockHeadingsRule = {
|
|
|
4310
4335
|
};
|
|
4311
4336
|
|
|
4312
4337
|
// eslint/rules/documentation/support-document-placement.ts
|
|
4313
|
-
import
|
|
4338
|
+
import path38 from "path";
|
|
4314
4339
|
var supportDocumentPlacementRule = {
|
|
4315
4340
|
meta: {
|
|
4316
4341
|
type: "problem",
|
|
@@ -4324,7 +4349,7 @@ var supportDocumentPlacementRule = {
|
|
|
4324
4349
|
root(node) {
|
|
4325
4350
|
const filename = getFilename(context);
|
|
4326
4351
|
if (!filename.endsWith(".md")) return;
|
|
4327
|
-
const parentFolder =
|
|
4352
|
+
const parentFolder = path38.basename(path38.dirname(filename));
|
|
4328
4353
|
if (filename.endsWith("-rule.md") && parentFolder !== "rules") {
|
|
4329
4354
|
context.report({
|
|
4330
4355
|
node,
|
|
@@ -4367,11 +4392,11 @@ var noTemplatePromptRule = {
|
|
|
4367
4392
|
};
|
|
4368
4393
|
|
|
4369
4394
|
// eslint/rules/documentation/guide-folder-entry-point.ts
|
|
4370
|
-
import
|
|
4395
|
+
import path40 from "path";
|
|
4371
4396
|
|
|
4372
4397
|
// eslint/rules/documentation/project-index.ts
|
|
4373
4398
|
import { readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
|
|
4374
|
-
import
|
|
4399
|
+
import path39 from "path";
|
|
4375
4400
|
var KIND_BY_SUFFIX = [
|
|
4376
4401
|
["-rule.md", "rule"],
|
|
4377
4402
|
["-guide.md", "guide"],
|
|
@@ -4380,7 +4405,7 @@ var KIND_BY_SUFFIX = [
|
|
|
4380
4405
|
];
|
|
4381
4406
|
function listMarkdownFiles(dir) {
|
|
4382
4407
|
return readdirSync3(dir).flatMap((entry) => {
|
|
4383
|
-
const entryPath =
|
|
4408
|
+
const entryPath = path39.join(dir, entry);
|
|
4384
4409
|
if (statSync4(entryPath).isDirectory()) {
|
|
4385
4410
|
return entry.startsWith("_") ? [] : listMarkdownFiles(entryPath);
|
|
4386
4411
|
}
|
|
@@ -4398,11 +4423,11 @@ function getProjectDocs(docsRoot) {
|
|
|
4398
4423
|
if (cached) return cached;
|
|
4399
4424
|
const files = listMarkdownFiles(docsRoot);
|
|
4400
4425
|
const docs = files.sort((a, b) => a.localeCompare(b)).map((filePath) => {
|
|
4401
|
-
const fileName =
|
|
4426
|
+
const fileName = path39.basename(filePath);
|
|
4402
4427
|
const kind = KIND_BY_SUFFIX.find(([suffix]) => fileName.endsWith(suffix))?.[1];
|
|
4403
4428
|
return {
|
|
4404
4429
|
filePath,
|
|
4405
|
-
doc:
|
|
4430
|
+
doc: path39.relative(docsRoot, filePath).split(path39.sep).join("/"),
|
|
4406
4431
|
fileName,
|
|
4407
4432
|
kind,
|
|
4408
4433
|
title: extractTitle(filePath)
|
|
@@ -4412,12 +4437,12 @@ function getProjectDocs(docsRoot) {
|
|
|
4412
4437
|
return docs;
|
|
4413
4438
|
}
|
|
4414
4439
|
function findDocsRoot(filePath) {
|
|
4415
|
-
let dir =
|
|
4440
|
+
let dir = path39.dirname(filePath);
|
|
4416
4441
|
for (; ; ) {
|
|
4417
|
-
if (
|
|
4442
|
+
if (path39.basename(dir) === "docs" && statSync4(dir).isDirectory()) {
|
|
4418
4443
|
return dir;
|
|
4419
4444
|
}
|
|
4420
|
-
const parent =
|
|
4445
|
+
const parent = path39.dirname(dir);
|
|
4421
4446
|
if (parent === dir) return void 0;
|
|
4422
4447
|
dir = parent;
|
|
4423
4448
|
}
|
|
@@ -4441,13 +4466,13 @@ var guideFolderEntryPointRule = {
|
|
|
4441
4466
|
if (!docsRoot) return;
|
|
4442
4467
|
const docs = getProjectDocs(docsRoot);
|
|
4443
4468
|
const guideFolders = new Set(
|
|
4444
|
-
docs.filter((doc) => ["rules", "references"].includes(
|
|
4469
|
+
docs.filter((doc) => ["rules", "references"].includes(path40.basename(path40.dirname(doc.filePath)))).map((doc) => path40.dirname(path40.dirname(doc.filePath))).filter((folder) => path40.resolve(folder) !== path40.resolve(docsRoot))
|
|
4445
4470
|
);
|
|
4446
|
-
const currentDir =
|
|
4471
|
+
const currentDir = path40.dirname(filename);
|
|
4447
4472
|
if (guideFolders.has(currentDir)) {
|
|
4448
|
-
const expectedEntryPoint = `${
|
|
4473
|
+
const expectedEntryPoint = `${path40.basename(currentDir)}.md`;
|
|
4449
4474
|
const hasEntryPoint = docs.some(
|
|
4450
|
-
(doc) => doc.kind === "guide" &&
|
|
4475
|
+
(doc) => doc.kind === "guide" && path40.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
|
|
4451
4476
|
);
|
|
4452
4477
|
if (!hasEntryPoint) {
|
|
4453
4478
|
context.report({
|
|
@@ -4672,7 +4697,7 @@ var noNestedHowToRule = {
|
|
|
4672
4697
|
|
|
4673
4698
|
// eslint/rules/documentation/glossary-term-linking.ts
|
|
4674
4699
|
import { readFileSync as readFileSync6 } from "fs";
|
|
4675
|
-
import
|
|
4700
|
+
import path41 from "path";
|
|
4676
4701
|
function extractGlossaryTerms(filePath) {
|
|
4677
4702
|
const content = readFileSync6(filePath, "utf8");
|
|
4678
4703
|
const terms = [];
|
|
@@ -4726,9 +4751,9 @@ var glossaryTermLinkingRule = {
|
|
|
4726
4751
|
const docsRoot = findDocsRoot(filename);
|
|
4727
4752
|
if (!docsRoot) return;
|
|
4728
4753
|
const docs = getProjectDocs(docsRoot);
|
|
4729
|
-
const guideDir =
|
|
4754
|
+
const guideDir = path41.dirname(filename);
|
|
4730
4755
|
const guideReferences = docs.filter(
|
|
4731
|
-
(doc) => doc.kind === "reference" &&
|
|
4756
|
+
(doc) => doc.kind === "reference" && path41.dirname(doc.filePath) === guideDir
|
|
4732
4757
|
);
|
|
4733
4758
|
if (guideReferences.length === 0) return;
|
|
4734
4759
|
const glossaryTerms = [];
|
|
@@ -4753,7 +4778,7 @@ var glossaryTermLinkingRule = {
|
|
|
4753
4778
|
|
|
4754
4779
|
// eslint/rules/documentation/guide-mentions-documents.ts
|
|
4755
4780
|
import { existsSync } from "fs";
|
|
4756
|
-
import
|
|
4781
|
+
import path42 from "path";
|
|
4757
4782
|
function visitSteps3(node, check) {
|
|
4758
4783
|
if (node.type === "list" && node.ordered) {
|
|
4759
4784
|
for (const child of node.children) check(child);
|
|
@@ -4786,12 +4811,12 @@ var guideMentionsDocumentsRule = {
|
|
|
4786
4811
|
if (!filename.endsWith("-guide.md")) return;
|
|
4787
4812
|
const docsRoot = findDocsRoot(filename);
|
|
4788
4813
|
if (!docsRoot) return;
|
|
4789
|
-
const guideDir =
|
|
4790
|
-
if (
|
|
4814
|
+
const guideDir = path42.dirname(filename);
|
|
4815
|
+
if (path42.basename(filename, ".md") !== path42.basename(guideDir)) return;
|
|
4791
4816
|
const docs = getProjectDocs(docsRoot);
|
|
4792
4817
|
const owned = docs.filter((doc) => {
|
|
4793
|
-
const parent =
|
|
4794
|
-
return parent ===
|
|
4818
|
+
const parent = path42.dirname(doc.filePath);
|
|
4819
|
+
return parent === path42.join(guideDir, "rules") || parent === path42.join(guideDir, "references");
|
|
4795
4820
|
});
|
|
4796
4821
|
const allLinks = [];
|
|
4797
4822
|
collectMarkdownLinks(node, allLinks);
|
|
@@ -4818,7 +4843,7 @@ var guideMentionsDocumentsRule = {
|
|
|
4818
4843
|
for (const link of allLinks) {
|
|
4819
4844
|
const target = linkTarget(link.url);
|
|
4820
4845
|
if (!target.endsWith(".md")) continue;
|
|
4821
|
-
const resolved =
|
|
4846
|
+
const resolved = path42.normalize(path42.join(guideDir, target));
|
|
4822
4847
|
if (!existsSync(resolved)) {
|
|
4823
4848
|
context.report({
|
|
4824
4849
|
node: link,
|
|
@@ -5270,11 +5295,11 @@ var themeVariableNamespaceRule = {
|
|
|
5270
5295
|
|
|
5271
5296
|
// eslint/rules/tailwind/css-entry-point.ts
|
|
5272
5297
|
import { statSync as statSync6 } from "fs";
|
|
5273
|
-
import
|
|
5298
|
+
import path45 from "path";
|
|
5274
5299
|
|
|
5275
5300
|
// eslint/rules/tailwind/source-files.ts
|
|
5276
5301
|
import { readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
|
|
5277
|
-
import
|
|
5302
|
+
import path43 from "path";
|
|
5278
5303
|
var CSS_EXTENSIONS = [".css"];
|
|
5279
5304
|
var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
5280
5305
|
var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS3, ...CSS_EXTENSIONS];
|
|
@@ -5287,7 +5312,7 @@ function findFiles(dir, extensions) {
|
|
|
5287
5312
|
}
|
|
5288
5313
|
return entries.flatMap((entry) => {
|
|
5289
5314
|
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
5290
|
-
const entryPath =
|
|
5315
|
+
const entryPath = path43.join(dir, entry);
|
|
5291
5316
|
let stats;
|
|
5292
5317
|
try {
|
|
5293
5318
|
stats = statSync5(entryPath);
|
|
@@ -5295,7 +5320,7 @@ function findFiles(dir, extensions) {
|
|
|
5295
5320
|
return [];
|
|
5296
5321
|
}
|
|
5297
5322
|
if (stats.isDirectory()) return findFiles(entryPath, extensions);
|
|
5298
|
-
return extensions.includes(
|
|
5323
|
+
return extensions.includes(path43.extname(entry)) ? [entryPath] : [];
|
|
5299
5324
|
});
|
|
5300
5325
|
}
|
|
5301
5326
|
function cachedTextReader() {
|
|
@@ -5318,7 +5343,7 @@ function escapeRegExp(text) {
|
|
|
5318
5343
|
}
|
|
5319
5344
|
|
|
5320
5345
|
// eslint/rules/tailwind/stylesheet-graph.ts
|
|
5321
|
-
import
|
|
5346
|
+
import path44 from "path";
|
|
5322
5347
|
function registersTailwind(text) {
|
|
5323
5348
|
return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
|
|
5324
5349
|
}
|
|
@@ -5332,25 +5357,25 @@ function moduleImports(text, fileName) {
|
|
|
5332
5357
|
return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
|
|
5333
5358
|
}
|
|
5334
5359
|
function resolveSpecifier2(fromFile, spec, sourceRoot) {
|
|
5335
|
-
if (spec.startsWith("/")) return
|
|
5336
|
-
if (spec.startsWith("./") || spec.startsWith("../")) return
|
|
5337
|
-
if (spec.startsWith("@/")) return
|
|
5360
|
+
if (spec.startsWith("/")) return path44.resolve(spec);
|
|
5361
|
+
if (spec.startsWith("./") || spec.startsWith("../")) return path44.resolve(path44.dirname(fromFile), spec);
|
|
5362
|
+
if (spec.startsWith("@/")) return path44.resolve(sourceRoot, spec.slice(2));
|
|
5338
5363
|
return void 0;
|
|
5339
5364
|
}
|
|
5340
5365
|
function buildStylesheetGraph(options) {
|
|
5341
5366
|
const { cssFiles, sourceRoot, textOf } = options;
|
|
5342
|
-
const cssSet = new Set(cssFiles.map((file) =>
|
|
5367
|
+
const cssSet = new Set(cssFiles.map((file) => path44.normalize(file)));
|
|
5343
5368
|
const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
|
|
5344
5369
|
const reachable = /* @__PURE__ */ new Set();
|
|
5345
5370
|
const queue = [...globals];
|
|
5346
|
-
for (const global of globals) reachable.add(
|
|
5371
|
+
for (const global of globals) reachable.add(path44.normalize(global));
|
|
5347
5372
|
while (queue.length > 0) {
|
|
5348
5373
|
const from = queue.shift();
|
|
5349
5374
|
if (!from) continue;
|
|
5350
5375
|
for (const spec of importedSpecifiers(textOf(from))) {
|
|
5351
5376
|
const target = resolveSpecifier2(from, spec, sourceRoot);
|
|
5352
5377
|
if (!target) continue;
|
|
5353
|
-
const normalized =
|
|
5378
|
+
const normalized = path44.normalize(target);
|
|
5354
5379
|
if (cssSet.has(normalized) && !reachable.has(normalized)) {
|
|
5355
5380
|
reachable.add(normalized);
|
|
5356
5381
|
queue.push(normalized);
|
|
@@ -5362,7 +5387,7 @@ function buildStylesheetGraph(options) {
|
|
|
5362
5387
|
for (const spec of importedSpecifiers(textOf(global))) {
|
|
5363
5388
|
const target = resolveSpecifier2(global, spec, sourceRoot);
|
|
5364
5389
|
if (!target) continue;
|
|
5365
|
-
const normalized =
|
|
5390
|
+
const normalized = path44.normalize(target);
|
|
5366
5391
|
if (cssSet.has(normalized)) directChildren.add(normalized);
|
|
5367
5392
|
}
|
|
5368
5393
|
}
|
|
@@ -5395,7 +5420,7 @@ var cssEntryPointRule = {
|
|
|
5395
5420
|
return {
|
|
5396
5421
|
"StyleSheet:exit"(node) {
|
|
5397
5422
|
if (globals.length === 0) return;
|
|
5398
|
-
const current =
|
|
5423
|
+
const current = path45.normalize(path45.resolve(context.filename));
|
|
5399
5424
|
if (globals.includes(current)) {
|
|
5400
5425
|
if (globals.length > 1) {
|
|
5401
5426
|
context.report({
|
|
@@ -5404,7 +5429,7 @@ var cssEntryPointRule = {
|
|
|
5404
5429
|
});
|
|
5405
5430
|
return;
|
|
5406
5431
|
}
|
|
5407
|
-
const basename =
|
|
5432
|
+
const basename = path45.basename(current);
|
|
5408
5433
|
const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
|
|
5409
5434
|
if (importCount !== 1) {
|
|
5410
5435
|
context.report({
|
|
@@ -5673,7 +5698,7 @@ var nextjsPackageJsonRules = {
|
|
|
5673
5698
|
|
|
5674
5699
|
// eslint/rules/husky/husky-hook.ts
|
|
5675
5700
|
import { existsSync as existsSync2, readFileSync as readFileSync8 } from "fs";
|
|
5676
|
-
import
|
|
5701
|
+
import path46 from "path";
|
|
5677
5702
|
function memberName4(member) {
|
|
5678
5703
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
5679
5704
|
}
|
|
@@ -5692,7 +5717,7 @@ var huskyHookRule = {
|
|
|
5692
5717
|
if (root.type !== "Object") return;
|
|
5693
5718
|
const scriptName = context.filename;
|
|
5694
5719
|
if (!scriptName.endsWith("package.json")) return;
|
|
5695
|
-
const hookPath =
|
|
5720
|
+
const hookPath = path46.join(context.cwd, ".husky", "pre-commit");
|
|
5696
5721
|
if (!existsSync2(hookPath)) {
|
|
5697
5722
|
context.report({
|
|
5698
5723
|
node,
|
|
@@ -5732,7 +5757,7 @@ var huskyRules = {
|
|
|
5732
5757
|
|
|
5733
5758
|
// eslint/rules/vulyk/vulyk-docs.ts
|
|
5734
5759
|
import { existsSync as existsSync3, readFileSync as readFileSync9 } from "fs";
|
|
5735
|
-
import
|
|
5760
|
+
import path47 from "path";
|
|
5736
5761
|
var PASIKA_REPO = "Bredansky/pasika";
|
|
5737
5762
|
var BASE_REQUIRED_DOCS = [
|
|
5738
5763
|
{ name: "documentation-guide", path: "docs/documentation-guide" },
|
|
@@ -5765,8 +5790,8 @@ var vulykDocsRule = {
|
|
|
5765
5790
|
if (!context.filename.endsWith("package.json")) return;
|
|
5766
5791
|
const root = node.body;
|
|
5767
5792
|
if (root.type !== "Object") return;
|
|
5768
|
-
const projectRoot =
|
|
5769
|
-
const configPath =
|
|
5793
|
+
const projectRoot = path47.dirname(path47.resolve(context.filename));
|
|
5794
|
+
const configPath = path47.join(projectRoot, "vulyk.config.ts");
|
|
5770
5795
|
if (!existsSync3(configPath)) {
|
|
5771
5796
|
context.report({
|
|
5772
5797
|
node,
|
|
@@ -5791,7 +5816,7 @@ var vulykDocsRule = {
|
|
|
5791
5816
|
});
|
|
5792
5817
|
}
|
|
5793
5818
|
}
|
|
5794
|
-
const agentsPath =
|
|
5819
|
+
const agentsPath = path47.join(projectRoot, "AGENTS.md");
|
|
5795
5820
|
if (!existsSync3(agentsPath)) {
|
|
5796
5821
|
context.report({
|
|
5797
5822
|
node,
|