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.
@@ -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 isComponentProp = isComponentName(element.openingElement?.name);
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
- return `${String(files.length)}:${String(total)}`;
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 resolveSpecifier(fromFile, specifier, sourceRoot) {
1328
- let base;
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
- function build(sourceRoot, files) {
1350
- const modules = /* @__PURE__ */ new Map();
1351
- const consumers = /* @__PURE__ */ new Map();
1352
- const symbolConsumers = /* @__PURE__ */ new Map();
1353
- for (const file of files) {
1354
- try {
1355
- modules.set(file, parseModule(file));
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
- for (const [file, module] of modules) {
1360
- for (const moduleImport of module.imports) {
1361
- const target = resolveSpecifier(file, moduleImport.specifier, sourceRoot);
1362
- if (!target || !modules.has(target)) continue;
1363
- const fileConsumers = consumers.get(target) ?? /* @__PURE__ */ new Set();
1364
- fileConsumers.add(file);
1365
- consumers.set(target, fileConsumers);
1366
- for (const name of moduleImport.names) {
1367
- const key = symbolKey(target, name);
1368
- const nameConsumers = symbolConsumers.get(key) ?? /* @__PURE__ */ new Set();
1369
- nameConsumers.add(file);
1370
- symbolConsumers.set(key, nameConsumers);
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
- const index = build(sourceRoot, files);
1394
- cache = { index, checkedAt: now, fingerprint: currentFingerprint };
1395
- return index;
1396
- }
1408
+ };
1409
+
1410
+ // eslint/rules/component-placement.ts
1411
+ import path11 from "path";
1397
1412
 
1398
1413
  // eslint/project/ccf.ts
1399
- import path9 from "path";
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 = path9.relative(sourceRoot, file);
1403
- return relative.startsWith("..") ? [] : relative.split(path9.sep);
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) => path9.relative(path9.dirname(sourceRoot), consumer).split(path9.sep).join("/")).sort((left, right) => left.localeCompare(right));
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 = path10.resolve(filename);
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 path11 from "path";
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 = path11.resolve(context.filename);
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 path12 from "path";
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(path12.extname(filename));
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 path12.join(sourceRoot, "config", segments[1] ?? "");
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 = path12.join(sourceRoot, ...segments.slice(0, depth + 1));
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(path12.join(folderPath, `${folder}.tsx`))) {
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(path12.join(folderPath, "index.ts"))) {
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 = path12.resolve(context.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(path12.join(moduleRoot, "index.ts"))) {
1715
+ if (moduleRoot && !fs2.existsSync(path13.join(moduleRoot, "index.ts"))) {
1701
1716
  return report2(
1702
1717
  context,
1703
- `Add src/config/${path12.basename(moduleRoot)}/index.ts as the configuration module entry point.`
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 && path12.basename(filename) !== "index.ts") {
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/${path12.basename(moduleRoot)}/${expected2}/.`
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 = path12.basename(filename, path12.extname(filename));
1719
- const currentFolder2 = path12.basename(path12.dirname(filename));
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) && path12.extname(filename) !== ".css") {
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 = path12.basename(path12.dirname(filename));
1748
+ const currentFolder = path13.basename(path13.dirname(filename));
1734
1749
  const kinds = exportedKinds(filename);
1735
- const isConfigModuleRoot = topLevel === "config" && segments.length === 3 && path12.basename(filename) === "index.ts";
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 ${path12.basename(filename)} beside ${currentFolder}/.`
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 path13 from "path";
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(path13.sep, "/");
1806
+ const normalized = filename.replaceAll(path14.sep, "/");
1792
1807
  if (!normalized.includes("/src/app/")) return false;
1793
- const basename = path13.basename(filename, path13.extname(filename));
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 path14 from "path";
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 = path14.resolve(context.filename);
1857
+ const filename = path15.resolve(context.filename);
1843
1858
  if (!filename.endsWith(".tsx")) return {};
1844
- const base = path14.basename(filename, path14.extname(filename));
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 path15 from "path";
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 = path15.resolve(context.filename);
1899
- const baseName = path15.basename(filename);
1913
+ const filename = path16.resolve(context.filename);
1914
+ const baseName = path16.basename(filename);
1900
1915
  if (!INDEX_NAMES.has(baseName)) return {};
1901
- const folder = path15.basename(path15.dirname(filename));
1916
+ const folder = path16.basename(path16.dirname(filename));
1902
1917
  if (!SUPPORT_FOLDERS3.has(folder)) return {};
1903
- const directory = path15.dirname(filename);
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(path15.basename(specifier));
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 path16 from "path";
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 = path16.resolve(context.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 || path16.basename(target).startsWith("index.")) continue;
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 = `${path16.sep}src${path16.sep}`;
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 path16.resolve(context.cwd ?? process.cwd(), "src");
2000
+ return path17.resolve(context.cwd ?? process.cwd(), "src");
1986
2001
  }
1987
2002
 
1988
2003
  // eslint/rules/util-file-name.ts
1989
- import path17 from "path";
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 = path17.resolve(context.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 = path17.basename(filename, path17.extname(filename));
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}.${path17.extname(filename).slice(1)}.`
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 path18 from "path";
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 = path18.resolve(context.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 || !path18.basename(target).startsWith("index.")) continue;
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 = `${path18.sep}src${path18.sep}`;
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 path18.resolve(context.cwd ?? process.cwd(), "src");
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 path19 from "path";
2463
+ import path20 from "path";
2449
2464
  var FEATURES_SEGMENT = "features";
2450
2465
  function featureNameOf(resolvedPath, sourceRoot) {
2451
- const relative = path19.relative(sourceRoot, resolvedPath);
2466
+ const relative = path20.relative(sourceRoot, resolvedPath);
2452
2467
  if (relative.startsWith("..")) return void 0;
2453
- const segments = relative.split(path19.sep);
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 = path19.relative(sourceRoot, filename);
2484
+ const fileRelative = path20.relative(sourceRoot, filename);
2470
2485
  if (fileRelative.startsWith("..")) return {};
2471
- const fileSegments = fileRelative.split(path19.sep);
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 = path19.resolve(sourceRoot, source.value.slice(2));
2500
+ resolved = path20.resolve(sourceRoot, source.value.slice(2));
2486
2501
  } else if (source.value.startsWith(".")) {
2487
- resolved = path19.resolve(path19.dirname(filename), source.value);
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 path20 from "path";
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 = path20.relative(sourceRoot, filename);
2550
+ const relative = path21.relative(sourceRoot, filename);
2536
2551
  if (relative.startsWith("..")) return {};
2537
- const segments = relative.split(path20.sep);
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 path21 from "path";
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 = path21.relative(sourceRoot, filename);
2645
+ const relative = path22.relative(sourceRoot, filename);
2631
2646
  if (relative.startsWith("..")) return {};
2632
- const segments = relative.split(path21.sep);
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 path22 from "path";
2689
+ import path23 from "path";
2675
2690
  function isInLocalesDir(filename) {
2676
- const segments = path22.resolve(filename).split(path22.sep);
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 path23 from "path";
2740
+ import path24 from "path";
2726
2741
  function isLocalesFile(filename) {
2727
- const segments = path23.resolve(filename).split(path23.sep);
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 = path23.resolve(filename).split(path23.sep);
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 path24 from "path";
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 = path24.resolve(context.filename);
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 path25 from "path";
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 = path25.resolve(context.filename);
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 path26 from "path";
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 = path26.resolve(context.filename);
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 path27 from "path";
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 = path27.resolve(context.filename);
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 path28 from "path";
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 = path28.resolve(context.filename);
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 path29 from "path";
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 = path29.resolve(context.filename);
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 path30 from "path";
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 = path30.resolve(context.filename);
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 path31 from "path";
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 = path31.resolve(context.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 path32 from "path";
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 = path32.resolve(filename).split(path32.sep);
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 path33 from "path";
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 = path33.resolve(context.filename);
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 path34 from "path";
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 = path34.resolve(context.filename);
3746
+ const filename = path35.resolve(context.filename);
3732
3747
  if (!MODULE_EXTENSION.test(filename)) return {};
3733
- const relative = path34.relative(context.cwd, filename).replace(/\\/g, "/");
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 = path34.basename(filename);
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 path35 from "path";
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 = path35.resolve(context.filename);
3775
- const basename = path35.basename(filename);
3789
+ const filename = path36.resolve(context.filename);
3790
+ const basename = path36.basename(filename);
3776
3791
  if (!ESLINT_CONFIG.test(basename)) return {};
3777
- const projectRoot = path35.dirname(filename);
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 = path35.join(projectRoot, "tsconfig.json");
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(path35.join(projectRoot, name)));
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(path35.join(projectRoot, prettierConfigFile), "utf8");
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 path36 from "path";
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 = path36.basename(filename);
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 path37 from "path";
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 = path37.basename(path37.dirname(filename));
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 path39 from "path";
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 path38 from "path";
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 = path38.join(dir, entry);
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 = path38.basename(filePath);
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: path38.relative(docsRoot, filePath).split(path38.sep).join("/"),
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 = path38.dirname(filePath);
4430
+ let dir = path39.dirname(filePath);
4416
4431
  for (; ; ) {
4417
- if (path38.basename(dir) === "docs" && statSync4(dir).isDirectory()) {
4432
+ if (path39.basename(dir) === "docs" && statSync4(dir).isDirectory()) {
4418
4433
  return dir;
4419
4434
  }
4420
- const parent = path38.dirname(dir);
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(path39.basename(path39.dirname(doc.filePath)))).map((doc) => path39.dirname(path39.dirname(doc.filePath))).filter((folder) => path39.resolve(folder) !== path39.resolve(docsRoot))
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 = path39.dirname(filename);
4461
+ const currentDir = path40.dirname(filename);
4447
4462
  if (guideFolders.has(currentDir)) {
4448
- const expectedEntryPoint = `${path39.basename(currentDir)}.md`;
4463
+ const expectedEntryPoint = `${path40.basename(currentDir)}.md`;
4449
4464
  const hasEntryPoint = docs.some(
4450
- (doc) => doc.kind === "guide" && path39.dirname(doc.filePath) === currentDir && doc.fileName === expectedEntryPoint
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 path40 from "path";
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 = path40.dirname(filename);
4744
+ const guideDir = path41.dirname(filename);
4730
4745
  const guideReferences = docs.filter(
4731
- (doc) => doc.kind === "reference" && path40.dirname(doc.filePath) === guideDir
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 path41 from "path";
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 = path41.dirname(filename);
4790
- if (path41.basename(filename, ".md") !== path41.basename(guideDir)) return;
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 = path41.dirname(doc.filePath);
4794
- return parent === path41.join(guideDir, "rules") || parent === path41.join(guideDir, "references");
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 = path41.normalize(path41.join(guideDir, target));
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
- (theme) => blockChildren2(theme).some((child) => {
4932
- if (child.type === "Declaration") return child.property.startsWith("--*");
4933
- if (child.type === "Raw") return child.value.includes("--*: initial");
4934
- return false;
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 path44 from "path";
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 path42 from "path";
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 = path42.join(dir, entry);
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(path42.extname(entry)) ? [entryPath] : [];
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 path43 from "path";
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 path43.resolve(spec);
5327
- if (spec.startsWith("./") || spec.startsWith("../")) return path43.resolve(path43.dirname(fromFile), spec);
5328
- if (spec.startsWith("@/")) return path43.resolve(sourceRoot, spec.slice(2));
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) => path43.normalize(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(path43.normalize(global));
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 = path43.normalize(target);
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 = path43.normalize(target);
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 = path44.normalize(path44.resolve(context.filename));
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 = path44.basename(current);
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 path45 from "path";
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 = path45.join(context.cwd, ".husky", "pre-commit");
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 path46 from "path";
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 = path46.dirname(path46.resolve(context.filename));
5760
- const configPath = path46.join(projectRoot, "vulyk.config.ts");
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 = path46.join(projectRoot, "AGENTS.md");
5809
+ const agentsPath = path47.join(projectRoot, "AGENTS.md");
5786
5810
  if (!existsSync3(agentsPath)) {
5787
5811
  context.report({
5788
5812
  node,