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.
- package/dist/eslint/pasika/index.js +117 -1
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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
|
}
|