pasika 0.10.28 → 0.10.30

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.
@@ -3981,6 +3981,61 @@ function looksLikeLocaleKey(name) {
3981
3981
  function looksLikeUserFacingString(value) {
3982
3982
  return typeof value === "string" && /^\p{Lu}/u.test(value);
3983
3983
  }
3984
+ function looksLikeUserFacingJsxText(value) {
3985
+ return typeof value === "string" && /\p{L}/u.test(value);
3986
+ }
3987
+ var USER_FACING_PROPERTY_NAMES = /* @__PURE__ */ new Set([
3988
+ "alt",
3989
+ "aria-label",
3990
+ "cancelText",
3991
+ "children",
3992
+ "confirmText",
3993
+ "description",
3994
+ "emptyText",
3995
+ "errorMessage",
3996
+ "helperText",
3997
+ "label",
3998
+ "placeholder",
3999
+ "submitText",
4000
+ "successMessage",
4001
+ "title"
4002
+ ]);
4003
+ var USER_FACING_VARIABLE_SUFFIX_RE = /(?:Description|Label|Message|Text|Title)$/u;
4004
+ var TOAST_METHOD_NAMES = /* @__PURE__ */ new Set(["error", "info", "success", "warning"]);
4005
+ function getNodeName(node) {
4006
+ if (!node) return null;
4007
+ if (node.type === "Identifier") return node.name;
4008
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
4009
+ return null;
4010
+ }
4011
+ function containsUserFacingString(node) {
4012
+ if (!node) return false;
4013
+ if (node.type === "Literal") return looksLikeUserFacingJsxText(node.value);
4014
+ if (node.type === "TemplateLiteral") {
4015
+ return node.quasis.some((quasi) => looksLikeUserFacingJsxText(quasi.value.cooked ?? quasi.value.raw));
4016
+ }
4017
+ if (node.type === "ConditionalExpression") {
4018
+ return containsUserFacingString(node.consequent) || containsUserFacingString(node.alternate);
4019
+ }
4020
+ if (node.type === "LogicalExpression") {
4021
+ return containsUserFacingString(node.left) || containsUserFacingString(node.right);
4022
+ }
4023
+ if (node.type === "BinaryExpression") {
4024
+ return node.operator === "+" && (containsUserFacingString(node.left) || containsUserFacingString(node.right));
4025
+ }
4026
+ return false;
4027
+ }
4028
+ function isUserFacingVariable(node) {
4029
+ const name = getNodeName(node);
4030
+ return name !== null && USER_FACING_VARIABLE_SUFFIX_RE.test(name);
4031
+ }
4032
+ function objectContainsUserFacingProperties(node) {
4033
+ return node.properties.some((property) => {
4034
+ if (property.type !== "Property") return false;
4035
+ const name = getNodeName(property.key);
4036
+ return name !== null && USER_FACING_PROPERTY_NAMES.has(name) && containsUserFacingString(property.value);
4037
+ });
4038
+ }
3984
4039
  var localesLocationRule = {
3985
4040
  meta: {
3986
4041
  schema: [],
@@ -3996,9 +4051,52 @@ var localesLocationRule = {
3996
4051
  const srcIdx = segments.lastIndexOf("src");
3997
4052
  if (srcIdx === -1) return {};
3998
4053
  const folder = segments[srcIdx + 1];
3999
- if (folder === "app" || folder === "config") return {};
4054
+ const skipObjectLiteralCheck = folder === "app" || folder === "config";
4000
4055
  return {
4056
+ JSXText(node) {
4057
+ if (!looksLikeUserFacingJsxText(node.value)) return;
4058
+ context.report({
4059
+ node,
4060
+ message: "User-facing JSX text must come from src/locales/index.ts, not be written inline."
4061
+ });
4062
+ },
4063
+ JSXAttribute(node) {
4064
+ const name = node.name?.name;
4065
+ if (typeof name !== "string" || !USER_FACING_PROPERTY_NAMES.has(name)) return;
4066
+ const value = node.value;
4067
+ if (!value) return;
4068
+ const hasUserFacingString = value.type === "JSXExpressionContainer" ? containsUserFacingString(value.expression) : looksLikeUserFacingJsxText(value.value);
4069
+ if (!hasUserFacingString) return;
4070
+ context.report({
4071
+ node,
4072
+ message: "User-facing JSX attribute text must come from src/locales/index.ts, not be written inline."
4073
+ });
4074
+ },
4075
+ "JSXElement > JSXExpressionContainer, JSXFragment > JSXExpressionContainer"(node) {
4076
+ if (!containsUserFacingString(node.expression)) return;
4077
+ context.report({
4078
+ node,
4079
+ message: "User-facing JSX expression text must come from src/locales/index.ts, not be written inline."
4080
+ });
4081
+ },
4082
+ ObjectExpression(node) {
4083
+ if (skipObjectLiteralCheck || node.parent.type === "VariableDeclarator" || !objectContainsUserFacingProperties(node)) {
4084
+ return;
4085
+ }
4086
+ context.report({
4087
+ node,
4088
+ message: "User-facing object properties must come from src/locales/index.ts, not be written inline."
4089
+ });
4090
+ },
4001
4091
  VariableDeclarator(node) {
4092
+ if (node.id.type === "Identifier" && isUserFacingVariable(node.id) && containsUserFacingString(node.init)) {
4093
+ context.report({
4094
+ node,
4095
+ message: "User-facing variable text must come from src/locales/index.ts, not be written inline."
4096
+ });
4097
+ return;
4098
+ }
4099
+ if (skipObjectLiteralCheck) return;
4002
4100
  if (node.id.type === "Identifier" && node.init?.type === "ObjectExpression" && node.init.properties.length > 0 && looksLikeLocaleKey(node.id.name)) {
4003
4101
  const hasUserFacingStringValues = node.init.properties.some(
4004
4102
  (p) => p.type === "Property" && p.value.type === "Literal" && looksLikeUserFacingString(p.value.value)
@@ -4010,6 +4108,24 @@ var localesLocationRule = {
4010
4108
  });
4011
4109
  }
4012
4110
  }
4111
+ },
4112
+ AssignmentExpression(node) {
4113
+ if (!isUserFacingVariable(node.left) || !containsUserFacingString(node.right)) return;
4114
+ context.report({
4115
+ node,
4116
+ message: "User-facing variable text must come from src/locales/index.ts, not be written inline."
4117
+ });
4118
+ },
4119
+ CallExpression(node) {
4120
+ if (node.callee.type !== "MemberExpression") return;
4121
+ const objectName = getNodeName(node.callee.object);
4122
+ const methodName = getNodeName(node.callee.property);
4123
+ if (objectName !== "toast" || methodName === null || !TOAST_METHOD_NAMES.has(methodName)) return;
4124
+ if (!containsUserFacingString(node.arguments[0])) return;
4125
+ context.report({
4126
+ node,
4127
+ message: "User-facing toast text must come from src/locales/index.ts, not be written inline."
4128
+ });
4013
4129
  }
4014
4130
  };
4015
4131
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.10.28",
3
+ "version": "0.10.30",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",