pasika 0.10.82 → 0.10.84
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.d.ts +1 -0
- package/dist/eslint/pasika/index.js +102 -16
- package/package.json +1 -1
|
@@ -1218,6 +1218,8 @@ function isNestedInside(expectedFolder, currentFolder, componentFile) {
|
|
|
1218
1218
|
if (!sameFolder(currentFolder.slice(0, -1), expectedFolder)) return false;
|
|
1219
1219
|
const folderName = currentFolder[currentFolder.length - 1];
|
|
1220
1220
|
if (!folderName) return false;
|
|
1221
|
+
const componentName = path10.basename(componentFile, path10.extname(componentFile));
|
|
1222
|
+
if (componentName !== folderName) return false;
|
|
1221
1223
|
return fs3.existsSync(path10.join(path10.dirname(componentFile), `${folderName}.tsx`));
|
|
1222
1224
|
}
|
|
1223
1225
|
var componentPlacementRule = {
|
|
@@ -2937,7 +2939,13 @@ function parentComponentName(dirPath, folderName) {
|
|
|
2937
2939
|
if (!fs4.existsSync(componentFile)) return void 0;
|
|
2938
2940
|
try {
|
|
2939
2941
|
const exports = parseModule(componentFile).exports;
|
|
2940
|
-
|
|
2942
|
+
const classifiedComponent = exports.find((moduleExport) => moduleExport.kind === "component")?.name;
|
|
2943
|
+
if (classifiedComponent) return classifiedComponent;
|
|
2944
|
+
const normalizedFolderName = folderName.replaceAll("-", "").toLowerCase();
|
|
2945
|
+
const ownerExport = exports.find(
|
|
2946
|
+
(moduleExport) => isPascalCase4(moduleExport.name) && moduleExport.name.toLowerCase() === normalizedFolderName
|
|
2947
|
+
);
|
|
2948
|
+
return ownerExport?.name;
|
|
2941
2949
|
} catch {
|
|
2942
2950
|
return void 0;
|
|
2943
2951
|
}
|
|
@@ -2987,7 +2995,7 @@ var enforceBarrelExportsRule = {
|
|
|
2987
2995
|
if (nonParentExports.length > 0) {
|
|
2988
2996
|
context.report({
|
|
2989
2997
|
loc: { line: 1, column: 0 },
|
|
2990
|
-
message: `index.ts must not re-export
|
|
2998
|
+
message: `index.ts must not re-export nested internals: ${nonParentExports.join(", ")}. Only "${parentName}" may be re-exported. See docs/next-codebase-guide/rules/folder-nesting-rule.md`
|
|
2991
2999
|
});
|
|
2992
3000
|
}
|
|
2993
3001
|
}
|
|
@@ -3021,6 +3029,31 @@ function stringArguments(node) {
|
|
|
3021
3029
|
}
|
|
3022
3030
|
return [];
|
|
3023
3031
|
}
|
|
3032
|
+
function staticClassLiterals(node) {
|
|
3033
|
+
if (!node) return [];
|
|
3034
|
+
if (node.type === "Literal" && typeof node.value === "string") return [node];
|
|
3035
|
+
if (node.type === "CallExpression") {
|
|
3036
|
+
if (node.callee.type === "Identifier" && node.callee.name === "cn") return [];
|
|
3037
|
+
return node.arguments.flatMap(
|
|
3038
|
+
(argument) => argument.type === "SpreadElement" ? [] : staticClassLiterals(argument)
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
if (node.type === "ObjectExpression") {
|
|
3042
|
+
return node.properties.flatMap(
|
|
3043
|
+
(property) => property.type === "Property" ? staticClassLiterals(property.value) : []
|
|
3044
|
+
);
|
|
3045
|
+
}
|
|
3046
|
+
if (node.type === "ArrayExpression") {
|
|
3047
|
+
return node.elements.flatMap((element) => element?.type === "SpreadElement" ? [] : staticClassLiterals(element));
|
|
3048
|
+
}
|
|
3049
|
+
if (node.type === "ConditionalExpression") {
|
|
3050
|
+
return [...staticClassLiterals(node.consequent), ...staticClassLiterals(node.alternate)];
|
|
3051
|
+
}
|
|
3052
|
+
if (node.type === "LogicalExpression") {
|
|
3053
|
+
return [...staticClassLiterals(node.left), ...staticClassLiterals(node.right)];
|
|
3054
|
+
}
|
|
3055
|
+
return [];
|
|
3056
|
+
}
|
|
3024
3057
|
var enforceCnMergeRule = {
|
|
3025
3058
|
meta: { schema: [], type: "problem", docs: { description: "Enforce cn() for conditional class merging." } },
|
|
3026
3059
|
create(context) {
|
|
@@ -3034,6 +3067,32 @@ var enforceCnMergeRule = {
|
|
|
3034
3067
|
}
|
|
3035
3068
|
}
|
|
3036
3069
|
return {
|
|
3070
|
+
CallExpression(node) {
|
|
3071
|
+
if (node.callee.type !== "Identifier") return;
|
|
3072
|
+
if (node.callee.name === "cn") {
|
|
3073
|
+
for (const argument of node.arguments) {
|
|
3074
|
+
if (argument.type !== "Literal" || typeof argument.value !== "string" || classCount(argument.value) <= 5) {
|
|
3075
|
+
continue;
|
|
3076
|
+
}
|
|
3077
|
+
context.report({
|
|
3078
|
+
node: argument,
|
|
3079
|
+
message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
3080
|
+
});
|
|
3081
|
+
}
|
|
3082
|
+
return;
|
|
3083
|
+
}
|
|
3084
|
+
if (node.callee.name !== "cva") return;
|
|
3085
|
+
for (const argument of node.arguments) {
|
|
3086
|
+
if (argument.type === "SpreadElement") continue;
|
|
3087
|
+
for (const literal of staticClassLiterals(argument)) {
|
|
3088
|
+
if (typeof literal.value !== "string" || classCount(literal.value) <= 5) continue;
|
|
3089
|
+
context.report({
|
|
3090
|
+
node: literal,
|
|
3091
|
+
message: "Static cva class list with more than 5 classes must use cn() with grouped string literals. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
},
|
|
3037
3096
|
JSXAttribute(node) {
|
|
3038
3097
|
const attributeName = node.name?.name ?? "";
|
|
3039
3098
|
const element = node.parent.parent;
|
|
@@ -3099,17 +3158,6 @@ var enforceCnMergeRule = {
|
|
|
3099
3158
|
node,
|
|
3100
3159
|
message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
3101
3160
|
});
|
|
3102
|
-
return;
|
|
3103
|
-
}
|
|
3104
|
-
if (expr.type === "CallExpression" && expr.callee.type === "Identifier" && expr.callee.name === "cn") {
|
|
3105
|
-
for (const arg of expr.arguments) {
|
|
3106
|
-
if (arg.type === "Literal" && typeof arg.value === "string" && classCount(arg.value) > 5) {
|
|
3107
|
-
context.report({
|
|
3108
|
-
node: arg,
|
|
3109
|
-
message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/next-tailwind-guide/rules/class-composition-rule.md"
|
|
3110
|
-
});
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
3161
|
}
|
|
3114
3162
|
}
|
|
3115
3163
|
};
|
|
@@ -3812,6 +3860,24 @@ function sourceSegments(sourceRoot, absolutePath) {
|
|
|
3812
3860
|
}
|
|
3813
3861
|
return relativePath.split(path31.sep);
|
|
3814
3862
|
}
|
|
3863
|
+
function isWithin(root, candidate) {
|
|
3864
|
+
const relativePath = path31.relative(root, candidate);
|
|
3865
|
+
return relativePath === "" || !relativePath.startsWith("..") && !path31.isAbsolute(relativePath);
|
|
3866
|
+
}
|
|
3867
|
+
function componentFolderAncestors(targetFile, sourceRoot) {
|
|
3868
|
+
const folders = [];
|
|
3869
|
+
let current = path31.dirname(targetFile);
|
|
3870
|
+
while (current !== sourceRoot && isWithin(sourceRoot, current)) {
|
|
3871
|
+
const folderName = path31.basename(current);
|
|
3872
|
+
if (hasComponentOwner(current, folderName) && hasExactEntry(current, "index.ts")) {
|
|
3873
|
+
folders.push(current);
|
|
3874
|
+
}
|
|
3875
|
+
const parent = path31.dirname(current);
|
|
3876
|
+
if (parent === current) break;
|
|
3877
|
+
current = parent;
|
|
3878
|
+
}
|
|
3879
|
+
return folders;
|
|
3880
|
+
}
|
|
3815
3881
|
function relativeSpecifier(filename, resolvedPath) {
|
|
3816
3882
|
const relativePath = path31.relative(path31.dirname(filename), resolvedPath).split(path31.sep).join("/");
|
|
3817
3883
|
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
@@ -3841,6 +3907,26 @@ var importBoundariesRule = {
|
|
|
3841
3907
|
return;
|
|
3842
3908
|
}
|
|
3843
3909
|
const importPath = source.value;
|
|
3910
|
+
const resolvedModule = resolveSpecifier(filename, importPath, sourceRoot);
|
|
3911
|
+
if (resolvedModule) {
|
|
3912
|
+
for (const componentFolder of componentFolderAncestors(resolvedModule, sourceRoot)) {
|
|
3913
|
+
if (isWithin(componentFolder, filename)) continue;
|
|
3914
|
+
const componentEntry = path31.join(componentFolder, "index.ts");
|
|
3915
|
+
if (path31.resolve(resolvedModule) === path31.resolve(componentEntry)) continue;
|
|
3916
|
+
const entrySpecifier = prefersRelative(filename, componentFolder) ? relativeSpecifier(filename, componentFolder) : aliasSpecifier(sourceRoot, componentFolder);
|
|
3917
|
+
const folderLabel = `src/${path31.relative(sourceRoot, componentFolder).split(path31.sep).join("/")}/`;
|
|
3918
|
+
const message = [
|
|
3919
|
+
`Do not import "${importPath}" across the ${folderLabel} component boundary;`,
|
|
3920
|
+
`outside consumers may import only "${entrySpecifier}".`,
|
|
3921
|
+
"Move nested internals to their CCF when they need reuse."
|
|
3922
|
+
].join(" ");
|
|
3923
|
+
context.report({
|
|
3924
|
+
node: source,
|
|
3925
|
+
message
|
|
3926
|
+
});
|
|
3927
|
+
return;
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3844
3930
|
const resolvedPath = resolveSourceImport(sourceRoot, filename, importPath);
|
|
3845
3931
|
if (!resolvedPath) {
|
|
3846
3932
|
return;
|
|
@@ -5055,7 +5141,7 @@ var ownershipIndexCache = /* @__PURE__ */ new WeakMap();
|
|
|
5055
5141
|
function normalizePath(value) {
|
|
5056
5142
|
return value.replaceAll("\\", "/").toLowerCase();
|
|
5057
5143
|
}
|
|
5058
|
-
function
|
|
5144
|
+
function isWithin2(root, file) {
|
|
5059
5145
|
const relative = path39.relative(root, file);
|
|
5060
5146
|
return relative === "" || !relative.startsWith("..") && !path39.isAbsolute(relative);
|
|
5061
5147
|
}
|
|
@@ -5197,7 +5283,7 @@ var ContractOwnershipIndex = class {
|
|
|
5197
5283
|
const normalized = normalizePath(fileName);
|
|
5198
5284
|
if (/\/typescript\/lib\/lib\.[^/]+\.d\.ts$/u.test(normalized)) return "platform";
|
|
5199
5285
|
if (normalized.includes("/node_modules/")) return "third-party";
|
|
5200
|
-
if (
|
|
5286
|
+
if (isWithin2(this.cwd, path39.resolve(fileName))) return "first-party";
|
|
5201
5287
|
return "unknown";
|
|
5202
5288
|
}
|
|
5203
5289
|
schemaOwnership(declaration) {
|
|
@@ -5211,7 +5297,7 @@ var ContractOwnershipIndex = class {
|
|
|
5211
5297
|
}
|
|
5212
5298
|
indexApiContracts() {
|
|
5213
5299
|
for (const sourceFile of this.program.getSourceFiles()) {
|
|
5214
|
-
if (sourceFile.isDeclarationFile || !
|
|
5300
|
+
if (sourceFile.isDeclarationFile || !isWithin2(this.cwd, path39.resolve(sourceFile.fileName))) continue;
|
|
5215
5301
|
const visit = (node) => {
|
|
5216
5302
|
if (ts7.isCallExpression(node) && this.isDefineApiContractCall(node)) this.indexApiContractCall(node);
|
|
5217
5303
|
ts7.forEachChild(node, visit);
|