eslint-plugin-formatjs 4.11.3 → 4.12.1
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.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,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'parserError' | 'missingValue' | 'unusedValue';
|
|
3
|
+
type Options = [{
|
|
4
|
+
ignoreList: string[];
|
|
5
|
+
}?];
|
|
6
|
+
export declare const name = "enforce-placeholders";
|
|
7
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
8
|
+
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 collectPlaceholderNames(ast) {
|
|
@@ -68,7 +69,8 @@ function checkNode(context, node) {
|
|
|
68
69
|
catch (e) {
|
|
69
70
|
context.report({
|
|
70
71
|
node: messageNode,
|
|
71
|
-
|
|
72
|
+
messageId: 'parserError',
|
|
73
|
+
data: { message: e instanceof Error ? e.message : String(e) },
|
|
72
74
|
});
|
|
73
75
|
continue;
|
|
74
76
|
}
|
|
@@ -82,26 +84,28 @@ function checkNode(context, node) {
|
|
|
82
84
|
if (missingPlaceholders.length > 0) {
|
|
83
85
|
context.report({
|
|
84
86
|
node: messageNode,
|
|
85
|
-
|
|
87
|
+
messageId: 'missingValue',
|
|
88
|
+
data: {
|
|
89
|
+
list: missingPlaceholders.join(', '),
|
|
90
|
+
},
|
|
86
91
|
});
|
|
87
92
|
}
|
|
88
93
|
literalElementByLiteralKey.forEach((element, key) => {
|
|
89
94
|
if (!ignoreList.has(key) && !placeholderNames.has(key)) {
|
|
90
95
|
context.report({
|
|
91
96
|
node: element,
|
|
92
|
-
|
|
97
|
+
messageId: 'unusedValue',
|
|
93
98
|
});
|
|
94
99
|
}
|
|
95
100
|
});
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
|
-
|
|
103
|
+
exports.name = 'enforce-placeholders';
|
|
104
|
+
exports.rule = {
|
|
99
105
|
meta: {
|
|
100
106
|
type: 'problem',
|
|
101
107
|
docs: {
|
|
102
108
|
description: 'Enforce that all messages with placeholders have enough passed-in values',
|
|
103
|
-
category: 'Errors',
|
|
104
|
-
recommended: true,
|
|
105
109
|
url: 'https://formatjs.io/docs/tooling/linter#enforce-placeholders',
|
|
106
110
|
},
|
|
107
111
|
schema: [
|
|
@@ -118,10 +122,18 @@ const rule = {
|
|
|
118
122
|
additionalProperties: false,
|
|
119
123
|
},
|
|
120
124
|
],
|
|
125
|
+
messages: {
|
|
126
|
+
parserError: '{{message}}',
|
|
127
|
+
missingValue: 'Missing value(s) for the following placeholder(s): {{list}}.',
|
|
128
|
+
unusedValue: 'Value not used by the message.',
|
|
129
|
+
},
|
|
121
130
|
},
|
|
131
|
+
defaultOptions: [],
|
|
122
132
|
create(context) {
|
|
123
133
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
134
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
124
135
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
136
|
+
//@ts-expect-error
|
|
125
137
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
126
138
|
CallExpression: callExpressionVisitor,
|
|
127
139
|
}, {
|
|
@@ -134,4 +146,3 @@ const rule = {
|
|
|
134
146
|
};
|
|
135
147
|
},
|
|
136
148
|
};
|
|
137
|
-
exports.default = rule;
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
declare enum LDML {
|
|
3
|
+
zero = "zero",
|
|
4
|
+
one = "one",
|
|
5
|
+
two = "two",
|
|
6
|
+
few = "few",
|
|
7
|
+
many = "many",
|
|
8
|
+
other = "other"
|
|
9
|
+
}
|
|
10
|
+
type PluralConfig = {
|
|
11
|
+
[key in LDML]?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type Options = [PluralConfig?];
|
|
14
|
+
type MessageIds = 'missingPlural' | 'forbidden';
|
|
15
|
+
export declare const name = "enforce-plural-rules";
|
|
16
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
17
|
+
export {};
|
|
@@ -1,13 +1,8 @@
|
|
|
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 PluralRulesEnforcement extends Error {
|
|
6
|
-
constructor(message) {
|
|
7
|
-
super();
|
|
8
|
-
this.message = message;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
6
|
var LDML;
|
|
12
7
|
(function (LDML) {
|
|
13
8
|
LDML["zero"] = "zero";
|
|
@@ -18,23 +13,25 @@ var LDML;
|
|
|
18
13
|
LDML["other"] = "other";
|
|
19
14
|
})(LDML || (LDML = {}));
|
|
20
15
|
function verifyAst(plConfig, ast) {
|
|
16
|
+
const errors = [];
|
|
21
17
|
for (const el of ast) {
|
|
22
18
|
if ((0, icu_messageformat_parser_1.isPluralElement)(el)) {
|
|
23
19
|
const rules = Object.keys(plConfig);
|
|
24
20
|
for (const rule of rules) {
|
|
25
21
|
if (plConfig[rule] && !el.options[rule]) {
|
|
26
|
-
|
|
22
|
+
errors.push({ messageId: 'missingPlural', data: { rule } });
|
|
27
23
|
}
|
|
28
24
|
if (!plConfig[rule] && el.options[rule]) {
|
|
29
|
-
|
|
25
|
+
errors.push({ messageId: 'forbidden', data: { rule } });
|
|
30
26
|
}
|
|
31
27
|
}
|
|
32
28
|
const { options } = el;
|
|
33
29
|
for (const selector of Object.keys(options)) {
|
|
34
|
-
verifyAst(plConfig, options[selector].value);
|
|
30
|
+
errors.push(...verifyAst(plConfig, options[selector].value));
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
33
|
}
|
|
34
|
+
return errors;
|
|
38
35
|
}
|
|
39
36
|
function checkNode(context, node) {
|
|
40
37
|
const settings = (0, util_1.getSettings)(context);
|
|
@@ -50,26 +47,23 @@ function checkNode(context, node) {
|
|
|
50
47
|
if (!defaultMessage || !messageNode) {
|
|
51
48
|
continue;
|
|
52
49
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
catch (e) {
|
|
50
|
+
const errors = verifyAst(plConfig, (0, icu_messageformat_parser_1.parse)(defaultMessage, {
|
|
51
|
+
ignoreTag: settings.ignoreTag,
|
|
52
|
+
}));
|
|
53
|
+
for (const error of errors) {
|
|
59
54
|
context.report({
|
|
60
55
|
node: messageNode,
|
|
61
|
-
|
|
56
|
+
...error,
|
|
62
57
|
});
|
|
63
58
|
}
|
|
64
59
|
}
|
|
65
60
|
}
|
|
66
|
-
|
|
61
|
+
exports.name = 'enforce-plural-rules';
|
|
62
|
+
exports.rule = {
|
|
67
63
|
meta: {
|
|
68
64
|
type: 'problem',
|
|
69
65
|
docs: {
|
|
70
66
|
description: 'Enforce plural rules to always specify certain categories like `one`/`other`',
|
|
71
|
-
category: 'Errors',
|
|
72
|
-
recommended: false,
|
|
73
67
|
url: 'https://formatjs.io/docs/tooling/linter#enforce-plural-rules',
|
|
74
68
|
},
|
|
75
69
|
fixable: 'code',
|
|
@@ -85,10 +79,17 @@ const rule = {
|
|
|
85
79
|
additionalProperties: false,
|
|
86
80
|
},
|
|
87
81
|
],
|
|
82
|
+
messages: {
|
|
83
|
+
missingPlural: `Missing plural rule "{{rule}}"`,
|
|
84
|
+
forbidden: `Plural rule "{{rule}}" is forbidden`,
|
|
85
|
+
},
|
|
88
86
|
},
|
|
87
|
+
defaultOptions: [],
|
|
89
88
|
create(context) {
|
|
90
89
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
90
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
91
91
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
92
|
+
//@ts-expect-error
|
|
92
93
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
93
94
|
CallExpression: callExpressionVisitor,
|
|
94
95
|
}, {
|
|
@@ -101,4 +102,3 @@ const rule = {
|
|
|
101
102
|
};
|
|
102
103
|
},
|
|
103
104
|
};
|
|
104
|
-
exports.default = rule;
|
package/rules/no-camel-case.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'camelcase';
|
|
3
|
+
type Options = [Element[]?];
|
|
4
|
+
export declare const name = "no-camel-case";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
package/rules/no-camel-case.js
CHANGED
|
@@ -1,32 +1,30 @@
|
|
|
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-camel-case';
|
|
5
7
|
const CAMEL_CASE_REGEX = /[A-Z]/;
|
|
6
|
-
class CamelCase extends Error {
|
|
7
|
-
constructor() {
|
|
8
|
-
super(...arguments);
|
|
9
|
-
this.message = 'Camel case arguments are not allowed';
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
8
|
function verifyAst(ast) {
|
|
9
|
+
const errors = [];
|
|
13
10
|
for (const el of ast) {
|
|
14
11
|
if ((0, icu_messageformat_parser_1.isArgumentElement)(el)) {
|
|
15
12
|
if (CAMEL_CASE_REGEX.test(el.value)) {
|
|
16
|
-
|
|
13
|
+
errors.push({ messageId: 'camelcase', data: {} });
|
|
17
14
|
}
|
|
18
15
|
continue;
|
|
19
16
|
}
|
|
20
17
|
if ((0, icu_messageformat_parser_1.isPluralElement)(el)) {
|
|
21
18
|
if (CAMEL_CASE_REGEX.test(el.value)) {
|
|
22
|
-
|
|
19
|
+
errors.push({ messageId: 'camelcase', data: {} });
|
|
23
20
|
}
|
|
24
21
|
const { options } = el;
|
|
25
22
|
for (const selector of Object.keys(options)) {
|
|
26
|
-
verifyAst(options[selector].value);
|
|
23
|
+
errors.push(...verifyAst(options[selector].value));
|
|
27
24
|
}
|
|
28
25
|
}
|
|
29
26
|
}
|
|
27
|
+
return errors;
|
|
30
28
|
}
|
|
31
29
|
function checkNode(context, node) {
|
|
32
30
|
const settings = (0, util_1.getSettings)(context);
|
|
@@ -35,33 +33,36 @@ function checkNode(context, node) {
|
|
|
35
33
|
if (!defaultMessage || !messageNode) {
|
|
36
34
|
continue;
|
|
37
35
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
catch (e) {
|
|
36
|
+
const errors = verifyAst((0, icu_messageformat_parser_1.parse)(defaultMessage, {
|
|
37
|
+
ignoreTag: settings.ignoreTag,
|
|
38
|
+
}));
|
|
39
|
+
for (const error of errors) {
|
|
44
40
|
context.report({
|
|
45
41
|
node: messageNode,
|
|
46
|
-
|
|
42
|
+
...error,
|
|
47
43
|
});
|
|
48
44
|
}
|
|
49
45
|
}
|
|
50
46
|
}
|
|
51
|
-
|
|
47
|
+
exports.rule = {
|
|
52
48
|
meta: {
|
|
53
49
|
type: 'problem',
|
|
54
50
|
docs: {
|
|
55
51
|
description: 'Disallow camel case placeholders in message',
|
|
56
|
-
category: 'Errors',
|
|
57
|
-
recommended: false,
|
|
58
52
|
url: 'https://formatjs.io/docs/tooling/linter#no-camel-case',
|
|
59
53
|
},
|
|
60
54
|
fixable: 'code',
|
|
55
|
+
schema: [],
|
|
56
|
+
messages: {
|
|
57
|
+
camelcase: 'Camel case arguments are not allowed',
|
|
58
|
+
},
|
|
61
59
|
},
|
|
60
|
+
defaultOptions: [],
|
|
62
61
|
create(context) {
|
|
63
62
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
63
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
64
64
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
65
|
+
//@ts-expect-error
|
|
65
66
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
66
67
|
CallExpression: callExpressionVisitor,
|
|
67
68
|
}, {
|
|
@@ -74,4 +75,3 @@ const rule = {
|
|
|
74
75
|
};
|
|
75
76
|
},
|
|
76
77
|
};
|
|
77
|
-
exports.default = rule;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
interface Config {
|
|
3
|
+
limit: number;
|
|
4
|
+
}
|
|
5
|
+
type MessageIds = 'tooComplex' | 'parserError';
|
|
6
|
+
type Options = [Config?];
|
|
7
|
+
export declare const name = "no-complex-selectors";
|
|
8
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
9
|
+
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 calculateComplexity(ast) {
|
|
@@ -65,29 +66,26 @@ function checkNode(context, node) {
|
|
|
65
66
|
catch (e) {
|
|
66
67
|
context.report({
|
|
67
68
|
node: messageNode,
|
|
68
|
-
|
|
69
|
+
messageId: 'parserError',
|
|
70
|
+
data: { message: e instanceof Error ? e.message : String(e) },
|
|
69
71
|
});
|
|
70
72
|
return;
|
|
71
73
|
}
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
complexity = calculateComplexity(ast);
|
|
75
|
-
}
|
|
76
|
-
catch (e) {
|
|
77
|
-
context.report({
|
|
78
|
-
node: messageNode,
|
|
79
|
-
message: e instanceof Error ? e.message : e,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
74
|
+
const complexity = calculateComplexity(ast);
|
|
82
75
|
if (complexity > config.limit) {
|
|
83
76
|
context.report({
|
|
84
77
|
node: messageNode,
|
|
85
|
-
|
|
78
|
+
messageId: 'tooComplex',
|
|
79
|
+
data: {
|
|
80
|
+
complexity,
|
|
81
|
+
limit: config.limit,
|
|
82
|
+
},
|
|
86
83
|
});
|
|
87
84
|
}
|
|
88
85
|
}
|
|
89
86
|
}
|
|
90
|
-
|
|
87
|
+
exports.name = 'no-complex-selectors';
|
|
88
|
+
exports.rule = {
|
|
91
89
|
meta: {
|
|
92
90
|
type: 'problem',
|
|
93
91
|
docs: {
|
|
@@ -100,8 +98,6 @@ results in 2 sentences: "I have a dog" & "I have many dogs".
|
|
|
100
98
|
Default complexity limit is 20
|
|
101
99
|
(using Smartling as a reference: https://help.smartling.com/hc/en-us/articles/360008030994-ICU-MessageFormat)
|
|
102
100
|
`,
|
|
103
|
-
category: 'Errors',
|
|
104
|
-
recommended: false,
|
|
105
101
|
url: 'https://formatjs.io/docs/tooling/linter#no-complex-selectors',
|
|
106
102
|
},
|
|
107
103
|
schema: [
|
|
@@ -116,10 +112,17 @@ Default complexity limit is 20
|
|
|
116
112
|
},
|
|
117
113
|
],
|
|
118
114
|
fixable: 'code',
|
|
115
|
+
messages: {
|
|
116
|
+
tooComplex: `Message complexity is too high ({{complexity}} vs limit at {{limit}})`,
|
|
117
|
+
parserError: '{{meesage}}',
|
|
118
|
+
},
|
|
119
119
|
},
|
|
120
|
+
defaultOptions: [{ limit: 20 }],
|
|
120
121
|
create(context) {
|
|
121
122
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
123
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
122
124
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
125
|
+
//@ts-expect-error
|
|
123
126
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
124
127
|
CallExpression: callExpressionVisitor,
|
|
125
128
|
}, {
|
|
@@ -132,4 +135,3 @@ Default complexity limit is 20
|
|
|
132
135
|
};
|
|
133
136
|
},
|
|
134
137
|
};
|
|
135
|
-
exports.default = rule;
|
package/rules/no-emoji.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare const
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
export declare const name = "no-emoji";
|
|
3
|
+
type MessageIds = 'notAllowed' | 'notAllowedAboveVersion';
|
|
4
|
+
type NoEmojiConfig = {
|
|
5
|
+
versionAbove: string;
|
|
6
|
+
};
|
|
7
|
+
export type Options = [NoEmojiConfig?];
|
|
8
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
9
|
+
export {};
|
package/rules/no-emoji.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 unicode_emoji_utils_1 = require("unicode-emoji-utils");
|
|
4
5
|
const util_1 = require("../util");
|
|
6
|
+
exports.name = 'no-emoji';
|
|
5
7
|
function checkNode(context, node) {
|
|
6
8
|
const msgs = (0, util_1.extractMessages)(node, (0, util_1.getSettings)(context));
|
|
7
9
|
let allowedEmojis = [];
|
|
@@ -58,13 +60,11 @@ const versionAboveEnums = [
|
|
|
58
60
|
'14.0',
|
|
59
61
|
'15.0',
|
|
60
62
|
];
|
|
61
|
-
|
|
63
|
+
exports.rule = {
|
|
62
64
|
meta: {
|
|
63
65
|
type: 'problem',
|
|
64
66
|
docs: {
|
|
65
67
|
description: 'Disallow emojis in message',
|
|
66
|
-
category: 'Errors',
|
|
67
|
-
recommended: false,
|
|
68
68
|
url: 'https://formatjs.io/docs/tooling/linter#no-emoji',
|
|
69
69
|
},
|
|
70
70
|
fixable: 'code',
|
|
@@ -80,9 +80,12 @@ const rule = {
|
|
|
80
80
|
notAllowedAboveVersion: 'Emojis above version {{versionAbove}} are not allowed - Emoji: {{emoji}}',
|
|
81
81
|
},
|
|
82
82
|
},
|
|
83
|
+
defaultOptions: [],
|
|
83
84
|
create(context) {
|
|
84
85
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
86
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
85
87
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
88
|
+
//@ts-expect-error
|
|
86
89
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
87
90
|
CallExpression: callExpressionVisitor,
|
|
88
91
|
}, {
|
|
@@ -95,4 +98,3 @@ const rule = {
|
|
|
95
98
|
};
|
|
96
99
|
},
|
|
97
100
|
};
|
|
98
|
-
exports.default = rule;
|
package/rules/no-id.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { RuleModule, RuleListener } from '@typescript-eslint/utils/ts-eslint';
|
|
2
|
+
type MessageIds = 'noId';
|
|
3
|
+
type Options = [];
|
|
4
|
+
export declare const name = "no-id";
|
|
5
|
+
export declare const rule: RuleModule<MessageIds, Options, RuleListener>;
|
|
6
|
+
export {};
|
package/rules/no-id.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
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
|
function isComment(token) {
|
|
5
6
|
return !!token && (token.type === 'Block' || token.type === 'Line');
|
|
6
7
|
}
|
|
8
|
+
exports.name = 'no-id';
|
|
7
9
|
function checkNode(context, node) {
|
|
8
10
|
const msgs = (0, util_1.extractMessages)(node, (0, util_1.getSettings)(context));
|
|
9
11
|
for (const [{ idPropNode }] of msgs) {
|
|
10
12
|
if (idPropNode) {
|
|
11
13
|
context.report({
|
|
12
14
|
node: idPropNode,
|
|
13
|
-
|
|
15
|
+
messageId: 'noId',
|
|
14
16
|
fix(fixer) {
|
|
15
17
|
const src = context.getSourceCode();
|
|
16
18
|
const token = src.getTokenAfter(idPropNode);
|
|
@@ -24,20 +26,25 @@ function checkNode(context, node) {
|
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
exports.
|
|
29
|
+
exports.rule = {
|
|
28
30
|
meta: {
|
|
29
31
|
type: 'problem',
|
|
30
32
|
docs: {
|
|
31
33
|
description: 'Ban explicit ID from MessageDescriptor',
|
|
32
|
-
category: 'Errors',
|
|
33
|
-
recommended: false,
|
|
34
34
|
url: 'https://formatjs.io/docs/tooling/linter#no-id',
|
|
35
35
|
},
|
|
36
36
|
fixable: 'code',
|
|
37
|
+
schema: [],
|
|
38
|
+
messages: {
|
|
39
|
+
noId: 'Manual `id` are not allowed in message descriptor',
|
|
40
|
+
},
|
|
37
41
|
},
|
|
42
|
+
defaultOptions: [],
|
|
38
43
|
create(context) {
|
|
39
44
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
45
|
+
//@ts-expect-error defineTemplateBodyVisitor exists in Vue parser
|
|
40
46
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
47
|
+
//@ts-expect-error
|
|
41
48
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
42
49
|
CallExpression: callExpressionVisitor,
|
|
43
50
|
}, {
|
|
@@ -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;
|