eslint-plugin-formatjs 6.6.0 → 6.6.2

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/index.js CHANGED
@@ -23,7 +23,6 @@ const FORMAT_FUNCTION_NAMES = /* @__PURE__ */ new Set([
23
23
  "$t"
24
24
  ]);
25
25
  const COMPONENT_NAMES = /* @__PURE__ */ new Set(["FormattedMessage"]);
26
- const DECLARATION_FUNCTION_NAMES = /* @__PURE__ */ new Set(["defineMessage"]);
27
26
  function getSettings({ settings }) {
28
27
  return settings.formatjs ?? settings;
29
28
  }
@@ -76,21 +75,29 @@ function staticallyEvaluateStringConcat(node) {
76
75
  const left = getStaticStringFromBinaryExpressionOperand(node.left);
77
76
  return left !== void 0 && right !== void 0 ? [left + right, true] : ["", false];
78
77
  }
79
- function isIntlFormatMessageCall(node) {
80
- if (node.type !== "CallExpression") return false;
81
- if (node.arguments.length < 1 || node.arguments[0].type !== "ObjectExpression") return false;
82
- if (node.callee.type === "MemberExpression") return (node.callee.object.type === "Identifier" && node.callee.object.name === "intl" || node.callee.object.type === "MemberExpression" && node.callee.object.property.type === "Identifier" && node.callee.object.property.name === "intl") && node.callee.property.type === "Identifier" && (node.callee.property.name === "formatMessage" || node.callee.property.name === "$t");
83
- if (node.callee.type === "Identifier") return FORMAT_FUNCTION_NAMES.has(node.callee.name);
84
- return false;
78
+ function unwrapObjectExpression(node) {
79
+ switch (node?.type) {
80
+ case "TSAsExpression":
81
+ case "TSSatisfiesExpression":
82
+ case "TSNonNullExpression":
83
+ case "TSTypeAssertion": return unwrapObjectExpression(node.expression);
84
+ case "ObjectExpression": return node;
85
+ }
85
86
  }
86
- function isSingleMessageDescriptorDeclaration(node, functionNames) {
87
- return node.type === "CallExpression" && node.callee.type === "Identifier" && functionNames.has(node.callee.name);
87
+ function getCalleeName(node) {
88
+ if (node.type === "Identifier") return node.name;
89
+ if (node.type === "MemberExpression" && node.property.type === "Identifier") return node.property.name;
88
90
  }
89
- function isMultipleMessageDescriptorDeclaration(node) {
90
- return node.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "defineMessages";
91
+ function isIntlFormatMessageCall(node, additionalFunctionNames = []) {
92
+ if (node.type === "ChainExpression") return isIntlFormatMessageCall(node.expression, additionalFunctionNames);
93
+ if (node.type !== "CallExpression") return false;
94
+ const descriptor = node.arguments[0];
95
+ const calleeName = getCalleeName(node.callee);
96
+ return !!(calleeName && (FORMAT_FUNCTION_NAMES.has(calleeName) || additionalFunctionNames.includes(calleeName)) && descriptor?.type !== "SpreadElement" && unwrapObjectExpression(descriptor));
91
97
  }
92
- function extractMessageDescriptor(node) {
93
- if (!node || node.type !== "ObjectExpression") return;
98
+ function extractMessageDescriptor(expression) {
99
+ const node = unwrapObjectExpression(expression);
100
+ if (!node) return;
94
101
  const result = {
95
102
  messageDescriptorNode: node,
96
103
  message: {},
@@ -100,8 +107,8 @@ function extractMessageDescriptor(node) {
100
107
  idValueNode: void 0
101
108
  };
102
109
  for (const prop of node.properties) {
103
- if (prop.type !== "Property" || prop.key.type !== "Identifier") continue;
104
- const propName = prop.key.name;
110
+ if (prop.type !== "Property") continue;
111
+ const propName = prop.key.type === "Identifier" ? prop.key.name : prop.key.type === "Literal" ? prop.key.value : void 0;
105
112
  if (propName !== "id" && propName !== "defaultMessage" && propName !== "description") continue;
106
113
  const valueNode = prop.value;
107
114
  const value = isStaticMessageExpression(valueNode) ? getStaticStringFromMessageExpression(valueNode) : void 0;
@@ -171,14 +178,13 @@ function extractMessageDescriptorFromJSXElement(node) {
171
178
  if (!result.messagePropNode && !result.descriptionNode && !result.idPropNode && hasSpreadAttribute) return;
172
179
  return [result, values];
173
180
  }
174
- function extractMessageDescriptors(node) {
175
- if (!node || node.type !== "ObjectExpression" || !node.properties.length) return [];
181
+ function extractMessageDescriptors(expression) {
182
+ const node = unwrapObjectExpression(expression);
183
+ if (!node) return [];
176
184
  const msgs = [];
177
185
  for (const prop of node.properties) {
178
186
  if (prop.type !== "Property") continue;
179
- const msg = prop.value;
180
- if (msg.type !== "ObjectExpression") continue;
181
- const nodeInfo = extractMessageDescriptor(msg);
187
+ const nodeInfo = extractMessageDescriptor(prop.value);
182
188
  if (nodeInfo) msgs.push(nodeInfo);
183
189
  }
184
190
  return msgs;
@@ -190,10 +196,13 @@ function extractMessages(node, { additionalComponentNames, additionalFunctionNam
190
196
  const args0 = node.arguments[0];
191
197
  const args1 = node.arguments[1];
192
198
  if (!args0 || args0.type === "SpreadElement") return [];
193
- if (!excludeMessageDeclCalls && isSingleMessageDescriptorDeclaration(node, DECLARATION_FUNCTION_NAMES) || isIntlFormatMessageCall(node) || isSingleMessageDescriptorDeclaration(node, allFormatFunctionNames)) {
199
+ const calleeName = getCalleeName(node.callee);
200
+ if (!calleeName) return [];
201
+ if (calleeName === "defineMessages") return excludeMessageDeclCalls ? [] : extractMessageDescriptors(args0).map((msg) => [msg, void 0]);
202
+ if (calleeName === "defineMessage" ? !excludeMessageDeclCalls : allFormatFunctionNames.has(calleeName)) {
194
203
  const msgDescriptorNodeInfo = extractMessageDescriptor(args0);
195
204
  if (msgDescriptorNodeInfo && (!args1 || args1.type !== "SpreadElement")) return [[msgDescriptorNodeInfo, args1]];
196
- } else if (!excludeMessageDeclCalls && isMultipleMessageDescriptorDeclaration(node)) return extractMessageDescriptors(args0).map((msg) => [msg, void 0]);
205
+ }
197
206
  } else if (node.type === "JSXOpeningElement" && node.name && node.name.type === "JSXIdentifier" && allComponentNames.has(node.name.name)) {
198
207
  const msgDescriptorNodeInfo = extractMessageDescriptorFromJSXElement(node);
199
208
  if (msgDescriptorNodeInfo) return [msgDescriptorNodeInfo];
@@ -4268,9 +4277,10 @@ const rule$3 = {
4268
4277
  schema: []
4269
4278
  },
4270
4279
  create(context) {
4280
+ const { additionalFunctionNames } = getSettings(context);
4271
4281
  return { JSXElement: (node) => {
4272
4282
  node.children.forEach((child) => {
4273
- if (child.type !== "JSXExpressionContainer" || !isIntlFormatMessageCall(child.expression)) return;
4283
+ if (child.type !== "JSXExpressionContainer" || !isIntlFormatMessageCall(child.expression, additionalFunctionNames)) return;
4274
4284
  context.report({
4275
4285
  node: child,
4276
4286
  messageId: "jsxChildren"
@@ -4573,7 +4583,7 @@ var package_exports = /* @__PURE__ */ __exportAll({
4573
4583
  version: () => version$1
4574
4584
  });
4575
4585
  var name$1 = "eslint-plugin-formatjs";
4576
- var version$1 = "6.6.0";
4586
+ var version$1 = "6.6.2";
4577
4587
  var description = "ESLint plugin for formatjs";
4578
4588
  var keywords = [
4579
4589
  "eslint",
@@ -4598,7 +4608,7 @@ var dependencies = {
4598
4608
  "@formatjs/ts-transformer": "workspace:*",
4599
4609
  "@types/estree-jsx": "1",
4600
4610
  "@types/picomatch": "4",
4601
- "@unicode/unicode-17.0.0": "1",
4611
+ "@unicode/unicode-17.0.0": "2",
4602
4612
  "magic-string": "1",
4603
4613
  "picomatch": "2 || 3 || 4"
4604
4614
  };