pasika 0.4.2 → 0.4.3

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.
@@ -66,11 +66,12 @@ function componentFromVariable(node) {
66
66
  smart: containsSmartCall(initializer)
67
67
  };
68
68
  }
69
- function parseComponentInfo(text, filename) {
69
+ function parseComponentInfo(text, filename, options) {
70
70
  const sourceFile = ts.createSourceFile(path.resolve(filename), text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
71
71
  const components = [];
72
72
  for (const statement of sourceFile.statements) {
73
- if (!isExported(statement)) continue;
73
+ const exported = isExported(statement);
74
+ if (!exported && !options?.includeNonExported) continue;
74
75
  if (ts.isFunctionDeclaration(statement)) {
75
76
  const component = componentFromFunction(statement);
76
77
  if (component) components.push(component);
@@ -350,59 +351,26 @@ var importBoundariesRule = {
350
351
  };
351
352
 
352
353
  // eslint/rules/no-mixed-concerns.ts
353
- function getExportName(declaration) {
354
- if (declaration?.type === "FunctionDeclaration" && declaration.id) {
355
- return declaration.id.name ?? null;
356
- }
357
- if (declaration?.type === "VariableDeclaration") {
358
- const declarator = declaration.declarations?.[0];
359
- if (declarator?.id?.type === "Identifier" && (declarator.init?.type === "ArrowFunctionExpression" || declarator.init?.type === "FunctionExpression")) {
360
- return declarator.id.name ?? null;
361
- }
362
- }
363
- if (declaration?.type === "ArrowFunctionExpression") {
364
- return "default";
365
- }
366
- if (declaration?.type === "FunctionExpression" && declaration.id) {
367
- return declaration.id.name ?? null;
368
- }
369
- return null;
370
- }
371
354
  var noMixedConcernsRule = {
372
355
  meta: {
373
356
  schema: [],
374
357
  type: "problem",
375
358
  docs: {
376
- description: "Enforce one exported React component per .tsx file."
359
+ description: "Enforce one React component per .tsx file, counting private components."
377
360
  }
378
361
  },
379
362
  create(context) {
380
363
  if (!context.filename.endsWith(".tsx")) return {};
381
- let exportedComponentCount = 0;
382
- const extraExports = [];
383
- function registerExport(name) {
384
- exportedComponentCount++;
385
- if (exportedComponentCount > 1) {
386
- extraExports.push({ name });
387
- }
388
- }
364
+ const sourceCode = context.sourceCode.text;
389
365
  return {
390
- ExportNamedDeclaration(node) {
391
- const name = getExportName(node.declaration);
392
- if (name) registerExport(name);
393
- },
394
- ExportDefaultDeclaration(node) {
395
- const name = getExportName(node.declaration);
396
- if (name) registerExport(name);
397
- },
398
366
  "Program:exit"() {
399
- if (exportedComponentCount > 1) {
400
- for (const extra of extraExports) {
401
- context.report({
402
- loc: { line: 1, column: 0 },
403
- message: `File exports multiple components. "${extra.name}" is an extra component export. Move it to its own file. Each .tsx file MUST contain exactly one component. See docs/code-organization-guide/rules/no-mixed-concerns-rule.md`
404
- });
405
- }
367
+ const components = parseComponentInfo(sourceCode, context.filename, { includeNonExported: true });
368
+ if (components.length <= 1) return;
369
+ for (const extra of components.slice(1)) {
370
+ context.report({
371
+ loc: { line: 1, column: 0 },
372
+ message: `File defines multiple components. "${extra.name}" is an extra component. Move it to its own file. Each component file MUST define exactly one component. See docs/code-organization-guide/rules/no-mixed-concerns-rule.md`
373
+ });
406
374
  }
407
375
  }
408
376
  };
@@ -885,7 +853,9 @@ function isOuterLayoutClass(className) {
885
853
  function stringArguments(node) {
886
854
  if (node?.type === "Literal" && typeof node.value === "string") return [node.value];
887
855
  if (node?.type === "TemplateLiteral") return node.quasis.map((quasi) => quasi.value.raw);
888
- if (node?.type === "ConditionalExpression") return [...stringArguments(node.consequent), ...stringArguments(node.alternate)];
856
+ if (node?.type === "ConditionalExpression") {
857
+ return [...stringArguments(node.consequent), ...stringArguments(node.alternate)];
858
+ }
889
859
  if (node?.type === "LogicalExpression") return [...stringArguments(node.left), ...stringArguments(node.right)];
890
860
  if (node?.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "cn") {
891
861
  return node.arguments.flatMap((argument) => stringArguments(argument));
@@ -901,7 +871,10 @@ var enforceCnMergeRule = {
901
871
  const element = node.parent.parent;
902
872
  const isComponentProp = isComponentName(element.openingElement?.name);
903
873
  if (isComponentProp && attributeName !== "className" && attributeName.endsWith("ClassName")) {
904
- context.report({ node, message: "Expose appearance through typed variant props instead of separate internal class-name props. See docs/styling-guide/rules/class-composition-rule.md" });
874
+ context.report({
875
+ node,
876
+ message: "Expose appearance through typed variant props instead of separate internal class-name props. See docs/styling-guide/rules/class-composition-rule.md"
877
+ });
905
878
  return;
906
879
  }
907
880
  if (attributeName !== "className" && attributeName !== "class") return;
@@ -910,31 +883,60 @@ var enforceCnMergeRule = {
910
883
  if (isComponentProp && attributeName === "className") {
911
884
  const expression = valueNode.type === "JSXExpressionContainer" ? valueNode.expression : valueNode;
912
885
  const invalidClass = stringArguments(expression).flatMap((value) => value.split(/\s+/).filter(Boolean)).find((className) => !isOuterLayoutClass(className));
913
- if (invalidClass) context.report({ node, message: `Passed className contains non-layout utility "${invalidClass}". Expose appearance through typed variant props. See docs/styling-guide/rules/class-composition-rule.md` });
886
+ if (invalidClass) {
887
+ context.report({
888
+ node,
889
+ message: `Passed className contains non-layout utility "${invalidClass}". Expose appearance through typed variant props. See docs/styling-guide/rules/class-composition-rule.md`
890
+ });
891
+ }
914
892
  return;
915
893
  }
916
894
  if (valueNode.type === "Literal" && typeof valueNode.value === "string") {
917
- if (classCount(valueNode.value) > 5) context.report({ node, message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/styling-guide/rules/class-composition-rule.md" });
895
+ if (classCount(valueNode.value) > 5) {
896
+ context.report({
897
+ node,
898
+ message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/styling-guide/rules/class-composition-rule.md"
899
+ });
900
+ }
918
901
  return;
919
902
  }
920
903
  if (valueNode.type !== "JSXExpressionContainer") return;
921
904
  const expr = valueNode.expression;
922
905
  if (expr.type === "BinaryExpression" && expr.operator === "+") {
923
- context.report({ node, message: "Use cn() instead of + operator for className. See docs/styling-guide/rules/class-composition-rule.md" });
906
+ context.report({
907
+ node,
908
+ message: "Use cn() instead of + operator for className. See docs/styling-guide/rules/class-composition-rule.md"
909
+ });
924
910
  return;
925
911
  }
926
912
  if (expr.type === "TemplateLiteral" && expr.expressions.length > 0) {
927
- context.report({ node, message: "Use cn() instead of template literals with conditionals for className. See docs/styling-guide/rules/class-composition-rule.md" });
913
+ context.report({
914
+ node,
915
+ message: "Use cn() instead of template literals with conditionals for className. See docs/styling-guide/rules/class-composition-rule.md"
916
+ });
917
+ return;
918
+ }
919
+ if (expr.type === "LogicalExpression" || expr.type === "ConditionalExpression") {
920
+ context.report({
921
+ node,
922
+ message: "Use cn() for conditional classes in className. See docs/styling-guide/rules/class-composition-rule.md"
923
+ });
928
924
  return;
929
925
  }
930
926
  if (expr.type === "Literal" && typeof expr.value === "string" && classCount(expr.value) > 5) {
931
- context.report({ node, message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/styling-guide/rules/class-composition-rule.md" });
927
+ context.report({
928
+ node,
929
+ message: "Static className with more than 5 classes must use cn() with grouped string literals. See docs/styling-guide/rules/class-composition-rule.md"
930
+ });
932
931
  return;
933
932
  }
934
933
  if (expr.type === "CallExpression" && expr.callee.type === "Identifier" && expr.callee.name === "cn") {
935
934
  for (const arg of expr.arguments) {
936
935
  if (arg.type === "Literal" && typeof arg.value === "string" && classCount(arg.value) > 5) {
937
- context.report({ node: arg, message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/styling-guide/rules/class-composition-rule.md" });
936
+ context.report({
937
+ node: arg,
938
+ message: "Each cn() string argument must contain at most 5 class names. Group by styling concern. See docs/styling-guide/rules/class-composition-rule.md"
939
+ });
938
940
  }
939
941
  }
940
942
  }
@@ -3284,6 +3286,7 @@ var ROLE_POSTFIXES = /* @__PURE__ */ new Set([
3284
3286
  "ScrollBar"
3285
3287
  ]);
3286
3288
  var CAMEL_CASE = /^[a-z][a-zA-Z0-9]*$/;
3289
+ var ENGLISH = /^[A-Za-z0-9_]*$/;
3287
3290
  function isLocalesFile2(filename) {
3288
3291
  const segments = path31.resolve(filename).split(path31.sep);
3289
3292
  const srcIdx = segments.lastIndexOf("src");
@@ -3298,6 +3301,14 @@ function reportFor(context, node, message) {
3298
3301
  context.report({ node, message });
3299
3302
  }
3300
3303
  function checkKey(context, node, name) {
3304
+ if (!ENGLISH.test(name)) {
3305
+ reportFor(
3306
+ context,
3307
+ node,
3308
+ `Locale key "${name}" must be English; write it in the Latin alphabet. See docs/code-organization-guide/rules/locales-rule.md`
3309
+ );
3310
+ return;
3311
+ }
3301
3312
  if (!CAMEL_CASE.test(name)) {
3302
3313
  reportFor(
3303
3314
  context,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",