eslint-plugin-formatjs 6.1.2 → 6.1.4

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.
Files changed (45) hide show
  1. package/package.json +2 -3
  2. package/rules/blocklist-elements.d.ts +2 -5
  3. package/rules/blocklist-elements.js +3 -11
  4. package/rules/enforce-default-message.d.ts +2 -5
  5. package/rules/enforce-default-message.js +1 -6
  6. package/rules/enforce-description.d.ts +2 -5
  7. package/rules/enforce-description.js +1 -6
  8. package/rules/enforce-id.d.ts +2 -5
  9. package/rules/enforce-id.js +1 -9
  10. package/rules/enforce-placeholders.d.ts +2 -8
  11. package/rules/enforce-placeholders.js +1 -6
  12. package/rules/enforce-plural-rules.d.ts +2 -4
  13. package/rules/enforce-plural-rules.js +1 -6
  14. package/rules/no-camel-case.d.ts +2 -5
  15. package/rules/no-camel-case.js +1 -6
  16. package/rules/no-complex-selectors.d.ts +2 -9
  17. package/rules/no-complex-selectors.js +1 -6
  18. package/rules/no-emoji.d.ts +2 -3
  19. package/rules/no-emoji.js +1 -6
  20. package/rules/no-id.d.ts +2 -4
  21. package/rules/no-id.js +1 -6
  22. package/rules/no-invalid-icu.d.ts +2 -3
  23. package/rules/no-invalid-icu.js +1 -6
  24. package/rules/no-literal-string-in-jsx.d.ts +2 -12
  25. package/rules/no-literal-string-in-jsx.js +3 -7
  26. package/rules/no-literal-string-in-object.d.ts +2 -8
  27. package/rules/no-literal-string-in-object.js +2 -8
  28. package/rules/no-missing-icu-plural-one-placeholders.d.ts +2 -4
  29. package/rules/no-missing-icu-plural-one-placeholders.js +1 -6
  30. package/rules/no-multiple-plurals.d.ts +2 -5
  31. package/rules/no-multiple-plurals.js +1 -6
  32. package/rules/no-multiple-whitespaces.d.ts +2 -5
  33. package/rules/no-multiple-whitespaces.js +1 -6
  34. package/rules/no-offset.d.ts +2 -5
  35. package/rules/no-offset.js +1 -6
  36. package/rules/no-useless-message.d.ts +2 -5
  37. package/rules/no-useless-message.js +1 -6
  38. package/rules/prefer-formatted-message.d.ts +2 -4
  39. package/rules/prefer-formatted-message.js +0 -2
  40. package/rules/prefer-pound-in-plural.d.ts +2 -5
  41. package/rules/prefer-pound-in-plural.js +1 -6
  42. package/util.d.ts +14 -16
  43. package/util.js +12 -12
  44. package/context-compat.d.ts +0 -3
  45. package/context-compat.js +0 -7
package/package.json CHANGED
@@ -1,20 +1,19 @@
1
1
  {
2
2
  "name": "eslint-plugin-formatjs",
3
3
  "description": "ESLint plugin for formatjs",
4
- "version": "6.1.2",
4
+ "version": "6.1.4",
5
5
  "license": "MIT",
6
6
  "author": "Long Ho <holevietlong@gmail.com>",
7
7
  "type": "module",
8
8
  "types": "index.d.ts",
9
9
  "dependencies": {
10
10
  "@types/picomatch": "^4.0.0",
11
- "@typescript-eslint/utils": "^8.52.0",
12
11
  "@unicode/unicode-17.0.0": "^1.6.16",
13
12
  "magic-string": "^0.30.0",
14
13
  "picomatch": "2 || 3 || 4",
15
14
  "tslib": "^2.8.1",
16
15
  "@formatjs/icu-messageformat-parser": "3.5.1",
17
- "@formatjs/ts-transformer": "4.3.2"
16
+ "@formatjs/ts-transformer": "4.4.0"
18
17
  },
19
18
  "peerDependencies": {
20
19
  "eslint": "9"
@@ -1,6 +1,4 @@
1
- import { ESLintUtils } from "@typescript-eslint/utils";
2
- import { type CoreMessageIds } from "../messages.js";
3
- type MessageIds = "blocklist" | CoreMessageIds;
1
+ import type { Rule } from "eslint";
4
2
  export declare const name = "blocklist-elements";
5
3
  export declare enum Element {
6
4
  literal = "literal",
@@ -13,5 +11,4 @@ export declare enum Element {
13
11
  plural = "plural",
14
12
  tag = "tag"
15
13
  }
16
- export declare const rule: ESLintUtils.RuleModule<MessageIds, Element[][], unknown, ESLintUtils.RuleListener>;
17
- export {};
14
+ export declare const rule: Rule.RuleModule;
@@ -1,7 +1,4 @@
1
1
  import { isArgumentElement, isDateElement, isLiteralElement, isNumberElement, isPluralElement, isSelectElement, isTagElement, isTimeElement, parse } from "@formatjs/icu-messageformat-parser";
2
- import { ESLintUtils } from "@typescript-eslint/utils";
3
- import "@typescript-eslint/utils/ts-eslint";
4
- import { getParserServices } from "../context-compat.js";
5
2
  import { extractMessages, getSettings } from "../util.js";
6
3
  import { CORE_MESSAGES } from "../messages.js";
7
4
  export const name = "blocklist-elements";
@@ -98,9 +95,7 @@ function checkNode(context, node) {
98
95
  }
99
96
  }
100
97
  }
101
- const createRule = ESLintUtils.RuleCreator((_) => "https://formatjs.github.io/docs/tooling/linter#blocklist-elements");
102
- export const rule = createRule({
103
- name,
98
+ export const rule = {
104
99
  meta: {
105
100
  type: "problem",
106
101
  docs: {
@@ -120,13 +115,10 @@ export const rule = createRule({
120
115
  blocklist: `{{type}} element is blocklisted`
121
116
  }
122
117
  },
123
- defaultOptions: [],
124
118
  create(context) {
125
119
  const callExpressionVisitor = (node) => checkNode(context, node);
126
- const parserServices = getParserServices(context);
127
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
120
+ const parserServices = context.sourceCode.parserServices;
128
121
  if (parserServices?.defineTemplateBodyVisitor) {
129
- //@ts-expect-error
130
122
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
131
123
  }
132
124
  return {
@@ -134,4 +126,4 @@ export const rule = createRule({
134
126
  CallExpression: callExpressionVisitor
135
127
  };
136
128
  }
137
- });
129
+ };
@@ -1,10 +1,7 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
1
+ import type { Rule } from "eslint";
2
2
  export declare enum Option {
3
3
  literal = "literal",
4
4
  anything = "anything"
5
5
  }
6
- type MessageIds = "defaultMessage" | "defaultMessageLiteral";
7
- type Options = [`${Option}`?];
8
6
  export declare const name = "enforce-default-message";
9
- export declare const rule: RuleModule<MessageIds, Options>;
10
- export {};
7
+ export declare const rule: Rule.RuleModule;
@@ -1,5 +1,3 @@
1
- import "@typescript-eslint/utils/ts-eslint";
2
- import { getParserServices } from "../context-compat.js";
3
1
  import { extractMessages, getSettings } from "../util.js";
4
2
  export let Option = /* @__PURE__ */ function(Option) {
5
3
  Option["literal"] = "literal";
@@ -45,13 +43,10 @@ export const rule = {
45
43
  defaultMessage: "`defaultMessage` has to be specified in message descriptor"
46
44
  }
47
45
  },
48
- defaultOptions: [],
49
46
  create(context) {
50
47
  const callExpressionVisitor = (node) => checkNode(context, node);
51
- const parserServices = getParserServices(context);
52
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
48
+ const parserServices = context.sourceCode.parserServices;
53
49
  if (parserServices?.defineTemplateBodyVisitor) {
54
- //@ts-expect-error
55
50
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
56
51
  }
57
52
  return {
@@ -1,10 +1,7 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
1
+ import type { Rule } from "eslint";
2
2
  export declare enum Option {
3
3
  literal = "literal",
4
4
  anything = "anything"
5
5
  }
6
- type MessageIds = "enforceDescription" | "enforceDescriptionLiteral";
7
- type Options = [`${Option}`?];
8
6
  export declare const name = "enforce-description";
9
- export declare const rule: RuleModule<MessageIds, Options>;
10
- export {};
7
+ export declare const rule: Rule.RuleModule;
@@ -1,5 +1,3 @@
1
- import "@typescript-eslint/utils/ts-eslint";
2
- import { getParserServices } from "../context-compat.js";
3
1
  import { extractMessages, getSettings } from "../util.js";
4
2
  export let Option = /* @__PURE__ */ function(Option) {
5
3
  Option["literal"] = "literal";
@@ -43,13 +41,10 @@ export const rule = {
43
41
  enforceDescriptionLiteral: "`description` has to be a string literal (not function call or variable)"
44
42
  }
45
43
  },
46
- defaultOptions: [],
47
44
  create(context) {
48
45
  const callExpressionVisitor = (node) => checkNode(context, node);
49
- const parserServices = getParserServices(context);
50
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
46
+ const parserServices = context.sourceCode.parserServices;
51
47
  if (parserServices?.defineTemplateBodyVisitor) {
52
- //@ts-expect-error
53
48
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
54
49
  }
55
50
  return {
@@ -1,11 +1,8 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
1
+ import type { Rule } from "eslint";
2
2
  export type Option = {
3
3
  idInterpolationPattern: string;
4
4
  idWhitelist?: string[];
5
5
  quoteStyle?: "single" | "double";
6
6
  };
7
- type MessageIds = "enforceId" | "enforceIdDefaultMessage" | "enforceIdDescription" | "enforceIdMatching" | "enforceIdMatchingAllowlisted";
8
- type Options = [Option];
9
7
  export declare const name = "enforce-id";
10
- export declare const rule: RuleModule<MessageIds, Options>;
11
- export {};
8
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { interpolateName } from "@formatjs/ts-transformer";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  function checkNode(context, node, { idInterpolationPattern, idWhitelistRegexps, quoteStyle }) {
6
4
  const msgs = extractMessages(node, getSettings(context));
@@ -114,10 +112,6 @@ Expected: {{expected}}
114
112
  Actual: {{actual}}`
115
113
  }
116
114
  },
117
- defaultOptions: [{
118
- idInterpolationPattern: "[sha512:contenthash:base64:6]",
119
- quoteStyle: "single"
120
- }],
121
115
  create(context) {
122
116
  const tmp = context.options[0];
123
117
  let opts = {
@@ -129,10 +123,8 @@ Actual: {{actual}}`
129
123
  opts.idWhitelistRegexps = idWhitelist.map((str) => new RegExp(str, "i"));
130
124
  }
131
125
  const callExpressionVisitor = (node) => checkNode(context, node, opts);
132
- const parserServices = getParserServices(context);
133
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
126
+ const parserServices = context.sourceCode.parserServices;
134
127
  if (parserServices?.defineTemplateBodyVisitor) {
135
- //@ts-expect-error
136
128
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
137
129
  }
138
130
  return {
@@ -1,9 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
3
- type MessageIds = "missingValue" | "unusedValue" | CoreMessageIds;
4
- type Options = [{
5
- ignoreList: string[];
6
- }?];
1
+ import type { Rule } from "eslint";
7
2
  export declare const name = "enforce-placeholders";
8
- export declare const rule: RuleModule<MessageIds, Options>;
9
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { TYPE, parse } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  function collectPlaceholderNames(ast) {
@@ -116,13 +114,10 @@ export const rule = {
116
114
  unusedValue: "Value not used by the message."
117
115
  }
118
116
  },
119
- defaultOptions: [],
120
117
  create(context) {
121
118
  const callExpressionVisitor = (node) => checkNode(context, node);
122
- const parserServices = getParserServices(context);
123
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
119
+ const parserServices = context.sourceCode.parserServices;
124
120
  if (parserServices?.defineTemplateBodyVisitor) {
125
- //@ts-expect-error
126
121
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
127
122
  }
128
123
  return {
@@ -1,5 +1,4 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
1
+ import type { Rule } from "eslint";
3
2
  declare enum LDML {
4
3
  zero = "zero",
5
4
  one = "one",
@@ -10,7 +9,6 @@ declare enum LDML {
10
9
  }
11
10
  type PluralConfig = { [key in LDML]? : boolean };
12
11
  export type Options = [PluralConfig?];
13
- type MessageIds = "missingPlural" | "forbidden" | CoreMessageIds;
14
12
  export declare const name = "enforce-plural-rules";
15
- export declare const rule: RuleModule<MessageIds, Options>;
13
+ export declare const rule: Rule.RuleModule;
16
14
  export {};
@@ -1,6 +1,4 @@
1
1
  import { isPluralElement, parse } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  var LDML = /* @__PURE__ */ function(LDML) {
@@ -96,13 +94,10 @@ export const rule = {
96
94
  forbidden: `Plural rule "{{rule}}" is forbidden`
97
95
  }
98
96
  },
99
- defaultOptions: [],
100
97
  create(context) {
101
98
  const callExpressionVisitor = (node) => checkNode(context, node);
102
- const parserServices = getParserServices(context);
103
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
99
+ const parserServices = context.sourceCode.parserServices;
104
100
  if (parserServices?.defineTemplateBodyVisitor) {
105
- //@ts-expect-error
106
101
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
107
102
  }
108
103
  return {
@@ -1,6 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
3
- type MessageIds = "camelcase" | CoreMessageIds;
1
+ import type { Rule } from "eslint";
4
2
  export declare const name = "no-camel-case";
5
- export declare const rule: RuleModule<MessageIds>;
6
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { isArgumentElement, isPluralElement, parse } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  export const name = "no-camel-case";
@@ -73,13 +71,10 @@ export const rule = {
73
71
  camelcase: "Camel case arguments are not allowed"
74
72
  }
75
73
  },
76
- defaultOptions: [],
77
74
  create(context) {
78
75
  const callExpressionVisitor = (node) => checkNode(context, node);
79
- const parserServices = getParserServices(context);
80
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
76
+ const parserServices = context.sourceCode.parserServices;
81
77
  if (parserServices?.defineTemplateBodyVisitor) {
82
- //@ts-expect-error
83
78
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
84
79
  }
85
80
  return {
@@ -1,10 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
3
- interface Config {
4
- limit: number;
5
- }
6
- type MessageIds = "tooComplex" | CoreMessageIds;
7
- type Options = [Config?];
1
+ import type { Rule } from "eslint";
8
2
  export declare const name = "no-complex-selectors";
9
- export declare const rule: RuleModule<MessageIds, Options>;
10
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { TYPE, parse } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  function calculateComplexity(ast) {
@@ -107,13 +105,10 @@ Default complexity limit is 20
107
105
  tooComplex: `Message complexity is too high ({{complexity}} vs limit at {{limit}})`
108
106
  }
109
107
  },
110
- defaultOptions: [{ limit: 20 }],
111
108
  create(context) {
112
109
  const callExpressionVisitor = (node) => checkNode(context, node);
113
- const parserServices = getParserServices(context);
114
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
110
+ const parserServices = context.sourceCode.parserServices;
115
111
  if (parserServices?.defineTemplateBodyVisitor) {
116
- //@ts-expect-error
117
112
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
118
113
  }
119
114
  return {
@@ -1,9 +1,8 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
1
+ import type { Rule } from "eslint";
2
2
  export declare const name = "no-emoji";
3
- type MessageIds = "notAllowed" | "notAllowedAboveVersion";
4
3
  type NoEmojiConfig = {
5
4
  versionAbove: string;
6
5
  };
7
6
  export type Options = [NoEmojiConfig?];
8
- export declare const rule: RuleModule<MessageIds, Options>;
7
+ export declare const rule: Rule.RuleModule;
9
8
  export {};
package/rules/no-emoji.js CHANGED
@@ -1,6 +1,4 @@
1
- import "@typescript-eslint/utils/ts-eslint";
2
1
  import { extractEmojis, filterEmojis, hasEmoji, isValidEmojiVersion } from "../emoji-utils.js";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  export const name = "no-emoji";
6
4
  function checkNode(context, node) {
@@ -76,13 +74,10 @@ export const rule = {
76
74
  notAllowedAboveVersion: "Emojis above version {{versionAbove}} are not allowed - Emoji: {{emoji}}"
77
75
  }
78
76
  },
79
- defaultOptions: [],
80
77
  create(context) {
81
78
  const callExpressionVisitor = (node) => checkNode(context, node);
82
- const parserServices = getParserServices(context);
83
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
79
+ const parserServices = context.sourceCode.parserServices;
84
80
  if (parserServices?.defineTemplateBodyVisitor) {
85
- //@ts-expect-error
86
81
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
87
82
  }
88
83
  return {
package/rules/no-id.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- type MessageIds = "noId";
1
+ import type { Rule } from "eslint";
3
2
  export declare const name = "no-id";
4
- export declare const rule: RuleModule<MessageIds>;
5
- export {};
3
+ export declare const rule: Rule.RuleModule;
package/rules/no-id.js CHANGED
@@ -1,5 +1,3 @@
1
- import "@typescript-eslint/utils/ts-eslint";
2
- import { getParserServices } from "../context-compat.js";
3
1
  import { extractMessages, getSettings } from "../util.js";
4
2
  function isComment(token) {
5
3
  return !!token && (token.type === "Block" || token.type === "Line");
@@ -36,13 +34,10 @@ export const rule = {
36
34
  schema: [],
37
35
  messages: { noId: "Manual `id` are not allowed in message descriptor" }
38
36
  },
39
- defaultOptions: [],
40
37
  create(context) {
41
38
  const callExpressionVisitor = (node) => checkNode(context, node);
42
- const parserServices = getParserServices(context);
43
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
39
+ const parserServices = context.sourceCode.parserServices;
44
40
  if (parserServices?.defineTemplateBodyVisitor) {
45
- //@ts-expect-error
46
41
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
47
42
  }
48
43
  return {
@@ -1,4 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
1
+ import type { Rule } from "eslint";
3
2
  export declare const name = "no-invalid-icu";
4
- export declare const rule: RuleModule<CoreMessageIds>;
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { parse } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  export const name = "no-invalid-icu";
@@ -44,13 +42,10 @@ export const rule = {
44
42
  schema: [],
45
43
  messages: CORE_MESSAGES
46
44
  },
47
- defaultOptions: [],
48
45
  create(context) {
49
46
  const callExpressionVisitor = (node) => checkNode(context, node);
50
- const parserServices = getParserServices(context);
51
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
47
+ const parserServices = context.sourceCode.parserServices;
52
48
  if (parserServices?.defineTemplateBodyVisitor) {
53
- //@ts-expect-error
54
49
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
55
50
  }
56
51
  return {
@@ -1,13 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- type PropMatcher = readonly [TagNamePattern: string, PropNamePattern: string][];
3
- type Config = {
4
- props?: {
5
- include?: PropMatcher;
6
- exclude?: PropMatcher;
7
- };
8
- };
9
- type MessageIds = "noLiteralStringInJsx";
10
- type Options = [Config?];
1
+ import type { Rule } from "eslint";
11
2
  export declare const name = "no-literal-string-in-jsx";
12
- export declare const rule: RuleModule<MessageIds, Options>;
13
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,3 @@
1
- import { TSESTree } from "@typescript-eslint/utils";
2
- import "@typescript-eslint/utils/json-schema";
3
- import "@typescript-eslint/utils/ts-eslint";
4
1
  import * as picomatchNs from "picomatch";
5
2
  const picomatch = picomatchNs.default ?? picomatchNs;
6
3
  const propMatcherSchema = {
@@ -18,9 +15,9 @@ const defaultPropIncludePattern = [
18
15
  const defaultPropExcludePattern = [];
19
16
  function stringifyJsxTagName(tagName) {
20
17
  switch (tagName.type) {
21
- case TSESTree.AST_NODE_TYPES.JSXIdentifier: return tagName.name;
22
- case TSESTree.AST_NODE_TYPES.JSXMemberExpression: return `${stringifyJsxTagName(tagName.object)}.${tagName.property.name}`;
23
- case TSESTree.AST_NODE_TYPES.JSXNamespacedName: return `${tagName.namespace.name}:${tagName.name.name}`;
18
+ case "JSXIdentifier": return tagName.name;
19
+ case "JSXMemberExpression": return `${stringifyJsxTagName(tagName.object)}.${tagName.property.name}`;
20
+ case "JSXNamespacedName": return `${tagName.namespace.name}:${tagName.name.name}`;
24
21
  }
25
22
  }
26
23
  function compilePropMatcher(propMatcher) {
@@ -50,7 +47,6 @@ export const rule = {
50
47
  }],
51
48
  messages: { noLiteralStringInJsx: "Cannot have untranslated text in JSX" }
52
49
  },
53
- defaultOptions: [],
54
50
  create(context) {
55
51
  const userConfig = context.options[0] || {};
56
52
  const propIncludePattern = compilePropMatcher([...defaultPropIncludePattern, ...userConfig.props?.include ?? []]);
@@ -1,9 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- type MessageIds = "untranslatedProperty";
3
- type PropertyConfig = {
4
- include: string[];
5
- };
6
- type Options = [PropertyConfig?];
1
+ import type { Rule } from "eslint";
7
2
  export declare const name = "no-literal-string-in-object";
8
- export declare const rule: RuleModule<MessageIds, Options>;
9
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,3 @@
1
- import { TSESTree } from "@typescript-eslint/utils";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
1
  export const name = "no-literal-string-in-object";
5
2
  export const rule = {
6
3
  meta: {
@@ -20,15 +17,12 @@ export const rule = {
20
17
  }],
21
18
  messages: { untranslatedProperty: "Object property: `{{propertyKey}}` might contain an untranslated literal string" }
22
19
  },
23
- defaultOptions: [],
24
20
  create(context) {
25
21
  const propertyVisitor = (node) => {
26
22
  checkProperty(context, node);
27
23
  };
28
- const parserServices = getParserServices(context);
29
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
24
+ const parserServices = context.sourceCode.parserServices;
30
25
  if (parserServices?.defineTemplateBodyVisitor) {
31
- //@ts-expect-error
32
26
  return parserServices.defineTemplateBodyVisitor({ Property: propertyVisitor }, { Property: propertyVisitor });
33
27
  }
34
28
  return { Property: propertyVisitor };
@@ -39,7 +33,7 @@ function checkProperty(context, node) {
39
33
  include: ["label"],
40
34
  ...context.options[0]
41
35
  };
42
- const propertyKey = node.key.type === TSESTree.AST_NODE_TYPES.Identifier ? node.key.name : node.key.type === TSESTree.AST_NODE_TYPES.Literal && typeof node.key.value === "string" ? node.key.value : null;
36
+ const propertyKey = node.key.type === "Identifier" ? node.key.name : node.key.type === "Literal" && typeof node.key.value === "string" ? node.key.value : null;
43
37
  if (!propertyKey || !config.include.includes(propertyKey)) {
44
38
  return;
45
39
  }
@@ -1,7 +1,5 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
1
+ import type { Rule } from "eslint";
2
2
  import { type CoreMessageIds } from "../messages.js";
3
3
  export declare const name = "no-missing-icu-plural-one-placeholders";
4
4
  export type MessageIds = "noMissingIcuPluralOnePlaceholders" | CoreMessageIds;
5
- type Options = [];
6
- export declare const rule: RuleModule<MessageIds, Options>;
7
- export {};
5
+ export declare const rule: Rule.RuleModule;
@@ -1,7 +1,5 @@
1
1
  import { isLiteralElement, isPluralElement, isSelectElement, isTagElement, parse } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
2
  import MagicString from "magic-string";
4
- import { getParserServices } from "../context-compat.js";
5
3
  import { extractMessages, patchMessage } from "../util.js";
6
4
  import { CORE_MESSAGES } from "../messages.js";
7
5
  export const name = "no-missing-icu-plural-one-placeholders";
@@ -82,13 +80,10 @@ export const rule = {
82
80
  },
83
81
  schema: []
84
82
  },
85
- defaultOptions: [],
86
83
  create(context) {
87
84
  const callExpressionVisitor = (node) => checkNode(context, node);
88
- const parserServices = getParserServices(context);
89
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
85
+ const parserServices = context.sourceCode.parserServices;
90
86
  if (parserServices?.defineTemplateBodyVisitor) {
91
- //@ts-expect-error
92
87
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
93
88
  }
94
89
  return {
@@ -1,6 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
3
- type MessageIds = "noMultiplePlurals" | CoreMessageIds;
1
+ import type { Rule } from "eslint";
4
2
  export declare const name = "no-multiple-plurals";
5
- export declare const rule: RuleModule<MessageIds>;
6
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { isPluralElement, parse } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  function verifyAst(ast, pluralCount = { count: 0 }) {
@@ -64,13 +62,10 @@ export const rule = {
64
62
  noMultiplePlurals: "Multiple plural rules in the same message"
65
63
  }
66
64
  },
67
- defaultOptions: [],
68
65
  create(context) {
69
66
  const callExpressionVisitor = (node) => checkNode(context, node);
70
- const parserServices = getParserServices(context);
71
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
67
+ const parserServices = context.sourceCode.parserServices;
72
68
  if (parserServices?.defineTemplateBodyVisitor) {
73
- //@ts-expect-error
74
69
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
75
70
  }
76
71
  return {
@@ -1,6 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
3
- type MessageIds = "noMultipleWhitespaces" | CoreMessageIds;
1
+ import type { Rule } from "eslint";
4
2
  export declare const name = "no-multiple-whitespaces";
5
- export declare const rule: RuleModule<MessageIds>;
6
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { parse, TYPE } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings, patchMessage } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  function isAstValid(ast) {
@@ -114,13 +112,10 @@ export const rule = {
114
112
  fixable: "code",
115
113
  schema: []
116
114
  },
117
- defaultOptions: [],
118
115
  create(context) {
119
116
  const callExpressionVisitor = (node) => checkNode(context, node);
120
- const parserServices = getParserServices(context);
121
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
117
+ const parserServices = context.sourceCode.parserServices;
122
118
  if (parserServices?.defineTemplateBodyVisitor) {
123
- //@ts-expect-error
124
119
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
125
120
  }
126
121
  return {
@@ -1,6 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
3
- type MessageIds = "noOffset" | CoreMessageIds;
1
+ import type { Rule } from "eslint";
4
2
  export declare const name = "no-offset";
5
- export declare const rule: RuleModule<MessageIds>;
6
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { isPluralElement, parse } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  function verifyAst(ast) {
@@ -63,13 +61,10 @@ export const rule = {
63
61
  },
64
62
  schema: []
65
63
  },
66
- defaultOptions: [],
67
64
  create(context) {
68
65
  const callExpressionVisitor = (node) => checkNode(context, node);
69
- const parserServices = getParserServices(context);
70
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
66
+ const parserServices = context.sourceCode.parserServices;
71
67
  if (parserServices?.defineTemplateBodyVisitor) {
72
- //@ts-expect-error
73
68
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
74
69
  }
75
70
  return {
@@ -1,6 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
3
- type MessageIds = "unnecessaryFormat" | "unnecessaryFormatNumber" | "unnecessaryFormatDate" | "unnecessaryFormatTime" | CoreMessageIds;
1
+ import type { Rule } from "eslint";
4
2
  export declare const name = "no-useless-message";
5
- export declare const rule: RuleModule<MessageIds>;
6
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,6 +1,4 @@
1
1
  import { parse, TYPE } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
- import { getParserServices } from "../context-compat.js";
4
2
  import { extractMessages, getSettings } from "../util.js";
5
3
  import { CORE_MESSAGES } from "../messages.js";
6
4
  function verifyAst(ast) {
@@ -57,13 +55,10 @@ export const rule = {
57
55
  unnecessaryFormatTime: "Unnecessary formatted message: just use FormattedTime or intl.formatTime."
58
56
  }
59
57
  },
60
- defaultOptions: [],
61
58
  create(context) {
62
59
  const callExpressionVisitor = (node) => checkNode(context, node);
63
- const parserServices = getParserServices(context);
64
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
60
+ const parserServices = context.sourceCode.parserServices;
65
61
  if (parserServices?.defineTemplateBodyVisitor) {
66
- //@ts-expect-error
67
62
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
68
63
  }
69
64
  return {
@@ -1,5 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- type MessageIds = "jsxChildren";
1
+ import type { Rule } from "eslint";
3
2
  export declare const name = "prefer-formatted-message";
4
- export declare const rule: RuleModule<MessageIds>;
5
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,4 +1,3 @@
1
- import "@typescript-eslint/utils/ts-eslint";
2
1
  import { isIntlFormatMessageCall } from "../util.js";
3
2
  export const name = "prefer-formatted-message";
4
3
  export const rule = {
@@ -11,7 +10,6 @@ export const rule = {
11
10
  messages: { jsxChildren: "Prefer `FormattedMessage` over `intl.formatMessage` in the JSX children expression." },
12
11
  schema: []
13
12
  },
14
- defaultOptions: [],
15
13
  create(context) {
16
14
  return { JSXElement: (node) => {
17
15
  node.children.forEach((child) => {
@@ -1,6 +1,3 @@
1
- import { type RuleModule } from "@typescript-eslint/utils/ts-eslint";
2
- import { type CoreMessageIds } from "../messages.js";
3
- type MessageIds = "preferPoundInPlurals" | CoreMessageIds;
1
+ import type { Rule } from "eslint";
4
2
  export declare const name = "prefer-pound-in-plural";
5
- export declare const rule: RuleModule<MessageIds>;
6
- export {};
3
+ export declare const rule: Rule.RuleModule;
@@ -1,7 +1,5 @@
1
1
  import { parse, TYPE } from "@formatjs/icu-messageformat-parser";
2
- import "@typescript-eslint/utils/ts-eslint";
3
2
  import MagicString from "magic-string";
4
- import { getParserServices } from "../context-compat.js";
5
3
  import { extractMessages, getSettings, patchMessage } from "../util.js";
6
4
  import { CORE_MESSAGES } from "../messages.js";
7
5
  function verifyAst(context, messageNode, ast) {
@@ -151,13 +149,10 @@ export const rule = {
151
149
  fixable: "code",
152
150
  schema: []
153
151
  },
154
- defaultOptions: [],
155
152
  create(context) {
156
153
  const callExpressionVisitor = (node) => checkNode(context, node);
157
- const parserServices = getParserServices(context);
158
- //@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
154
+ const parserServices = context.sourceCode.parserServices;
159
155
  if (parserServices?.defineTemplateBodyVisitor) {
160
- //@ts-expect-error
161
156
  return parserServices.defineTemplateBodyVisitor({ CallExpression: callExpressionVisitor }, { CallExpression: callExpressionVisitor });
162
157
  }
163
158
  return {
package/util.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { MessageFormatElement } from "@formatjs/icu-messageformat-parser";
2
- import type { TSESTree } from "@typescript-eslint/utils";
3
- import { type RuleContext } from "@typescript-eslint/utils/ts-eslint";
2
+ import type { Rule } from "eslint";
3
+ import type { Expression, Node, ObjectExpression, Property } from "estree-jsx";
4
+ import type { JSXAttribute, JSXOpeningElement } from "estree-jsx";
4
5
  export interface MessageDescriptor {
5
6
  id?: string;
6
7
  defaultMessage?: string;
@@ -14,23 +15,20 @@ export interface Settings {
14
15
  }
15
16
  export interface MessageDescriptorNodeInfo {
16
17
  message: MessageDescriptor;
17
- messageDescriptorNode: TSESTree.ObjectExpression | TSESTree.JSXOpeningElement;
18
- messageNode?: TSESTree.Property["value"] | TSESTree.JSXAttribute["value"];
19
- messagePropNode?: TSESTree.Property | TSESTree.JSXAttribute;
20
- descriptionNode?: TSESTree.Property["value"] | TSESTree.JSXAttribute["value"];
21
- idValueNode?: TSESTree.Property["value"] | TSESTree.JSXAttribute["value"];
22
- idPropNode?: TSESTree.Property | TSESTree.JSXAttribute;
18
+ messageDescriptorNode: ObjectExpression | JSXOpeningElement;
19
+ messageNode?: Property["value"] | JSXAttribute["value"];
20
+ messagePropNode?: Property | JSXAttribute;
21
+ descriptionNode?: Property["value"] | JSXAttribute["value"];
22
+ idValueNode?: Property["value"] | JSXAttribute["value"];
23
+ idPropNode?: Property | JSXAttribute;
23
24
  }
24
- export declare function getSettings<
25
- TMessageIds extends string,
26
- TOptions extends readonly unknown[]
27
- >({ settings }: RuleContext<TMessageIds, TOptions>): Settings;
28
- export declare function isIntlFormatMessageCall(node: TSESTree.Node): node is TSESTree.CallExpression;
29
- export declare function extractMessageDescriptor(node?: TSESTree.Expression): MessageDescriptorNodeInfo | undefined;
30
- export declare function extractMessages(node: TSESTree.Node, { additionalComponentNames, additionalFunctionNames, excludeMessageDeclCalls }?: Settings): Array<[MessageDescriptorNodeInfo, TSESTree.Expression | undefined]>;
25
+ export declare function getSettings({ settings }: Rule.RuleContext): Settings;
26
+ export declare function isIntlFormatMessageCall(node: Node): boolean;
27
+ export declare function extractMessageDescriptor(node?: Expression): MessageDescriptorNodeInfo | undefined;
28
+ export declare function extractMessages(node: Node, { additionalComponentNames, additionalFunctionNames, excludeMessageDeclCalls }?: Settings): Array<[MessageDescriptorNodeInfo, Expression | undefined]>;
31
29
  /**
32
30
  * Apply changes to the ICU message in code. The return value can be used in
33
31
  * `fixer.replaceText(messageNode, <return value>)`. If the return value is null,
34
32
  * it means that the patch cannot be applied.
35
33
  */
36
- export declare function patchMessage(messageNode: TSESTree.Node, ast: MessageFormatElement[], patcher: (messageContent: string, ast: MessageFormatElement[]) => string): string | null;
34
+ export declare function patchMessage(messageNode: Node, ast: MessageFormatElement[], patcher: (messageContent: string, ast: MessageFormatElement[]) => string): string | null;
package/util.js CHANGED
@@ -1,4 +1,3 @@
1
- import "@typescript-eslint/utils/ts-eslint";
2
1
  const FORMAT_FUNCTION_NAMES = new Set([
3
2
  "$formatMessage",
4
3
  "formatMessage",
@@ -16,15 +15,17 @@ function isTemplateLiteralWithoutVar(node) {
16
15
  return node.type === "TemplateLiteral" && node.quasis.length === 1;
17
16
  }
18
17
  function staticallyEvaluateStringConcat(node) {
19
- if (!isStringLiteral(node.right)) {
18
+ const right = node.right;
19
+ const left = node.left;
20
+ if (!isStringLiteral(right)) {
20
21
  return ["", false];
21
22
  }
22
- if (isStringLiteral(node.left)) {
23
- return [String(node.left.value) + node.right.value, true];
23
+ if (isStringLiteral(left)) {
24
+ return [left.value + right.value, true];
24
25
  }
25
26
  if (node.left.type === "BinaryExpression") {
26
27
  const [result, isStaticallyEvaluatable] = staticallyEvaluateStringConcat(node.left);
27
- return [result + node.right.value, isStaticallyEvaluatable];
28
+ return [result + right.value, isStaticallyEvaluatable];
28
29
  }
29
30
  return ["", false];
30
31
  }
@@ -80,13 +81,13 @@ export function extractMessageDescriptor(node) {
80
81
  if (isStringLiteral(valueNode)) {
81
82
  value = valueNode.value;
82
83
  } else if (isTemplateLiteralWithoutVar(valueNode)) {
83
- value = valueNode.quasis[0].value.cooked;
84
+ value = valueNode.quasis[0].value.cooked ?? undefined;
84
85
  } else if (valueNode.type === "TaggedTemplateExpression") {
85
86
  const { quasi } = valueNode;
86
87
  if (!isTemplateLiteralWithoutVar(quasi)) {
87
88
  throw new Error("Tagged template expression must be no substitution");
88
89
  }
89
- value = quasi.quasis[0].value.cooked;
90
+ value = quasi.quasis[0].value.cooked ?? undefined;
90
91
  } else if (valueNode.type === "BinaryExpression") {
91
92
  const [result, isStatic] = staticallyEvaluateStringConcat(valueNode);
92
93
  if (isStatic) {
@@ -154,13 +155,13 @@ function extractMessageDescriptorFromJSXElement(node) {
154
155
  value = result;
155
156
  }
156
157
  } else if (isTemplateLiteralWithoutVar(expression)) {
157
- value = expression.quasis[0].value.cooked;
158
+ value = expression.quasis[0].value.cooked ?? undefined;
158
159
  } else if (expression.type === "TaggedTemplateExpression") {
159
160
  const { quasi } = expression;
160
161
  if (!isTemplateLiteralWithoutVar(quasi)) {
161
162
  throw new Error("Tagged template expression must be no substitution");
162
163
  }
163
- value = quasi.quasis[0].value.cooked;
164
+ value = quasi.quasis[0].value.cooked ?? undefined;
164
165
  }
165
166
  }
166
167
  }
@@ -221,9 +222,8 @@ export function extractMessages(node, { additionalComponentNames, additionalFunc
221
222
  const allFormatFunctionNames = Array.isArray(additionalFunctionNames) ? new Set([...Array.from(FORMAT_FUNCTION_NAMES), ...additionalFunctionNames]) : FORMAT_FUNCTION_NAMES;
222
223
  const allComponentNames = Array.isArray(additionalComponentNames) ? new Set([...Array.from(COMPONENT_NAMES), ...additionalComponentNames]) : COMPONENT_NAMES;
223
224
  if (node.type === "CallExpression") {
224
- const expr = node;
225
- const args0 = expr.arguments[0];
226
- const args1 = expr.arguments[1];
225
+ const args0 = node.arguments[0];
226
+ const args1 = node.arguments[1];
227
227
  // We can't really analyze spread element
228
228
  if (!args0 || args0.type === "SpreadElement") {
229
229
  return [];
@@ -1,3 +0,0 @@
1
- import type { ParserServicesWithoutTypeInformation, ParserServicesWithTypeInformation } from "@typescript-eslint/utils";
2
- import { type RuleContext } from "@typescript-eslint/utils/ts-eslint";
3
- export declare const getParserServices: <TRuleContext extends RuleContext<string, unknown[]>>(context: TRuleContext) => Partial<ParserServicesWithoutTypeInformation> | Partial<ParserServicesWithTypeInformation> | undefined;
package/context-compat.js DELETED
@@ -1,7 +0,0 @@
1
- import "@typescript-eslint/utils/ts-eslint";
2
- export const getParserServices = (context) => {
3
- if (context.parserServices) {
4
- return context.parserServices;
5
- }
6
- return context.sourceCode.parserServices;
7
- };