pasika 0.5.2 → 0.5.4
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 +480 -456
- 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) {
|
|
@@ -1084,323 +1314,108 @@ var enforceCvaVariantPropsRule = {
|
|
|
1084
1314
|
cvaDefinitions.set(node.id.name, variantNames);
|
|
1085
1315
|
}
|
|
1086
1316
|
}
|
|
1087
|
-
},
|
|
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
|
-
}
|
|
1317
|
+
},
|
|
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,7 +1598,7 @@ 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",
|
|
@@ -1612,7 +1627,7 @@ function report2(context, message) {
|
|
|
1612
1627
|
};
|
|
1613
1628
|
}
|
|
1614
1629
|
function isCodeFile(filename) {
|
|
1615
|
-
return MODULE_EXTENSIONS2.has(
|
|
1630
|
+
return MODULE_EXTENSIONS2.has(path13.extname(filename));
|
|
1616
1631
|
}
|
|
1617
1632
|
function isRootSupportFolder(folder) {
|
|
1618
1633
|
return SUPPORT_FOLDERS2.has(folder);
|
|
@@ -1633,7 +1648,7 @@ function expectedSupportFolder(kinds) {
|
|
|
1633
1648
|
function configModuleRoot(filename, sourceRoot) {
|
|
1634
1649
|
const segments = segmentsOf(filename, sourceRoot);
|
|
1635
1650
|
if (segments[0] !== "config" || segments.length < 3) return void 0;
|
|
1636
|
-
return
|
|
1651
|
+
return path13.join(sourceRoot, "config", segments[1] ?? "");
|
|
1637
1652
|
}
|
|
1638
1653
|
function componentFolderStart(segments) {
|
|
1639
1654
|
if (segments[0] === "features") return 2;
|
|
@@ -1646,12 +1661,12 @@ function componentFolderViolation(segments, sourceRoot) {
|
|
|
1646
1661
|
for (let depth = segments.length - 2; depth >= start; depth -= 1) {
|
|
1647
1662
|
const folder = segments[depth];
|
|
1648
1663
|
if (!folder || SUPPORT_FOLDERS2.has(folder)) continue;
|
|
1649
|
-
const folderPath =
|
|
1664
|
+
const folderPath = path13.join(sourceRoot, ...segments.slice(0, depth + 1));
|
|
1650
1665
|
const label = `src/${segments.slice(0, depth + 1).join("/")}/`;
|
|
1651
|
-
if (!fs2.existsSync(
|
|
1666
|
+
if (!fs2.existsSync(path13.join(folderPath, `${folder}.tsx`))) {
|
|
1652
1667
|
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
1668
|
}
|
|
1654
|
-
if (!fs2.existsSync(
|
|
1669
|
+
if (!fs2.existsSync(path13.join(folderPath, "index.ts"))) {
|
|
1655
1670
|
return `A component folder must have an index.ts that named-re-exports its component; add index.ts to ${label}.`;
|
|
1656
1671
|
}
|
|
1657
1672
|
}
|
|
@@ -1666,7 +1681,7 @@ var applicationStructureRule = {
|
|
|
1666
1681
|
}
|
|
1667
1682
|
},
|
|
1668
1683
|
create(context) {
|
|
1669
|
-
const filename =
|
|
1684
|
+
const filename = path13.resolve(context.filename);
|
|
1670
1685
|
const sourceRoot = sourceRootOf(context);
|
|
1671
1686
|
const segments = segmentsOf(filename, sourceRoot);
|
|
1672
1687
|
if (segments.length === 0) return {};
|
|
@@ -1697,42 +1712,42 @@ var applicationStructureRule = {
|
|
|
1697
1712
|
);
|
|
1698
1713
|
}
|
|
1699
1714
|
const moduleRoot = configModuleRoot(filename, sourceRoot);
|
|
1700
|
-
if (moduleRoot && !fs2.existsSync(
|
|
1715
|
+
if (moduleRoot && !fs2.existsSync(path13.join(moduleRoot, "index.ts"))) {
|
|
1701
1716
|
return report2(
|
|
1702
1717
|
context,
|
|
1703
|
-
`Add src/config/${
|
|
1718
|
+
`Add src/config/${path13.basename(moduleRoot)}/index.ts as the configuration module entry point.`
|
|
1704
1719
|
);
|
|
1705
1720
|
}
|
|
1706
|
-
if (moduleRoot && segments.length === 3 &&
|
|
1721
|
+
if (moduleRoot && segments.length === 3 && path13.basename(filename) !== "index.ts") {
|
|
1707
1722
|
const kinds2 = exportedKinds(filename);
|
|
1708
1723
|
const expected2 = expectedSupportFolder(kinds2);
|
|
1709
1724
|
if (expected2 !== void 0) {
|
|
1710
1725
|
return report2(
|
|
1711
1726
|
context,
|
|
1712
|
-
`Move this configuration support file into src/config/${
|
|
1727
|
+
`Move this configuration support file into src/config/${path13.basename(moduleRoot)}/${expected2}/.`
|
|
1713
1728
|
);
|
|
1714
1729
|
}
|
|
1715
1730
|
}
|
|
1716
1731
|
}
|
|
1717
1732
|
if (topLevel === "app" && isCodeFile(filename)) {
|
|
1718
|
-
const basename =
|
|
1719
|
-
const currentFolder2 =
|
|
1733
|
+
const basename = path13.basename(filename, path13.extname(filename));
|
|
1734
|
+
const currentFolder2 = path13.basename(path13.dirname(filename));
|
|
1720
1735
|
if (SUPPORT_FOLDERS2.has(currentFolder2)) {
|
|
1721
1736
|
return report2(
|
|
1722
1737
|
context,
|
|
1723
1738
|
"src/app/ may contain routing files and framework assets, but ordinary components and support files must live outside src/app/."
|
|
1724
1739
|
);
|
|
1725
1740
|
}
|
|
1726
|
-
if (!ROUTING_FILES.has(basename) &&
|
|
1741
|
+
if (!ROUTING_FILES.has(basename) && path13.extname(filename) !== ".css") {
|
|
1727
1742
|
return report2(
|
|
1728
1743
|
context,
|
|
1729
1744
|
"src/app/ may contain routing files and framework assets, but ordinary components and support files must live outside src/app/."
|
|
1730
1745
|
);
|
|
1731
1746
|
}
|
|
1732
1747
|
}
|
|
1733
|
-
const currentFolder =
|
|
1748
|
+
const currentFolder = path13.basename(path13.dirname(filename));
|
|
1734
1749
|
const kinds = exportedKinds(filename);
|
|
1735
|
-
const isConfigModuleRoot = topLevel === "config" && segments.length === 3 &&
|
|
1750
|
+
const isConfigModuleRoot = topLevel === "config" && segments.length === 3 && path13.basename(filename) === "index.ts";
|
|
1736
1751
|
if (isConfigModuleRoot) return {};
|
|
1737
1752
|
if (!SUPPORT_FOLDERS2.has(currentFolder)) {
|
|
1738
1753
|
const expected2 = expectedSupportFolder(kinds);
|
|
@@ -1749,7 +1764,7 @@ var applicationStructureRule = {
|
|
|
1749
1764
|
if (kinds.has("component")) {
|
|
1750
1765
|
return report2(
|
|
1751
1766
|
context,
|
|
1752
|
-
`A support folder must not contain a component; move ${
|
|
1767
|
+
`A support folder must not contain a component; move ${path13.basename(filename)} beside ${currentFolder}/.`
|
|
1753
1768
|
);
|
|
1754
1769
|
}
|
|
1755
1770
|
const expected = expectedSupportFolder(kinds);
|
|
@@ -1766,7 +1781,7 @@ var applicationStructureRule = {
|
|
|
1766
1781
|
};
|
|
1767
1782
|
|
|
1768
1783
|
// eslint/rules/named-exports.ts
|
|
1769
|
-
import
|
|
1784
|
+
import path14 from "path";
|
|
1770
1785
|
var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
|
|
1771
1786
|
// App Router routing files
|
|
1772
1787
|
"default",
|
|
@@ -1788,9 +1803,9 @@ var FRAMEWORK_DEFAULT_EXPORT_FILES = /* @__PURE__ */ new Set([
|
|
|
1788
1803
|
"twitter-image"
|
|
1789
1804
|
]);
|
|
1790
1805
|
function isFrameworkDefaultExportFile(filename) {
|
|
1791
|
-
const normalized = filename.replaceAll(
|
|
1806
|
+
const normalized = filename.replaceAll(path14.sep, "/");
|
|
1792
1807
|
if (!normalized.includes("/src/app/")) return false;
|
|
1793
|
-
const basename =
|
|
1808
|
+
const basename = path14.basename(filename, path14.extname(filename));
|
|
1794
1809
|
return FRAMEWORK_DEFAULT_EXPORT_FILES.has(basename);
|
|
1795
1810
|
}
|
|
1796
1811
|
var namedExportsRule = {
|
|
@@ -1815,7 +1830,7 @@ var namedExportsRule = {
|
|
|
1815
1830
|
};
|
|
1816
1831
|
|
|
1817
1832
|
// eslint/rules/data-testid-case.ts
|
|
1818
|
-
import
|
|
1833
|
+
import path15 from "path";
|
|
1819
1834
|
var NEXT_ROUTING_FILES2 = /* @__PURE__ */ new Set([
|
|
1820
1835
|
"page",
|
|
1821
1836
|
"layout",
|
|
@@ -1839,9 +1854,9 @@ var dataTestIdCaseRule = {
|
|
|
1839
1854
|
}
|
|
1840
1855
|
},
|
|
1841
1856
|
create(context) {
|
|
1842
|
-
const filename =
|
|
1857
|
+
const filename = path15.resolve(context.filename);
|
|
1843
1858
|
if (!filename.endsWith(".tsx")) return {};
|
|
1844
|
-
const base =
|
|
1859
|
+
const base = path15.basename(filename, path15.extname(filename));
|
|
1845
1860
|
if (NEXT_ROUTING_FILES2.has(base)) return {};
|
|
1846
1861
|
const text = context.sourceCode.text;
|
|
1847
1862
|
const components = parseComponentInfo(text, filename);
|
|
@@ -1883,7 +1898,7 @@ function toKebabCase(value) {
|
|
|
1883
1898
|
|
|
1884
1899
|
// eslint/rules/support-folder-shape.ts
|
|
1885
1900
|
import fs3 from "fs";
|
|
1886
|
-
import
|
|
1901
|
+
import path16 from "path";
|
|
1887
1902
|
var SUPPORT_FOLDERS3 = /* @__PURE__ */ new Set(["constants", "types", "schemas"]);
|
|
1888
1903
|
var INDEX_NAMES = /* @__PURE__ */ new Set(["index.ts", "index.tsx", "index.mts", "index.cts"]);
|
|
1889
1904
|
var supportFolderShapeRule = {
|
|
@@ -1895,12 +1910,12 @@ var supportFolderShapeRule = {
|
|
|
1895
1910
|
}
|
|
1896
1911
|
},
|
|
1897
1912
|
create(context) {
|
|
1898
|
-
const filename =
|
|
1899
|
-
const baseName =
|
|
1913
|
+
const filename = path16.resolve(context.filename);
|
|
1914
|
+
const baseName = path16.basename(filename);
|
|
1900
1915
|
if (!INDEX_NAMES.has(baseName)) return {};
|
|
1901
|
-
const folder =
|
|
1916
|
+
const folder = path16.basename(path16.dirname(filename));
|
|
1902
1917
|
if (!SUPPORT_FOLDERS3.has(folder)) return {};
|
|
1903
|
-
const directory =
|
|
1918
|
+
const directory = path16.dirname(filename);
|
|
1904
1919
|
let entries;
|
|
1905
1920
|
try {
|
|
1906
1921
|
entries = fs3.readdirSync(directory);
|
|
@@ -1918,7 +1933,7 @@ var supportFolderShapeRule = {
|
|
|
1918
1933
|
const exportPattern = /export\s+(?:\{[^}]*\}|\*[^;]*)\s+from\s+["'](?<specifier>\.[^"']+)["']/g;
|
|
1919
1934
|
for (const match of source.matchAll(exportPattern)) {
|
|
1920
1935
|
const specifier = match.groups?.specifier;
|
|
1921
|
-
if (specifier) exportedFiles.add(
|
|
1936
|
+
if (specifier) exportedFiles.add(path16.basename(specifier));
|
|
1922
1937
|
}
|
|
1923
1938
|
const missing = siblingModules.filter((entry) => {
|
|
1924
1939
|
const stem = entry.replace(/\.(?:[cm]?tsx?|jsx?)$/, "");
|
|
@@ -1935,7 +1950,7 @@ var supportFolderShapeRule = {
|
|
|
1935
1950
|
};
|
|
1936
1951
|
|
|
1937
1952
|
// eslint/rules/import-through-index.ts
|
|
1938
|
-
import
|
|
1953
|
+
import path17 from "path";
|
|
1939
1954
|
var importThroughIndexRule = {
|
|
1940
1955
|
meta: {
|
|
1941
1956
|
schema: [],
|
|
@@ -1945,7 +1960,7 @@ var importThroughIndexRule = {
|
|
|
1945
1960
|
}
|
|
1946
1961
|
},
|
|
1947
1962
|
create(context) {
|
|
1948
|
-
const filename =
|
|
1963
|
+
const filename = path17.resolve(context.filename);
|
|
1949
1964
|
const sourceRoot = sourceRootOf2(context, filename);
|
|
1950
1965
|
return {
|
|
1951
1966
|
Program(node) {
|
|
@@ -1957,7 +1972,7 @@ var importThroughIndexRule = {
|
|
|
1957
1972
|
(segment) => ["constants", "types", "schemas"].includes(segment)
|
|
1958
1973
|
);
|
|
1959
1974
|
const supportFolder = supportFolderIndex >= 0 ? targetSegments[supportFolderIndex] : void 0;
|
|
1960
|
-
if (!supportFolder ||
|
|
1975
|
+
if (!supportFolder || path17.basename(target).startsWith("index.")) continue;
|
|
1961
1976
|
const folderIndex = targetSegments.slice(0, supportFolderIndex + 1);
|
|
1962
1977
|
const expected = `@/${folderIndex.join("/")}`;
|
|
1963
1978
|
context.report({
|
|
@@ -1979,14 +1994,14 @@ function importSpecifiers(source) {
|
|
|
1979
1994
|
return specifiers;
|
|
1980
1995
|
}
|
|
1981
1996
|
function sourceRootOf2(context, filename) {
|
|
1982
|
-
const marker = `${
|
|
1997
|
+
const marker = `${path17.sep}src${path17.sep}`;
|
|
1983
1998
|
const srcIndex = filename.lastIndexOf(marker);
|
|
1984
1999
|
if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
|
|
1985
|
-
return
|
|
2000
|
+
return path17.resolve(context.cwd ?? process.cwd(), "src");
|
|
1986
2001
|
}
|
|
1987
2002
|
|
|
1988
2003
|
// eslint/rules/util-file-name.ts
|
|
1989
|
-
import
|
|
2004
|
+
import path18 from "path";
|
|
1990
2005
|
function toKebabCase2(value) {
|
|
1991
2006
|
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
2007
|
}
|
|
@@ -1999,7 +2014,7 @@ var utilFileNameRule = {
|
|
|
1999
2014
|
}
|
|
2000
2015
|
},
|
|
2001
2016
|
create(context) {
|
|
2002
|
-
const filename =
|
|
2017
|
+
const filename = path18.resolve(context.filename);
|
|
2003
2018
|
const segments = filename.replace(/\\/g, "/").split("/");
|
|
2004
2019
|
if (!segments.includes("utils")) return {};
|
|
2005
2020
|
let module;
|
|
@@ -2013,13 +2028,13 @@ var utilFileNameRule = {
|
|
|
2013
2028
|
const functionName = functions[0]?.name;
|
|
2014
2029
|
if (!functionName) return {};
|
|
2015
2030
|
const expected = toKebabCase2(functionName);
|
|
2016
|
-
const actual =
|
|
2031
|
+
const actual = path18.basename(filename, path18.extname(filename));
|
|
2017
2032
|
if (!expected || actual === expected) return {};
|
|
2018
2033
|
return {
|
|
2019
2034
|
Program(node) {
|
|
2020
2035
|
context.report({
|
|
2021
2036
|
node,
|
|
2022
|
-
message: `A utility file exporting ${functionName} must be named ${expected}.${
|
|
2037
|
+
message: `A utility file exporting ${functionName} must be named ${expected}.${path18.extname(filename).slice(1)}.`
|
|
2023
2038
|
});
|
|
2024
2039
|
}
|
|
2025
2040
|
};
|
|
@@ -2027,7 +2042,7 @@ var utilFileNameRule = {
|
|
|
2027
2042
|
};
|
|
2028
2043
|
|
|
2029
2044
|
// eslint/rules/no-util-barrel.ts
|
|
2030
|
-
import
|
|
2045
|
+
import path19 from "path";
|
|
2031
2046
|
var noUtilBarrelRule = {
|
|
2032
2047
|
meta: {
|
|
2033
2048
|
schema: [],
|
|
@@ -2037,7 +2052,7 @@ var noUtilBarrelRule = {
|
|
|
2037
2052
|
}
|
|
2038
2053
|
},
|
|
2039
2054
|
create(context) {
|
|
2040
|
-
const filename =
|
|
2055
|
+
const filename = path19.resolve(context.filename);
|
|
2041
2056
|
const sourceRoot = sourceRootOf3(context, filename);
|
|
2042
2057
|
return {
|
|
2043
2058
|
Program(node) {
|
|
@@ -2046,7 +2061,7 @@ var noUtilBarrelRule = {
|
|
|
2046
2061
|
if (!target) continue;
|
|
2047
2062
|
const segments = target.replace(/\\/g, "/").split("/");
|
|
2048
2063
|
const utilsIndex = segments.lastIndexOf("utils");
|
|
2049
|
-
if (utilsIndex < 0 || !
|
|
2064
|
+
if (utilsIndex < 0 || !path19.basename(target).startsWith("index.")) continue;
|
|
2050
2065
|
context.report({
|
|
2051
2066
|
node,
|
|
2052
2067
|
message: `Import utilities directly instead of through "${specifier}". See docs/code-organization-guide/rules/utilities-rule.md`
|
|
@@ -2066,10 +2081,10 @@ function importSpecifiers2(source) {
|
|
|
2066
2081
|
return specifiers;
|
|
2067
2082
|
}
|
|
2068
2083
|
function sourceRootOf3(context, filename) {
|
|
2069
|
-
const marker = `${
|
|
2084
|
+
const marker = `${path19.sep}src${path19.sep}`;
|
|
2070
2085
|
const srcIndex = filename.lastIndexOf(marker);
|
|
2071
2086
|
if (srcIndex >= 0) return filename.slice(0, srcIndex + marker.length - 1);
|
|
2072
|
-
return
|
|
2087
|
+
return path19.resolve(context.cwd ?? process.cwd(), "src");
|
|
2073
2088
|
}
|
|
2074
2089
|
|
|
2075
2090
|
// eslint/rules/jsx-hygiene.ts
|
|
@@ -2445,12 +2460,12 @@ var cvaBooleanVariantsRule = {
|
|
|
2445
2460
|
};
|
|
2446
2461
|
|
|
2447
2462
|
// eslint/rules/cross-feature-import.ts
|
|
2448
|
-
import
|
|
2463
|
+
import path20 from "path";
|
|
2449
2464
|
var FEATURES_SEGMENT = "features";
|
|
2450
2465
|
function featureNameOf(resolvedPath, sourceRoot) {
|
|
2451
|
-
const relative =
|
|
2466
|
+
const relative = path20.relative(sourceRoot, resolvedPath);
|
|
2452
2467
|
if (relative.startsWith("..")) return void 0;
|
|
2453
|
-
const segments = relative.split(
|
|
2468
|
+
const segments = relative.split(path20.sep);
|
|
2454
2469
|
if (segments[0] !== FEATURES_SEGMENT || segments.length < 2) return void 0;
|
|
2455
2470
|
return segments[1];
|
|
2456
2471
|
}
|
|
@@ -2466,9 +2481,9 @@ var crossFeatureImportRule = {
|
|
|
2466
2481
|
const filename = context.filename;
|
|
2467
2482
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
2468
2483
|
const sourceRoot = sourceRootOf(context);
|
|
2469
|
-
const fileRelative =
|
|
2484
|
+
const fileRelative = path20.relative(sourceRoot, filename);
|
|
2470
2485
|
if (fileRelative.startsWith("..")) return {};
|
|
2471
|
-
const fileSegments = fileRelative.split(
|
|
2486
|
+
const fileSegments = fileRelative.split(path20.sep);
|
|
2472
2487
|
const isInCompositions = fileSegments[0] === "compositions";
|
|
2473
2488
|
const isInApp = fileSegments[0] === "app";
|
|
2474
2489
|
const isConfig = fileSegments[0] === "config";
|
|
@@ -2482,9 +2497,9 @@ var crossFeatureImportRule = {
|
|
|
2482
2497
|
if (typeof source.value !== "string") return;
|
|
2483
2498
|
let resolved;
|
|
2484
2499
|
if (source.value.startsWith("@/")) {
|
|
2485
|
-
resolved =
|
|
2500
|
+
resolved = path20.resolve(sourceRoot, source.value.slice(2));
|
|
2486
2501
|
} else if (source.value.startsWith(".")) {
|
|
2487
|
-
resolved =
|
|
2502
|
+
resolved = path20.resolve(path20.dirname(filename), source.value);
|
|
2488
2503
|
}
|
|
2489
2504
|
if (!resolved) return;
|
|
2490
2505
|
const feature = featureNameOf(resolved, sourceRoot);
|
|
@@ -2503,7 +2518,7 @@ var crossFeatureImportRule = {
|
|
|
2503
2518
|
};
|
|
2504
2519
|
|
|
2505
2520
|
// eslint/rules/pure-function-extract.ts
|
|
2506
|
-
import
|
|
2521
|
+
import path21 from "path";
|
|
2507
2522
|
function isComponentLikeName(name) {
|
|
2508
2523
|
return /^[A-Z]/.test(name);
|
|
2509
2524
|
}
|
|
@@ -2532,9 +2547,9 @@ var pureFunctionExtractRule = {
|
|
|
2532
2547
|
const filename = context.filename;
|
|
2533
2548
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
2534
2549
|
const sourceRoot = sourceRootOf(context);
|
|
2535
|
-
const relative =
|
|
2550
|
+
const relative = path21.relative(sourceRoot, filename);
|
|
2536
2551
|
if (relative.startsWith("..")) return {};
|
|
2537
|
-
const segments = relative.split(
|
|
2552
|
+
const segments = relative.split(path21.sep);
|
|
2538
2553
|
if (segments[0] === "utils") return {};
|
|
2539
2554
|
if (segments[0] === "app") return {};
|
|
2540
2555
|
const supportFolders = /* @__PURE__ */ new Set(["hooks", "types", "schemas", "constants", "utils"]);
|
|
@@ -2574,7 +2589,7 @@ var pureFunctionExtractRule = {
|
|
|
2574
2589
|
};
|
|
2575
2590
|
|
|
2576
2591
|
// eslint/rules/hook-complexity.ts
|
|
2577
|
-
import
|
|
2592
|
+
import path22 from "path";
|
|
2578
2593
|
import ts4 from "typescript";
|
|
2579
2594
|
var REACT_HOOKS = /* @__PURE__ */ new Set([
|
|
2580
2595
|
"useState",
|
|
@@ -2627,9 +2642,9 @@ var hookComplexityRule = {
|
|
|
2627
2642
|
create(context) {
|
|
2628
2643
|
const filename = context.filename;
|
|
2629
2644
|
const sourceRoot = sourceRootOf(context);
|
|
2630
|
-
const relative =
|
|
2645
|
+
const relative = path22.relative(sourceRoot, filename);
|
|
2631
2646
|
if (relative.startsWith("..")) return {};
|
|
2632
|
-
const segments = relative.split(
|
|
2647
|
+
const segments = relative.split(path22.sep);
|
|
2633
2648
|
const sourceText = context.sourceCode.text;
|
|
2634
2649
|
function checkHook(node, name, body, exported) {
|
|
2635
2650
|
if (!exported) return;
|
|
@@ -2671,9 +2686,9 @@ var hookComplexityRule = {
|
|
|
2671
2686
|
};
|
|
2672
2687
|
|
|
2673
2688
|
// eslint/rules/locale-dotted-path.ts
|
|
2674
|
-
import
|
|
2689
|
+
import path23 from "path";
|
|
2675
2690
|
function isInLocalesDir(filename) {
|
|
2676
|
-
const segments =
|
|
2691
|
+
const segments = path23.resolve(filename).split(path23.sep);
|
|
2677
2692
|
const srcIdx = segments.lastIndexOf("src");
|
|
2678
2693
|
return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
|
|
2679
2694
|
}
|
|
@@ -2722,9 +2737,9 @@ var localeDottedPathRule = {
|
|
|
2722
2737
|
};
|
|
2723
2738
|
|
|
2724
2739
|
// eslint/rules/locales-location.ts
|
|
2725
|
-
import
|
|
2740
|
+
import path24 from "path";
|
|
2726
2741
|
function isLocalesFile(filename) {
|
|
2727
|
-
const segments =
|
|
2742
|
+
const segments = path24.resolve(filename).split(path24.sep);
|
|
2728
2743
|
const srcIdx = segments.lastIndexOf("src");
|
|
2729
2744
|
return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
|
|
2730
2745
|
}
|
|
@@ -2743,7 +2758,7 @@ var localesLocationRule = {
|
|
|
2743
2758
|
create(context) {
|
|
2744
2759
|
if (isLocalesFile(context.filename)) return {};
|
|
2745
2760
|
const filename = context.filename;
|
|
2746
|
-
const segments =
|
|
2761
|
+
const segments = path24.resolve(filename).split(path24.sep);
|
|
2747
2762
|
const srcIdx = segments.lastIndexOf("src");
|
|
2748
2763
|
if (srcIdx === -1) return {};
|
|
2749
2764
|
const folder = segments[srcIdx + 1];
|
|
@@ -2765,7 +2780,7 @@ var localesLocationRule = {
|
|
|
2765
2780
|
};
|
|
2766
2781
|
|
|
2767
2782
|
// eslint/rules/hook-extraction.ts
|
|
2768
|
-
import
|
|
2783
|
+
import path25 from "path";
|
|
2769
2784
|
var hookExtractionRule = {
|
|
2770
2785
|
meta: {
|
|
2771
2786
|
schema: [],
|
|
@@ -2776,7 +2791,7 @@ var hookExtractionRule = {
|
|
|
2776
2791
|
},
|
|
2777
2792
|
create(context) {
|
|
2778
2793
|
const sourceRoot = sourceRootOf(context);
|
|
2779
|
-
const file =
|
|
2794
|
+
const file = path25.resolve(context.filename);
|
|
2780
2795
|
const segments = segmentsOf(file, sourceRoot);
|
|
2781
2796
|
if (segments.length === 0) return {};
|
|
2782
2797
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -2802,7 +2817,7 @@ var hookExtractionRule = {
|
|
|
2802
2817
|
};
|
|
2803
2818
|
|
|
2804
2819
|
// eslint/rules/value-extraction.ts
|
|
2805
|
-
import
|
|
2820
|
+
import path26 from "path";
|
|
2806
2821
|
var valueExtractionRule = {
|
|
2807
2822
|
meta: {
|
|
2808
2823
|
schema: [],
|
|
@@ -2813,7 +2828,7 @@ var valueExtractionRule = {
|
|
|
2813
2828
|
},
|
|
2814
2829
|
create(context) {
|
|
2815
2830
|
const sourceRoot = sourceRootOf(context);
|
|
2816
|
-
const file =
|
|
2831
|
+
const file = path26.resolve(context.filename);
|
|
2817
2832
|
const segments = segmentsOf(file, sourceRoot);
|
|
2818
2833
|
if (segments.length === 0 || segments[0] !== "app") return {};
|
|
2819
2834
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -2834,7 +2849,7 @@ var valueExtractionRule = {
|
|
|
2834
2849
|
};
|
|
2835
2850
|
|
|
2836
2851
|
// eslint/rules/config-extraction.ts
|
|
2837
|
-
import
|
|
2852
|
+
import path27 from "path";
|
|
2838
2853
|
var configExtractionRule = {
|
|
2839
2854
|
meta: {
|
|
2840
2855
|
schema: [],
|
|
@@ -2845,7 +2860,7 @@ var configExtractionRule = {
|
|
|
2845
2860
|
},
|
|
2846
2861
|
create(context) {
|
|
2847
2862
|
const sourceRoot = sourceRootOf(context);
|
|
2848
|
-
const file =
|
|
2863
|
+
const file = path27.resolve(context.filename);
|
|
2849
2864
|
const segments = segmentsOf(file, sourceRoot);
|
|
2850
2865
|
if (segments.length < 3 || segments[0] !== "config") return {};
|
|
2851
2866
|
if (SUPPORT_FOLDERS2.has(segments[2] ?? "")) return {};
|
|
@@ -2883,7 +2898,7 @@ var configExtractionRule = {
|
|
|
2883
2898
|
};
|
|
2884
2899
|
|
|
2885
2900
|
// eslint/rules/component-nesting.ts
|
|
2886
|
-
import
|
|
2901
|
+
import path28 from "path";
|
|
2887
2902
|
var componentNestingRule = {
|
|
2888
2903
|
meta: {
|
|
2889
2904
|
schema: [],
|
|
@@ -2894,7 +2909,7 @@ var componentNestingRule = {
|
|
|
2894
2909
|
},
|
|
2895
2910
|
create(context) {
|
|
2896
2911
|
const sourceRoot = sourceRootOf(context);
|
|
2897
|
-
const file =
|
|
2912
|
+
const file = path28.resolve(context.filename);
|
|
2898
2913
|
const segments = segmentsOf(file, sourceRoot);
|
|
2899
2914
|
if (segments.length !== 4 || segments[0] !== "features") return {};
|
|
2900
2915
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -2927,7 +2942,7 @@ var componentNestingRule = {
|
|
|
2927
2942
|
};
|
|
2928
2943
|
|
|
2929
2944
|
// eslint/rules/stay-flat.ts
|
|
2930
|
-
import
|
|
2945
|
+
import path29 from "path";
|
|
2931
2946
|
var stayFlatRule = {
|
|
2932
2947
|
meta: {
|
|
2933
2948
|
schema: [],
|
|
@@ -2938,7 +2953,7 @@ var stayFlatRule = {
|
|
|
2938
2953
|
},
|
|
2939
2954
|
create(context) {
|
|
2940
2955
|
const sourceRoot = sourceRootOf(context);
|
|
2941
|
-
const file =
|
|
2956
|
+
const file = path29.resolve(context.filename);
|
|
2942
2957
|
const segments = segmentsOf(file, sourceRoot);
|
|
2943
2958
|
if (segments.length !== 3 || segments[0] !== "features") return {};
|
|
2944
2959
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -2978,7 +2993,7 @@ var stayFlatRule = {
|
|
|
2978
2993
|
};
|
|
2979
2994
|
|
|
2980
2995
|
// eslint/rules/type-extraction.ts
|
|
2981
|
-
import
|
|
2996
|
+
import path30 from "path";
|
|
2982
2997
|
var typeExtractionRule = {
|
|
2983
2998
|
meta: {
|
|
2984
2999
|
schema: [],
|
|
@@ -2989,7 +3004,7 @@ var typeExtractionRule = {
|
|
|
2989
3004
|
},
|
|
2990
3005
|
create(context) {
|
|
2991
3006
|
const sourceRoot = sourceRootOf(context);
|
|
2992
|
-
const file =
|
|
3007
|
+
const file = path30.resolve(context.filename);
|
|
2993
3008
|
const segments = segmentsOf(file, sourceRoot);
|
|
2994
3009
|
if (segments.length === 0) return {};
|
|
2995
3010
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -3035,7 +3050,7 @@ var typeExtractionRule = {
|
|
|
3035
3050
|
};
|
|
3036
3051
|
|
|
3037
3052
|
// eslint/rules/locale-placement.ts
|
|
3038
|
-
import
|
|
3053
|
+
import path31 from "path";
|
|
3039
3054
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3040
3055
|
import ts5 from "typescript";
|
|
3041
3056
|
var LOCALE_ACCESS = /\blocales\.(?<key>[A-Za-z_$][\w$]*)/g;
|
|
@@ -3083,7 +3098,7 @@ var localePlacementRule = {
|
|
|
3083
3098
|
},
|
|
3084
3099
|
create(context) {
|
|
3085
3100
|
const sourceRoot = sourceRootOf(context);
|
|
3086
|
-
const file =
|
|
3101
|
+
const file = path31.resolve(context.filename);
|
|
3087
3102
|
const segments = segmentsOf(file, sourceRoot);
|
|
3088
3103
|
if (segments.length === 0) return {};
|
|
3089
3104
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -3161,7 +3176,7 @@ var localePlacementRule = {
|
|
|
3161
3176
|
};
|
|
3162
3177
|
|
|
3163
3178
|
// eslint/rules/sole-state-owner.ts
|
|
3164
|
-
import
|
|
3179
|
+
import path32 from "path";
|
|
3165
3180
|
import ts6 from "typescript";
|
|
3166
3181
|
function findStateHooks(node) {
|
|
3167
3182
|
const hooks = [];
|
|
@@ -3241,7 +3256,7 @@ var soleStateOwnerRule = {
|
|
|
3241
3256
|
}
|
|
3242
3257
|
},
|
|
3243
3258
|
create(context) {
|
|
3244
|
-
const filename =
|
|
3259
|
+
const filename = path32.resolve(context.filename);
|
|
3245
3260
|
if (!filename.endsWith(".tsx") && !filename.endsWith(".jsx")) return {};
|
|
3246
3261
|
const text = context.sourceCode.text;
|
|
3247
3262
|
const components = parseComponentInfo(text, filename);
|
|
@@ -3320,7 +3335,7 @@ function usesOutsideJsx(declaration, hook, children) {
|
|
|
3320
3335
|
}
|
|
3321
3336
|
|
|
3322
3337
|
// eslint/rules/locale-key-shape.ts
|
|
3323
|
-
import
|
|
3338
|
+
import path33 from "path";
|
|
3324
3339
|
var MAX_KEY_LENGTH = 30;
|
|
3325
3340
|
var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
|
|
3326
3341
|
"Button",
|
|
@@ -3370,7 +3385,7 @@ var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
|
|
|
3370
3385
|
var CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
|
|
3371
3386
|
var ENGLISH = /^[A-Za-z0-9_]*$/;
|
|
3372
3387
|
function isLocalesFile2(filename) {
|
|
3373
|
-
const segments =
|
|
3388
|
+
const segments = path33.resolve(filename).split(path33.sep);
|
|
3374
3389
|
const srcIdx = segments.lastIndexOf("src");
|
|
3375
3390
|
return srcIdx !== -1 && segments[srcIdx + 1] === "locales";
|
|
3376
3391
|
}
|
|
@@ -3441,7 +3456,7 @@ var localeKeyShapeRule = {
|
|
|
3441
3456
|
};
|
|
3442
3457
|
|
|
3443
3458
|
// eslint/rules/shared-style-dedup.ts
|
|
3444
|
-
import
|
|
3459
|
+
import path34 from "path";
|
|
3445
3460
|
import { readFileSync as readFileSync4, statSync as statSync3 } from "fs";
|
|
3446
3461
|
var CLASS_NAME = /className="(?<classes>[^"]+)"/g;
|
|
3447
3462
|
var comboCache;
|
|
@@ -3483,7 +3498,7 @@ var sharedStyleDedupRule = {
|
|
|
3483
3498
|
},
|
|
3484
3499
|
create(context) {
|
|
3485
3500
|
const sourceRoot = sourceRootOf(context);
|
|
3486
|
-
const file =
|
|
3501
|
+
const file = path34.resolve(context.filename);
|
|
3487
3502
|
const segments = segmentsOf(file, sourceRoot);
|
|
3488
3503
|
if (segments.length === 0) return {};
|
|
3489
3504
|
const index = getProjectIndex(sourceRoot);
|
|
@@ -3687,7 +3702,7 @@ var zodSchemaValidationRule = {
|
|
|
3687
3702
|
};
|
|
3688
3703
|
|
|
3689
3704
|
// eslint/rules/source-under-src.ts
|
|
3690
|
-
import
|
|
3705
|
+
import path35 from "path";
|
|
3691
3706
|
var NON_SOURCE_ROOT_DIRS = /* @__PURE__ */ new Set([
|
|
3692
3707
|
".agents",
|
|
3693
3708
|
".cache",
|
|
@@ -3728,14 +3743,14 @@ var sourceUnderSrcRule = {
|
|
|
3728
3743
|
}
|
|
3729
3744
|
},
|
|
3730
3745
|
create(context) {
|
|
3731
|
-
const filename =
|
|
3746
|
+
const filename = path35.resolve(context.filename);
|
|
3732
3747
|
if (!MODULE_EXTENSION.test(filename)) return {};
|
|
3733
|
-
const relative =
|
|
3748
|
+
const relative = path35.relative(context.cwd, filename).replace(/\\/g, "/");
|
|
3734
3749
|
if (relative === "src" || relative.startsWith("src/")) return {};
|
|
3735
3750
|
const topLevel = relative.split("/")[0] ?? "";
|
|
3736
3751
|
if (NON_SOURCE_ROOT_DIRS.has(topLevel)) return {};
|
|
3737
3752
|
if (!relative.includes("/")) {
|
|
3738
|
-
const basename =
|
|
3753
|
+
const basename = path35.basename(filename);
|
|
3739
3754
|
if (CONFIG_FILE.test(basename) || DECLARATION_FILE.test(basename) || basename.startsWith(".")) return {};
|
|
3740
3755
|
}
|
|
3741
3756
|
return {
|
|
@@ -3752,7 +3767,7 @@ var sourceUnderSrcRule = {
|
|
|
3752
3767
|
|
|
3753
3768
|
// eslint/rules/zirka-baseline.ts
|
|
3754
3769
|
import fs4 from "fs";
|
|
3755
|
-
import
|
|
3770
|
+
import path36 from "path";
|
|
3756
3771
|
var ESLINT_CONFIG = /^eslint\.config\.(?:ts|mts|cts|js|mjs|cjs)$/;
|
|
3757
3772
|
var PRETTIER_CONFIGS = [
|
|
3758
3773
|
"prettier.config.mjs",
|
|
@@ -3771,10 +3786,10 @@ var zirkaBaselineRule = {
|
|
|
3771
3786
|
}
|
|
3772
3787
|
},
|
|
3773
3788
|
create(context) {
|
|
3774
|
-
const filename =
|
|
3775
|
-
const basename =
|
|
3789
|
+
const filename = path36.resolve(context.filename);
|
|
3790
|
+
const basename = path36.basename(filename);
|
|
3776
3791
|
if (!ESLINT_CONFIG.test(basename)) return {};
|
|
3777
|
-
const projectRoot =
|
|
3792
|
+
const projectRoot = path36.dirname(filename);
|
|
3778
3793
|
const report3 = (message) => {
|
|
3779
3794
|
context.report({
|
|
3780
3795
|
node: context.sourceCode.ast,
|
|
@@ -3789,7 +3804,7 @@ var zirkaBaselineRule = {
|
|
|
3789
3804
|
'ESLint config must take its configuration from zirka (import { styleguide } from "zirka") instead of restating rules locally.'
|
|
3790
3805
|
);
|
|
3791
3806
|
}
|
|
3792
|
-
const tsconfigPath =
|
|
3807
|
+
const tsconfigPath = path36.join(projectRoot, "tsconfig.json");
|
|
3793
3808
|
if (!fs4.existsSync(tsconfigPath)) {
|
|
3794
3809
|
report3('No tsconfig.json found. Create one extending the zirka TypeScript base config ("zirka/typescript").');
|
|
3795
3810
|
} else {
|
|
@@ -3807,13 +3822,13 @@ var zirkaBaselineRule = {
|
|
|
3807
3822
|
report3('tsconfig.json must extend the zirka TypeScript base config ("zirka/typescript").');
|
|
3808
3823
|
}
|
|
3809
3824
|
}
|
|
3810
|
-
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs4.existsSync(
|
|
3825
|
+
const prettierConfigFile = PRETTIER_CONFIGS.find((name) => fs4.existsSync(path36.join(projectRoot, name)));
|
|
3811
3826
|
if (!prettierConfigFile) {
|
|
3812
3827
|
report3(
|
|
3813
3828
|
"No prettier config found. Create one that takes its configuration from zirka (styleguide({ prettier: true }).prettierConfig)."
|
|
3814
3829
|
);
|
|
3815
3830
|
} else {
|
|
3816
|
-
const content = fs4.readFileSync(
|
|
3831
|
+
const content = fs4.readFileSync(path36.join(projectRoot, prettierConfigFile), "utf8");
|
|
3817
3832
|
if (!content.includes("zirka")) {
|
|
3818
3833
|
report3(
|
|
3819
3834
|
"The prettier config must take its configuration from zirka (styleguide({ prettier: true }).prettierConfig) instead of restating it locally."
|
|
@@ -3883,7 +3898,7 @@ var docKindSuffixRule = {
|
|
|
3883
3898
|
};
|
|
3884
3899
|
|
|
3885
3900
|
// eslint/rules/documentation/title-matches-file-name.ts
|
|
3886
|
-
import
|
|
3901
|
+
import path37 from "path";
|
|
3887
3902
|
function toExpectedFileName(title) {
|
|
3888
3903
|
return `${title.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}.md`;
|
|
3889
3904
|
}
|
|
@@ -3903,7 +3918,7 @@ var titleMatchesFileNameRule = {
|
|
|
3903
3918
|
if (!filename.endsWith(".md")) return;
|
|
3904
3919
|
const title = getTextContent(node).trim();
|
|
3905
3920
|
const expectedFileName = toExpectedFileName(title);
|
|
3906
|
-
const actualFileName =
|
|
3921
|
+
const actualFileName = path37.basename(filename);
|
|
3907
3922
|
if (!title) {
|
|
3908
3923
|
context.report({
|
|
3909
3924
|
node,
|
|
@@ -4310,7 +4325,7 @@ var referenceBlockHeadingsRule = {
|
|
|
4310
4325
|
};
|
|
4311
4326
|
|
|
4312
4327
|
// eslint/rules/documentation/support-document-placement.ts
|
|
4313
|
-
import
|
|
4328
|
+
import path38 from "path";
|
|
4314
4329
|
var supportDocumentPlacementRule = {
|
|
4315
4330
|
meta: {
|
|
4316
4331
|
type: "problem",
|
|
@@ -4324,7 +4339,7 @@ var supportDocumentPlacementRule = {
|
|
|
4324
4339
|
root(node) {
|
|
4325
4340
|
const filename = getFilename(context);
|
|
4326
4341
|
if (!filename.endsWith(".md")) return;
|
|
4327
|
-
const parentFolder =
|
|
4342
|
+
const parentFolder = path38.basename(path38.dirname(filename));
|
|
4328
4343
|
if (filename.endsWith("-rule.md") && parentFolder !== "rules") {
|
|
4329
4344
|
context.report({
|
|
4330
4345
|
node,
|
|
@@ -4367,11 +4382,11 @@ var noTemplatePromptRule = {
|
|
|
4367
4382
|
};
|
|
4368
4383
|
|
|
4369
4384
|
// eslint/rules/documentation/guide-folder-entry-point.ts
|
|
4370
|
-
import
|
|
4385
|
+
import path40 from "path";
|
|
4371
4386
|
|
|
4372
4387
|
// eslint/rules/documentation/project-index.ts
|
|
4373
4388
|
import { readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
|
|
4374
|
-
import
|
|
4389
|
+
import path39 from "path";
|
|
4375
4390
|
var KIND_BY_SUFFIX = [
|
|
4376
4391
|
["-rule.md", "rule"],
|
|
4377
4392
|
["-guide.md", "guide"],
|
|
@@ -4380,7 +4395,7 @@ var KIND_BY_SUFFIX = [
|
|
|
4380
4395
|
];
|
|
4381
4396
|
function listMarkdownFiles(dir) {
|
|
4382
4397
|
return readdirSync3(dir).flatMap((entry) => {
|
|
4383
|
-
const entryPath =
|
|
4398
|
+
const entryPath = path39.join(dir, entry);
|
|
4384
4399
|
if (statSync4(entryPath).isDirectory()) {
|
|
4385
4400
|
return entry.startsWith("_") ? [] : listMarkdownFiles(entryPath);
|
|
4386
4401
|
}
|
|
@@ -4398,11 +4413,11 @@ function getProjectDocs(docsRoot) {
|
|
|
4398
4413
|
if (cached) return cached;
|
|
4399
4414
|
const files = listMarkdownFiles(docsRoot);
|
|
4400
4415
|
const docs = files.sort((a, b) => a.localeCompare(b)).map((filePath) => {
|
|
4401
|
-
const fileName =
|
|
4416
|
+
const fileName = path39.basename(filePath);
|
|
4402
4417
|
const kind = KIND_BY_SUFFIX.find(([suffix]) => fileName.endsWith(suffix))?.[1];
|
|
4403
4418
|
return {
|
|
4404
4419
|
filePath,
|
|
4405
|
-
doc:
|
|
4420
|
+
doc: path39.relative(docsRoot, filePath).split(path39.sep).join("/"),
|
|
4406
4421
|
fileName,
|
|
4407
4422
|
kind,
|
|
4408
4423
|
title: extractTitle(filePath)
|
|
@@ -4412,12 +4427,12 @@ function getProjectDocs(docsRoot) {
|
|
|
4412
4427
|
return docs;
|
|
4413
4428
|
}
|
|
4414
4429
|
function findDocsRoot(filePath) {
|
|
4415
|
-
let dir =
|
|
4430
|
+
let dir = path39.dirname(filePath);
|
|
4416
4431
|
for (; ; ) {
|
|
4417
|
-
if (
|
|
4432
|
+
if (path39.basename(dir) === "docs" && statSync4(dir).isDirectory()) {
|
|
4418
4433
|
return dir;
|
|
4419
4434
|
}
|
|
4420
|
-
const parent =
|
|
4435
|
+
const parent = path39.dirname(dir);
|
|
4421
4436
|
if (parent === dir) return void 0;
|
|
4422
4437
|
dir = parent;
|
|
4423
4438
|
}
|
|
@@ -4441,13 +4456,13 @@ var guideFolderEntryPointRule = {
|
|
|
4441
4456
|
if (!docsRoot) return;
|
|
4442
4457
|
const docs = getProjectDocs(docsRoot);
|
|
4443
4458
|
const guideFolders = new Set(
|
|
4444
|
-
docs.filter((doc) => ["rules", "references"].includes(
|
|
4459
|
+
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
4460
|
);
|
|
4446
|
-
const currentDir =
|
|
4461
|
+
const currentDir = path40.dirname(filename);
|
|
4447
4462
|
if (guideFolders.has(currentDir)) {
|
|
4448
|
-
const expectedEntryPoint = `${
|
|
4463
|
+
const expectedEntryPoint = `${path40.basename(currentDir)}.md`;
|
|
4449
4464
|
const hasEntryPoint = docs.some(
|
|
4450
|
-
(doc) => doc.kind === "guide" &&
|
|
4465
|
+
(doc) => doc.kind === "guide" && path40.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
|
|
4451
4466
|
);
|
|
4452
4467
|
if (!hasEntryPoint) {
|
|
4453
4468
|
context.report({
|
|
@@ -4672,7 +4687,7 @@ var noNestedHowToRule = {
|
|
|
4672
4687
|
|
|
4673
4688
|
// eslint/rules/documentation/glossary-term-linking.ts
|
|
4674
4689
|
import { readFileSync as readFileSync6 } from "fs";
|
|
4675
|
-
import
|
|
4690
|
+
import path41 from "path";
|
|
4676
4691
|
function extractGlossaryTerms(filePath) {
|
|
4677
4692
|
const content = readFileSync6(filePath, "utf8");
|
|
4678
4693
|
const terms = [];
|
|
@@ -4726,9 +4741,9 @@ var glossaryTermLinkingRule = {
|
|
|
4726
4741
|
const docsRoot = findDocsRoot(filename);
|
|
4727
4742
|
if (!docsRoot) return;
|
|
4728
4743
|
const docs = getProjectDocs(docsRoot);
|
|
4729
|
-
const guideDir =
|
|
4744
|
+
const guideDir = path41.dirname(filename);
|
|
4730
4745
|
const guideReferences = docs.filter(
|
|
4731
|
-
(doc) => doc.kind === "reference" &&
|
|
4746
|
+
(doc) => doc.kind === "reference" && path41.dirname(doc.filePath) === guideDir
|
|
4732
4747
|
);
|
|
4733
4748
|
if (guideReferences.length === 0) return;
|
|
4734
4749
|
const glossaryTerms = [];
|
|
@@ -4753,7 +4768,7 @@ var glossaryTermLinkingRule = {
|
|
|
4753
4768
|
|
|
4754
4769
|
// eslint/rules/documentation/guide-mentions-documents.ts
|
|
4755
4770
|
import { existsSync } from "fs";
|
|
4756
|
-
import
|
|
4771
|
+
import path42 from "path";
|
|
4757
4772
|
function visitSteps3(node, check) {
|
|
4758
4773
|
if (node.type === "list" && node.ordered) {
|
|
4759
4774
|
for (const child of node.children) check(child);
|
|
@@ -4786,12 +4801,12 @@ var guideMentionsDocumentsRule = {
|
|
|
4786
4801
|
if (!filename.endsWith("-guide.md")) return;
|
|
4787
4802
|
const docsRoot = findDocsRoot(filename);
|
|
4788
4803
|
if (!docsRoot) return;
|
|
4789
|
-
const guideDir =
|
|
4790
|
-
if (
|
|
4804
|
+
const guideDir = path42.dirname(filename);
|
|
4805
|
+
if (path42.basename(filename, ".md") !== path42.basename(guideDir)) return;
|
|
4791
4806
|
const docs = getProjectDocs(docsRoot);
|
|
4792
4807
|
const owned = docs.filter((doc) => {
|
|
4793
|
-
const parent =
|
|
4794
|
-
return parent ===
|
|
4808
|
+
const parent = path42.dirname(doc.filePath);
|
|
4809
|
+
return parent === path42.join(guideDir, "rules") || parent === path42.join(guideDir, "references");
|
|
4795
4810
|
});
|
|
4796
4811
|
const allLinks = [];
|
|
4797
4812
|
collectMarkdownLinks(node, allLinks);
|
|
@@ -4818,7 +4833,7 @@ var guideMentionsDocumentsRule = {
|
|
|
4818
4833
|
for (const link of allLinks) {
|
|
4819
4834
|
const target = linkTarget(link.url);
|
|
4820
4835
|
if (!target.endsWith(".md")) continue;
|
|
4821
|
-
const resolved =
|
|
4836
|
+
const resolved = path42.normalize(path42.join(guideDir, target));
|
|
4822
4837
|
if (!existsSync(resolved)) {
|
|
4823
4838
|
context.report({
|
|
4824
4839
|
node: link,
|
|
@@ -4916,6 +4931,12 @@ function selectorNames(node) {
|
|
|
4916
4931
|
}
|
|
4917
4932
|
|
|
4918
4933
|
// eslint/rules/tailwind/theme-reset.ts
|
|
4934
|
+
function isThemeReset(node) {
|
|
4935
|
+
if (!node) return false;
|
|
4936
|
+
if (node.type === "Declaration") return node.property.startsWith("--*");
|
|
4937
|
+
if (node.type === "Raw") return node.value.includes("--*: initial");
|
|
4938
|
+
return false;
|
|
4939
|
+
}
|
|
4919
4940
|
var themeResetRule = {
|
|
4920
4941
|
meta: {
|
|
4921
4942
|
schema: [],
|
|
@@ -4927,13 +4948,16 @@ var themeResetRule = {
|
|
|
4927
4948
|
create(context) {
|
|
4928
4949
|
return {
|
|
4929
4950
|
"StyleSheet:exit"(node) {
|
|
4930
|
-
const resetFound = atrulesNamed(node, "theme").some(
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4951
|
+
const resetFound = atrulesNamed(node, "theme").some((theme) => {
|
|
4952
|
+
const direct = blockChildren2(theme).some(isThemeReset);
|
|
4953
|
+
if (direct) return true;
|
|
4954
|
+
let nested = false;
|
|
4955
|
+
walkNodes(theme, (current) => {
|
|
4956
|
+
if (nested) return;
|
|
4957
|
+
if (isThemeReset(current)) nested = true;
|
|
4958
|
+
});
|
|
4959
|
+
return nested;
|
|
4960
|
+
});
|
|
4937
4961
|
if (!resetFound) {
|
|
4938
4962
|
context.report({
|
|
4939
4963
|
node,
|
|
@@ -5261,11 +5285,11 @@ var themeVariableNamespaceRule = {
|
|
|
5261
5285
|
|
|
5262
5286
|
// eslint/rules/tailwind/css-entry-point.ts
|
|
5263
5287
|
import { statSync as statSync6 } from "fs";
|
|
5264
|
-
import
|
|
5288
|
+
import path45 from "path";
|
|
5265
5289
|
|
|
5266
5290
|
// eslint/rules/tailwind/source-files.ts
|
|
5267
5291
|
import { readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
|
|
5268
|
-
import
|
|
5292
|
+
import path43 from "path";
|
|
5269
5293
|
var CSS_EXTENSIONS = [".css"];
|
|
5270
5294
|
var MODULE_EXTENSIONS3 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
5271
5295
|
var SOURCE_EXTENSIONS = [...MODULE_EXTENSIONS3, ...CSS_EXTENSIONS];
|
|
@@ -5278,7 +5302,7 @@ function findFiles(dir, extensions) {
|
|
|
5278
5302
|
}
|
|
5279
5303
|
return entries.flatMap((entry) => {
|
|
5280
5304
|
if (entry.startsWith(".") || entry === "node_modules") return [];
|
|
5281
|
-
const entryPath =
|
|
5305
|
+
const entryPath = path43.join(dir, entry);
|
|
5282
5306
|
let stats;
|
|
5283
5307
|
try {
|
|
5284
5308
|
stats = statSync5(entryPath);
|
|
@@ -5286,7 +5310,7 @@ function findFiles(dir, extensions) {
|
|
|
5286
5310
|
return [];
|
|
5287
5311
|
}
|
|
5288
5312
|
if (stats.isDirectory()) return findFiles(entryPath, extensions);
|
|
5289
|
-
return extensions.includes(
|
|
5313
|
+
return extensions.includes(path43.extname(entry)) ? [entryPath] : [];
|
|
5290
5314
|
});
|
|
5291
5315
|
}
|
|
5292
5316
|
function cachedTextReader() {
|
|
@@ -5309,7 +5333,7 @@ function escapeRegExp(text) {
|
|
|
5309
5333
|
}
|
|
5310
5334
|
|
|
5311
5335
|
// eslint/rules/tailwind/stylesheet-graph.ts
|
|
5312
|
-
import
|
|
5336
|
+
import path44 from "path";
|
|
5313
5337
|
function registersTailwind(text) {
|
|
5314
5338
|
return /@import\s+(?:url\(\s*)?["']tailwindcss["']\s*\)?/i.test(text);
|
|
5315
5339
|
}
|
|
@@ -5323,25 +5347,25 @@ function moduleImports(text, fileName) {
|
|
|
5323
5347
|
return new RegExp(`(?:import|require)\\s*\\(?\\s*["'][^"']*${escaped}["']`, "i").test(text);
|
|
5324
5348
|
}
|
|
5325
5349
|
function resolveSpecifier2(fromFile, spec, sourceRoot) {
|
|
5326
|
-
if (spec.startsWith("/")) return
|
|
5327
|
-
if (spec.startsWith("./") || spec.startsWith("../")) return
|
|
5328
|
-
if (spec.startsWith("@/")) return
|
|
5350
|
+
if (spec.startsWith("/")) return path44.resolve(spec);
|
|
5351
|
+
if (spec.startsWith("./") || spec.startsWith("../")) return path44.resolve(path44.dirname(fromFile), spec);
|
|
5352
|
+
if (spec.startsWith("@/")) return path44.resolve(sourceRoot, spec.slice(2));
|
|
5329
5353
|
return void 0;
|
|
5330
5354
|
}
|
|
5331
5355
|
function buildStylesheetGraph(options) {
|
|
5332
5356
|
const { cssFiles, sourceRoot, textOf } = options;
|
|
5333
|
-
const cssSet = new Set(cssFiles.map((file) =>
|
|
5357
|
+
const cssSet = new Set(cssFiles.map((file) => path44.normalize(file)));
|
|
5334
5358
|
const globals = cssFiles.filter((file) => registersTailwind(textOf(file)));
|
|
5335
5359
|
const reachable = /* @__PURE__ */ new Set();
|
|
5336
5360
|
const queue = [...globals];
|
|
5337
|
-
for (const global of globals) reachable.add(
|
|
5361
|
+
for (const global of globals) reachable.add(path44.normalize(global));
|
|
5338
5362
|
while (queue.length > 0) {
|
|
5339
5363
|
const from = queue.shift();
|
|
5340
5364
|
if (!from) continue;
|
|
5341
5365
|
for (const spec of importedSpecifiers(textOf(from))) {
|
|
5342
5366
|
const target = resolveSpecifier2(from, spec, sourceRoot);
|
|
5343
5367
|
if (!target) continue;
|
|
5344
|
-
const normalized =
|
|
5368
|
+
const normalized = path44.normalize(target);
|
|
5345
5369
|
if (cssSet.has(normalized) && !reachable.has(normalized)) {
|
|
5346
5370
|
reachable.add(normalized);
|
|
5347
5371
|
queue.push(normalized);
|
|
@@ -5353,7 +5377,7 @@ function buildStylesheetGraph(options) {
|
|
|
5353
5377
|
for (const spec of importedSpecifiers(textOf(global))) {
|
|
5354
5378
|
const target = resolveSpecifier2(global, spec, sourceRoot);
|
|
5355
5379
|
if (!target) continue;
|
|
5356
|
-
const normalized =
|
|
5380
|
+
const normalized = path44.normalize(target);
|
|
5357
5381
|
if (cssSet.has(normalized)) directChildren.add(normalized);
|
|
5358
5382
|
}
|
|
5359
5383
|
}
|
|
@@ -5386,7 +5410,7 @@ var cssEntryPointRule = {
|
|
|
5386
5410
|
return {
|
|
5387
5411
|
"StyleSheet:exit"(node) {
|
|
5388
5412
|
if (globals.length === 0) return;
|
|
5389
|
-
const current =
|
|
5413
|
+
const current = path45.normalize(path45.resolve(context.filename));
|
|
5390
5414
|
if (globals.includes(current)) {
|
|
5391
5415
|
if (globals.length > 1) {
|
|
5392
5416
|
context.report({
|
|
@@ -5395,7 +5419,7 @@ var cssEntryPointRule = {
|
|
|
5395
5419
|
});
|
|
5396
5420
|
return;
|
|
5397
5421
|
}
|
|
5398
|
-
const basename =
|
|
5422
|
+
const basename = path45.basename(current);
|
|
5399
5423
|
const importCount = moduleFiles.filter((modulePath) => moduleImports(textOf(modulePath), basename)).length;
|
|
5400
5424
|
if (importCount !== 1) {
|
|
5401
5425
|
context.report({
|
|
@@ -5664,7 +5688,7 @@ var nextjsPackageJsonRules = {
|
|
|
5664
5688
|
|
|
5665
5689
|
// eslint/rules/husky/husky-hook.ts
|
|
5666
5690
|
import { existsSync as existsSync2, readFileSync as readFileSync8 } from "fs";
|
|
5667
|
-
import
|
|
5691
|
+
import path46 from "path";
|
|
5668
5692
|
function memberName4(member) {
|
|
5669
5693
|
return member.name.type === "String" ? member.name.value : member.name.name;
|
|
5670
5694
|
}
|
|
@@ -5683,7 +5707,7 @@ var huskyHookRule = {
|
|
|
5683
5707
|
if (root.type !== "Object") return;
|
|
5684
5708
|
const scriptName = context.filename;
|
|
5685
5709
|
if (!scriptName.endsWith("package.json")) return;
|
|
5686
|
-
const hookPath =
|
|
5710
|
+
const hookPath = path46.join(context.cwd, ".husky", "pre-commit");
|
|
5687
5711
|
if (!existsSync2(hookPath)) {
|
|
5688
5712
|
context.report({
|
|
5689
5713
|
node,
|
|
@@ -5723,7 +5747,7 @@ var huskyRules = {
|
|
|
5723
5747
|
|
|
5724
5748
|
// eslint/rules/vulyk/vulyk-docs.ts
|
|
5725
5749
|
import { existsSync as existsSync3, readFileSync as readFileSync9 } from "fs";
|
|
5726
|
-
import
|
|
5750
|
+
import path47 from "path";
|
|
5727
5751
|
var PASIKA_REPO = "Bredansky/pasika";
|
|
5728
5752
|
var BASE_REQUIRED_DOCS = [
|
|
5729
5753
|
{ name: "documentation-guide", path: "docs/documentation-guide" },
|
|
@@ -5756,8 +5780,8 @@ var vulykDocsRule = {
|
|
|
5756
5780
|
if (!context.filename.endsWith("package.json")) return;
|
|
5757
5781
|
const root = node.body;
|
|
5758
5782
|
if (root.type !== "Object") return;
|
|
5759
|
-
const projectRoot =
|
|
5760
|
-
const configPath =
|
|
5783
|
+
const projectRoot = path47.dirname(path47.resolve(context.filename));
|
|
5784
|
+
const configPath = path47.join(projectRoot, "vulyk.config.ts");
|
|
5761
5785
|
if (!existsSync3(configPath)) {
|
|
5762
5786
|
context.report({
|
|
5763
5787
|
node,
|
|
@@ -5782,7 +5806,7 @@ var vulykDocsRule = {
|
|
|
5782
5806
|
});
|
|
5783
5807
|
}
|
|
5784
5808
|
}
|
|
5785
|
-
const agentsPath =
|
|
5809
|
+
const agentsPath = path47.join(projectRoot, "AGENTS.md");
|
|
5786
5810
|
if (!existsSync3(agentsPath)) {
|
|
5787
5811
|
context.report({
|
|
5788
5812
|
node,
|