eslint-plugin-formatjs 4.11.2 → 4.12.0
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/LICENSE.md +1 -1
- package/index.d.ts +3 -23
- package/index.js +36 -37
- package/package.json +5 -5
- package/rules/blocklist-elements.d.ts +17 -3
- package/rules/blocklist-elements.js +50 -46
- package/rules/enforce-default-message.d.ts +10 -3
- package/rules/enforce-default-message.js +21 -9
- package/rules/enforce-description.d.ts +10 -3
- package/rules/enforce-description.js +19 -6
- package/rules/enforce-id.d.ts +10 -3
- package/rules/enforce-id.js +53 -24
- package/rules/enforce-placeholders.d.ts +8 -3
- package/rules/enforce-placeholders.js +18 -7
- package/rules/enforce-plural-rules.d.ts +17 -3
- package/rules/enforce-plural-rules.js +20 -20
- package/rules/no-camel-case.d.ts +6 -3
- package/rules/no-camel-case.js +20 -20
- package/rules/no-complex-selectors.d.ts +9 -3
- package/rules/no-complex-selectors.js +18 -16
- package/rules/no-emoji.d.ts +9 -3
- package/rules/no-emoji.js +6 -4
- package/rules/no-id.d.ts +6 -3
- package/rules/no-id.js +11 -4
- package/rules/no-invalid-icu.d.ts +6 -3
- package/rules/no-invalid-icu.js +12 -5
- package/rules/no-literal-string-in-jsx.d.ts +13 -3
- package/rules/no-literal-string-in-jsx.js +10 -7
- package/rules/no-multiple-plurals.d.ts +6 -3
- package/rules/no-multiple-plurals.js +20 -20
- package/rules/no-multiple-whitespaces.d.ts +6 -3
- package/rules/no-multiple-whitespaces.js +10 -5
- package/rules/no-offset.d.ts +6 -3
- package/rules/no-offset.js +19 -19
- package/rules/no-useless-message.d.ts +6 -3
- package/rules/no-useless-message.js +23 -39
- package/rules/prefer-formatted-message.d.ts +6 -3
- package/rules/prefer-formatted-message.js +5 -3
- package/rules/prefer-pound-in-plural.d.ts +6 -3
- package/rules/prefer-pound-in-plural.js +10 -4
- package/util.d.ts +2 -2
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'icuError';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const name = "no-invalid-icu";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
package/rules/no-invalid-icu.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.name = void 0;
|
|
3
4
|
const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
4
5
|
const util_1 = require("../util");
|
|
6
|
+
exports.name = 'no-invalid-icu';
|
|
5
7
|
function checkNode(context, node) {
|
|
6
8
|
const settings = (0, util_1.getSettings)(context);
|
|
7
9
|
const msgs = (0, util_1.extractMessages)(node, settings);
|
|
@@ -21,24 +23,30 @@ function checkNode(context, node) {
|
|
|
21
23
|
const msg = e instanceof Error ? e.message : e;
|
|
22
24
|
context.report({
|
|
23
25
|
node: messageNode,
|
|
24
|
-
|
|
26
|
+
messageId: 'icuError',
|
|
27
|
+
data: { message: `Error parsing ICU string: ${msg}` },
|
|
25
28
|
});
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
|
-
|
|
32
|
+
exports.rule = {
|
|
30
33
|
meta: {
|
|
31
34
|
type: 'problem',
|
|
32
35
|
docs: {
|
|
33
36
|
description: `Make sure ICU messages are formatted correctly with no bad select statements, plurals, etc.`,
|
|
34
|
-
category: 'Errors',
|
|
35
|
-
recommended: true,
|
|
36
37
|
},
|
|
37
38
|
fixable: 'code',
|
|
39
|
+
schema: [],
|
|
40
|
+
messages: {
|
|
41
|
+
icuError: 'Invalid ICU Message format: {{message}}',
|
|
42
|
+
},
|
|
38
43
|
},
|
|
44
|
+
defaultOptions: [],
|
|
39
45
|
create(context) {
|
|
40
46
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
47
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
41
48
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
49
|
+
//@ts-expect-error
|
|
42
50
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
43
51
|
CallExpression: callExpressionVisitor,
|
|
44
52
|
}, {
|
|
@@ -51,4 +59,3 @@ const rule = {
|
|
|
51
59
|
};
|
|
52
60
|
},
|
|
53
61
|
};
|
|
54
|
-
exports.default = rule;
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } 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?];
|
|
11
|
+
export declare const name = "no-literal-string-in-jsx";
|
|
12
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
13
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.name = void 0;
|
|
3
4
|
const tslib_1 = require("tslib");
|
|
4
5
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
6
|
const picomatch_1 = tslib_1.__importDefault(require("picomatch"));
|
|
@@ -34,13 +35,12 @@ function compilePropMatcher(propMatcher) {
|
|
|
34
35
|
];
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
exports.name = 'no-literal-string-in-jsx';
|
|
39
|
+
exports.rule = {
|
|
38
40
|
meta: {
|
|
39
41
|
type: 'problem',
|
|
40
42
|
docs: {
|
|
41
43
|
description: 'Disallow untranslated literal strings without translation.',
|
|
42
|
-
category: 'Errors',
|
|
43
|
-
recommended: false,
|
|
44
44
|
url: 'https://formatjs.io/docs/tooling/linter#no-literal-string-in-jsx',
|
|
45
45
|
},
|
|
46
46
|
schema: [
|
|
@@ -61,7 +61,11 @@ const rule = {
|
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
63
|
],
|
|
64
|
+
messages: {
|
|
65
|
+
noLiteralStringInJsx: 'Cannot have untranslated text in JSX',
|
|
66
|
+
},
|
|
64
67
|
},
|
|
68
|
+
defaultOptions: [],
|
|
65
69
|
// TODO: Vue support
|
|
66
70
|
create(context) {
|
|
67
71
|
const userConfig = context.options[0] || {};
|
|
@@ -109,7 +113,7 @@ const rule = {
|
|
|
109
113
|
(node.quasis.length > 1 || node.quasis[0].value.raw.length > 0))) {
|
|
110
114
|
context.report({
|
|
111
115
|
node: node,
|
|
112
|
-
|
|
116
|
+
messageId: 'noLiteralStringInJsx',
|
|
113
117
|
});
|
|
114
118
|
}
|
|
115
119
|
else if (node.type === 'BinaryExpression' && node.operator === '+') {
|
|
@@ -150,7 +154,7 @@ const rule = {
|
|
|
150
154
|
node.value.value.length > 0) {
|
|
151
155
|
context.report({
|
|
152
156
|
node: node,
|
|
153
|
-
|
|
157
|
+
messageId: 'noLiteralStringInJsx',
|
|
154
158
|
});
|
|
155
159
|
}
|
|
156
160
|
else if (node.value.type === 'JSXExpressionContainer' &&
|
|
@@ -165,7 +169,7 @@ const rule = {
|
|
|
165
169
|
}
|
|
166
170
|
context.report({
|
|
167
171
|
node: node,
|
|
168
|
-
|
|
172
|
+
messageId: 'noLiteralStringInJsx',
|
|
169
173
|
});
|
|
170
174
|
},
|
|
171
175
|
// Children expression container
|
|
@@ -177,4 +181,3 @@ const rule = {
|
|
|
177
181
|
};
|
|
178
182
|
},
|
|
179
183
|
};
|
|
180
|
-
exports.default = rule;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'noMultiplePlurals';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const name = "no-multiple-plurals";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.name = void 0;
|
|
3
4
|
const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
4
5
|
const util_1 = require("../util");
|
|
5
|
-
class MultiplePlurals extends Error {
|
|
6
|
-
constructor() {
|
|
7
|
-
super(...arguments);
|
|
8
|
-
this.message = 'Cannot specify more than 1 plural rules';
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
6
|
function verifyAst(ast, pluralCount = { count: 0 }) {
|
|
7
|
+
const errors = [];
|
|
12
8
|
for (const el of ast) {
|
|
13
9
|
if ((0, icu_messageformat_parser_1.isPluralElement)(el)) {
|
|
14
10
|
pluralCount.count++;
|
|
15
11
|
if (pluralCount.count > 1) {
|
|
16
|
-
|
|
12
|
+
errors.push({ messageId: 'noMultiplePlurals', data: {} });
|
|
17
13
|
}
|
|
18
14
|
const { options } = el;
|
|
19
15
|
for (const selector of Object.keys(options)) {
|
|
20
|
-
verifyAst(options[selector].value, pluralCount);
|
|
16
|
+
errors.push(...verifyAst(options[selector].value, pluralCount));
|
|
21
17
|
}
|
|
22
18
|
}
|
|
23
19
|
}
|
|
20
|
+
return errors;
|
|
24
21
|
}
|
|
25
22
|
function checkNode(context, node) {
|
|
26
23
|
const settings = (0, util_1.getSettings)(context);
|
|
@@ -29,33 +26,37 @@ function checkNode(context, node) {
|
|
|
29
26
|
if (!defaultMessage || !messageNode) {
|
|
30
27
|
continue;
|
|
31
28
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
catch (e) {
|
|
29
|
+
const errors = verifyAst((0, icu_messageformat_parser_1.parse)(defaultMessage, {
|
|
30
|
+
ignoreTag: settings.ignoreTag,
|
|
31
|
+
}));
|
|
32
|
+
for (const error of errors) {
|
|
38
33
|
context.report({
|
|
39
|
-
node
|
|
40
|
-
|
|
34
|
+
node,
|
|
35
|
+
...error,
|
|
41
36
|
});
|
|
42
37
|
}
|
|
43
38
|
}
|
|
44
39
|
}
|
|
45
|
-
|
|
40
|
+
exports.name = 'no-multiple-plurals';
|
|
41
|
+
exports.rule = {
|
|
46
42
|
meta: {
|
|
47
43
|
type: 'problem',
|
|
48
44
|
docs: {
|
|
49
45
|
description: 'Disallow multiple plural rules in the same message',
|
|
50
|
-
category: 'Errors',
|
|
51
|
-
recommended: false,
|
|
52
46
|
url: 'https://formatjs.io/docs/tooling/linter#no-multiple-plurals',
|
|
53
47
|
},
|
|
54
48
|
fixable: 'code',
|
|
49
|
+
schema: [],
|
|
50
|
+
messages: {
|
|
51
|
+
noMultiplePlurals: 'Multiple plural rules in the same message',
|
|
52
|
+
},
|
|
55
53
|
},
|
|
54
|
+
defaultOptions: [],
|
|
56
55
|
create(context) {
|
|
57
56
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
57
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
58
58
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
59
|
+
//@ts-expect-error
|
|
59
60
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
60
61
|
CallExpression: callExpressionVisitor,
|
|
61
62
|
}, {
|
|
@@ -68,4 +69,3 @@ const rule = {
|
|
|
68
69
|
};
|
|
69
70
|
},
|
|
70
71
|
};
|
|
71
|
-
exports.default = rule;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'noMultipleWhitespaces' | 'parserError';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const name = "no-multiple-whitespaces";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.name = void 0;
|
|
3
4
|
const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
4
5
|
const util_1 = require("../util");
|
|
5
6
|
function isAstValid(ast) {
|
|
@@ -89,7 +90,8 @@ function checkNode(context, node) {
|
|
|
89
90
|
catch (e) {
|
|
90
91
|
context.report({
|
|
91
92
|
node: messageNode,
|
|
92
|
-
|
|
93
|
+
messageId: 'parserError',
|
|
94
|
+
data: { message: e instanceof Error ? e.message : String(e) },
|
|
93
95
|
});
|
|
94
96
|
return;
|
|
95
97
|
}
|
|
@@ -105,23 +107,27 @@ function checkNode(context, node) {
|
|
|
105
107
|
}
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
|
-
|
|
110
|
+
exports.name = 'no-multiple-whitespaces';
|
|
111
|
+
exports.rule = {
|
|
109
112
|
meta: {
|
|
110
113
|
type: 'problem',
|
|
111
114
|
docs: {
|
|
112
115
|
description: 'Prevents usage of multiple consecutive whitespaces in message',
|
|
113
|
-
category: 'Errors',
|
|
114
|
-
recommended: false,
|
|
115
116
|
url: 'https://formatjs.io/docs/tooling/linter#no-multiple-whitespaces',
|
|
116
117
|
},
|
|
117
118
|
messages: {
|
|
118
119
|
noMultipleWhitespaces: 'Multiple consecutive whitespaces are not allowed',
|
|
120
|
+
parserError: '{{message}}',
|
|
119
121
|
},
|
|
120
122
|
fixable: 'code',
|
|
123
|
+
schema: [],
|
|
121
124
|
},
|
|
125
|
+
defaultOptions: [],
|
|
122
126
|
create(context) {
|
|
123
127
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
128
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
124
129
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
130
|
+
//@ts-expect-error
|
|
125
131
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
126
132
|
CallExpression: callExpressionVisitor,
|
|
127
133
|
}, {
|
|
@@ -134,4 +140,3 @@ const rule = {
|
|
|
134
140
|
};
|
|
135
141
|
},
|
|
136
142
|
};
|
|
137
|
-
exports.default = rule;
|
package/rules/no-offset.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'noOffset';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const name = "no-offset";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
package/rules/no-offset.js
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.name = void 0;
|
|
3
4
|
const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
4
5
|
const util_1 = require("../util");
|
|
5
|
-
class NoOffsetError extends Error {
|
|
6
|
-
constructor() {
|
|
7
|
-
super(...arguments);
|
|
8
|
-
this.message = 'offset are not allowed in plural rules';
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
6
|
function verifyAst(ast) {
|
|
7
|
+
const errors = [];
|
|
12
8
|
for (const el of ast) {
|
|
13
9
|
if ((0, icu_messageformat_parser_1.isPluralElement)(el)) {
|
|
14
10
|
if (el.offset) {
|
|
15
|
-
|
|
11
|
+
errors.push({ messageId: 'noOffset', data: {} });
|
|
16
12
|
}
|
|
17
13
|
const { options } = el;
|
|
18
14
|
for (const selector of Object.keys(options)) {
|
|
19
|
-
verifyAst(options[selector].value);
|
|
15
|
+
errors.push(...verifyAst(options[selector].value));
|
|
20
16
|
}
|
|
21
17
|
}
|
|
22
18
|
}
|
|
19
|
+
return errors;
|
|
23
20
|
}
|
|
24
21
|
function checkNode(context, node) {
|
|
25
22
|
const settings = (0, util_1.getSettings)(context);
|
|
@@ -28,33 +25,37 @@ function checkNode(context, node) {
|
|
|
28
25
|
if (!defaultMessage || !messageNode) {
|
|
29
26
|
continue;
|
|
30
27
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
catch (e) {
|
|
28
|
+
const errors = verifyAst((0, icu_messageformat_parser_1.parse)(defaultMessage, {
|
|
29
|
+
ignoreTag: settings.ignoreTag,
|
|
30
|
+
}));
|
|
31
|
+
for (const error of errors) {
|
|
37
32
|
context.report({
|
|
38
33
|
node: messageNode,
|
|
39
|
-
|
|
34
|
+
...error,
|
|
40
35
|
});
|
|
41
36
|
}
|
|
42
37
|
}
|
|
43
38
|
}
|
|
44
|
-
|
|
39
|
+
exports.name = 'no-offset';
|
|
40
|
+
exports.rule = {
|
|
45
41
|
meta: {
|
|
46
42
|
type: 'problem',
|
|
47
43
|
docs: {
|
|
48
44
|
description: 'Disallow offset in plural rules',
|
|
49
|
-
category: 'Errors',
|
|
50
|
-
recommended: false,
|
|
51
45
|
url: 'https://formatjs.io/docs/tooling/linter#no-offset',
|
|
52
46
|
},
|
|
53
47
|
fixable: 'code',
|
|
48
|
+
messages: {
|
|
49
|
+
noOffset: 'offset is not allowed',
|
|
50
|
+
},
|
|
51
|
+
schema: [],
|
|
54
52
|
},
|
|
53
|
+
defaultOptions: [],
|
|
55
54
|
create(context) {
|
|
56
55
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
56
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
57
57
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
58
|
+
//@ts-expect-error
|
|
58
59
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
59
60
|
CallExpression: callExpressionVisitor,
|
|
60
61
|
}, {
|
|
@@ -67,4 +68,3 @@ const rule = {
|
|
|
67
68
|
};
|
|
68
69
|
},
|
|
69
70
|
};
|
|
70
|
-
exports.default = rule;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'unnecessaryFormat' | 'unnecessaryFormatNumber' | 'unnecessaryFormatDate' | 'unnecessaryFormatTime';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const name = "no-useless-message";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
|
@@ -1,44 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.name = void 0;
|
|
3
4
|
const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
4
5
|
const util_1 = require("../util");
|
|
5
|
-
class JustArgument extends Error {
|
|
6
|
-
constructor() {
|
|
7
|
-
super(...arguments);
|
|
8
|
-
this.message = 'Unnecessary formatted message.';
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
class JustNumber extends Error {
|
|
12
|
-
constructor() {
|
|
13
|
-
super(...arguments);
|
|
14
|
-
this.message = 'Unnecessary formatted message: just use FormattedNumber or intl.formatNumber.';
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
class JustDate extends Error {
|
|
18
|
-
constructor() {
|
|
19
|
-
super(...arguments);
|
|
20
|
-
this.message = 'Unnecessary formatted message: just use FormattedDate or intl.formatDate.';
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
class JustTime extends Error {
|
|
24
|
-
constructor() {
|
|
25
|
-
super(...arguments);
|
|
26
|
-
this.message = 'Unnecessary formatted message: just use FormattedTime or intl.formatTime.';
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
6
|
function verifyAst(ast) {
|
|
30
7
|
if (ast.length !== 1) {
|
|
31
8
|
return;
|
|
32
9
|
}
|
|
33
10
|
switch (ast[0].type) {
|
|
34
11
|
case icu_messageformat_parser_1.TYPE.argument:
|
|
35
|
-
|
|
12
|
+
return 'unnecessaryFormat';
|
|
36
13
|
case icu_messageformat_parser_1.TYPE.number:
|
|
37
|
-
|
|
14
|
+
return 'unnecessaryFormatNumber';
|
|
38
15
|
case icu_messageformat_parser_1.TYPE.date:
|
|
39
|
-
|
|
16
|
+
return 'unnecessaryFormatDate';
|
|
40
17
|
case icu_messageformat_parser_1.TYPE.time:
|
|
41
|
-
|
|
18
|
+
return 'unnecessaryFormatTime';
|
|
42
19
|
}
|
|
43
20
|
}
|
|
44
21
|
function checkNode(context, node) {
|
|
@@ -48,32 +25,40 @@ function checkNode(context, node) {
|
|
|
48
25
|
if (!defaultMessage || !messageNode) {
|
|
49
26
|
continue;
|
|
50
27
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
catch (e) {
|
|
28
|
+
const messageId = verifyAst((0, icu_messageformat_parser_1.parse)(defaultMessage, {
|
|
29
|
+
ignoreTag: settings.ignoreTag,
|
|
30
|
+
}));
|
|
31
|
+
if (messageId)
|
|
57
32
|
context.report({
|
|
58
33
|
node: messageNode,
|
|
59
|
-
|
|
34
|
+
messageId,
|
|
60
35
|
});
|
|
61
|
-
}
|
|
62
36
|
}
|
|
63
37
|
}
|
|
64
|
-
|
|
38
|
+
exports.name = 'no-useless-message';
|
|
39
|
+
exports.rule = {
|
|
65
40
|
meta: {
|
|
66
41
|
type: 'problem',
|
|
67
42
|
docs: {
|
|
68
43
|
description: 'Disallow unnecessary formatted message',
|
|
69
|
-
recommended:
|
|
44
|
+
recommended: 'recommended',
|
|
70
45
|
url: 'https://formatjs.io/docs/tooling/linter#no-useless-message',
|
|
71
46
|
},
|
|
72
47
|
fixable: 'code',
|
|
48
|
+
schema: [],
|
|
49
|
+
messages: {
|
|
50
|
+
unnecessaryFormat: 'Unnecessary formatted message.',
|
|
51
|
+
unnecessaryFormatNumber: 'Unnecessary formatted message: just use FormattedNumber or intl.formatNumber.',
|
|
52
|
+
unnecessaryFormatDate: 'Unnecessary formatted message: just use FormattedDate or intl.formatDate.',
|
|
53
|
+
unnecessaryFormatTime: 'Unnecessary formatted message: just use FormattedTime or intl.formatTime.',
|
|
54
|
+
},
|
|
73
55
|
},
|
|
56
|
+
defaultOptions: [],
|
|
74
57
|
create(context) {
|
|
75
58
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
59
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
76
60
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
61
|
+
//@ts-expect-error
|
|
77
62
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
78
63
|
CallExpression: callExpressionVisitor,
|
|
79
64
|
}, {
|
|
@@ -86,4 +71,3 @@ const rule = {
|
|
|
86
71
|
};
|
|
87
72
|
},
|
|
88
73
|
};
|
|
89
|
-
exports.default = rule;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'jsxChildren';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const name = "prefer-formatted-message";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.name = void 0;
|
|
3
4
|
const util_1 = require("../util");
|
|
4
|
-
|
|
5
|
+
exports.name = 'prefer-formatted-message';
|
|
6
|
+
exports.rule = {
|
|
5
7
|
meta: {
|
|
6
8
|
type: 'suggestion',
|
|
7
9
|
docs: {
|
|
8
10
|
description: 'Prefer `FormattedMessage` component over `intl.formatMessage` if applicable.',
|
|
9
|
-
recommended: false,
|
|
10
11
|
url: 'https://formatjs.io/docs/tooling/linter#prefer-formatted-message',
|
|
11
12
|
},
|
|
12
13
|
messages: {
|
|
13
14
|
jsxChildren: 'Prefer `FormattedMessage` over `intl.formatMessage` in the JSX children expression.',
|
|
14
15
|
},
|
|
16
|
+
schema: [],
|
|
15
17
|
},
|
|
18
|
+
defaultOptions: [],
|
|
16
19
|
// TODO: Vue support
|
|
17
20
|
create(context) {
|
|
18
21
|
return {
|
|
@@ -31,4 +34,3 @@ const rule = {
|
|
|
31
34
|
};
|
|
32
35
|
},
|
|
33
36
|
};
|
|
34
|
-
exports.default = rule;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'preferPoundInPlurals' | 'parseError';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const name = "prefer-pound-in-plural";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rule = exports.name = void 0;
|
|
3
4
|
const tslib_1 = require("tslib");
|
|
4
5
|
const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
5
6
|
const magic_string_1 = tslib_1.__importDefault(require("magic-string"));
|
|
@@ -148,30 +149,36 @@ function checkNode(context, node) {
|
|
|
148
149
|
catch (e) {
|
|
149
150
|
context.report({
|
|
150
151
|
node: messageNode,
|
|
151
|
-
|
|
152
|
+
messageId: 'parseError',
|
|
153
|
+
data: { message: e instanceof Error ? e.message : String(e) },
|
|
152
154
|
});
|
|
153
155
|
return;
|
|
154
156
|
}
|
|
155
157
|
verifyAst(context, messageNode, ast);
|
|
156
158
|
}
|
|
157
159
|
}
|
|
158
|
-
|
|
160
|
+
exports.name = 'prefer-pound-in-plural';
|
|
161
|
+
exports.rule = {
|
|
159
162
|
meta: {
|
|
160
163
|
type: 'suggestion',
|
|
161
164
|
docs: {
|
|
162
165
|
description: 'Prefer using # to reference the count in the plural argument.',
|
|
163
|
-
recommended: false,
|
|
164
166
|
url: 'https://formatjs.io/docs/tooling/linter#prefer-pound-in-plurals',
|
|
165
167
|
},
|
|
166
168
|
messages: {
|
|
167
169
|
preferPoundInPlurals: 'Prefer using # to reference the count in the plural argument instead of repeating the argument.',
|
|
170
|
+
parseError: '{{message}}',
|
|
168
171
|
},
|
|
169
172
|
fixable: 'code',
|
|
173
|
+
schema: [],
|
|
170
174
|
},
|
|
175
|
+
defaultOptions: [],
|
|
171
176
|
// TODO: Vue support
|
|
172
177
|
create(context) {
|
|
173
178
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
179
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
174
180
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
181
|
+
//@ts-expect-error
|
|
175
182
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
176
183
|
CallExpression: callExpressionVisitor,
|
|
177
184
|
}, {
|
|
@@ -184,4 +191,3 @@ const rule = {
|
|
|
184
191
|
};
|
|
185
192
|
},
|
|
186
193
|
};
|
|
187
|
-
exports.default = rule;
|
package/util.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MessageFormatElement } from '@formatjs/icu-messageformat-parser';
|
|
2
2
|
import { TSESTree } from '@typescript-eslint/utils';
|
|
3
|
-
import {
|
|
3
|
+
import { RuleContext } from '@typescript-eslint/utils/ts-eslint';
|
|
4
4
|
export interface MessageDescriptor {
|
|
5
5
|
id?: string;
|
|
6
6
|
defaultMessage?: string;
|
|
@@ -20,7 +20,7 @@ export interface MessageDescriptorNodeInfo {
|
|
|
20
20
|
idValueNode?: TSESTree.Property['value'] | TSESTree.JSXAttribute['value'];
|
|
21
21
|
idPropNode?: TSESTree.Property | TSESTree.JSXAttribute;
|
|
22
22
|
}
|
|
23
|
-
export declare function getSettings({ settings }:
|
|
23
|
+
export declare function getSettings<TMessageIds extends string, TOptions extends readonly unknown[]>({ settings }: RuleContext<TMessageIds, TOptions>): Settings;
|
|
24
24
|
export declare function isIntlFormatMessageCall(node: TSESTree.Node): node is TSESTree.CallExpression;
|
|
25
25
|
export declare function extractMessageDescriptor(node?: TSESTree.Expression): MessageDescriptorNodeInfo | undefined;
|
|
26
26
|
export declare function extractMessages(node: TSESTree.Node, { additionalComponentNames, additionalFunctionNames, excludeMessageDeclCalls, }?: Settings): Array<[MessageDescriptorNodeInfo, TSESTree.Expression | undefined]>;
|