eslint-plugin-formatjs 4.4.0 → 4.6.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/index.js
CHANGED
|
@@ -34,7 +34,7 @@ const plugin = {
|
|
|
34
34
|
'no-multiple-plurals': no_multiple_plurals_1.default,
|
|
35
35
|
'no-multiple-whitespaces': no_multiple_whitespaces_1.default,
|
|
36
36
|
'no-offset': no_offset_1.default,
|
|
37
|
-
'no-useless-message': no_useless_message_1.default
|
|
38
|
-
}
|
|
37
|
+
'no-useless-message': no_useless_message_1.default,
|
|
38
|
+
},
|
|
39
39
|
};
|
|
40
40
|
module.exports = plugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-formatjs",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "ESLint plugin for formatjs",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -20,15 +20,16 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://github.com/formatjs/formatjs#readme",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@formatjs/icu-messageformat-parser": "2.
|
|
24
|
-
"@formatjs/ts-transformer": "3.11.
|
|
23
|
+
"@formatjs/icu-messageformat-parser": "2.2.0",
|
|
24
|
+
"@formatjs/ts-transformer": "3.11.6",
|
|
25
25
|
"@types/eslint": "7 || 8",
|
|
26
26
|
"@types/picomatch": "^2.3.0",
|
|
27
|
-
"@typescript-eslint/typescript-estree": "
|
|
28
|
-
"emoji-regex": "^10.
|
|
27
|
+
"@typescript-eslint/typescript-estree": "5.45.0",
|
|
28
|
+
"emoji-regex": "^10.2.1",
|
|
29
29
|
"picomatch": "^2.3.1",
|
|
30
|
-
"tslib": "
|
|
31
|
-
"typescript": "^4.7"
|
|
30
|
+
"tslib": "2.4.0",
|
|
31
|
+
"typescript": "^4.7",
|
|
32
|
+
"unicode-emoji-utils": "^1.1.1"
|
|
32
33
|
},
|
|
33
34
|
"peerDependencies": {
|
|
34
35
|
"eslint": "7 || 8"
|
package/rules/no-emoji.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-emoji.d.ts","sourceRoot":"","sources":["no-emoji.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"no-emoji.d.ts","sourceRoot":"","sources":["no-emoji.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AA+E3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA0ChB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
package/rules/no-emoji.js
CHANGED
|
@@ -1,23 +1,63 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
3
|
const util_1 = require("../util");
|
|
5
|
-
const
|
|
6
|
-
const EMOJI_REGEX = emoji_regex_1.default();
|
|
4
|
+
const unicode_emoji_utils_1 = require("unicode-emoji-utils");
|
|
7
5
|
function checkNode(context, node) {
|
|
8
6
|
const msgs = (0, util_1.extractMessages)(node, (0, util_1.getSettings)(context));
|
|
7
|
+
let allowedEmojis = [];
|
|
8
|
+
let versionAbove;
|
|
9
|
+
const [emojiConfig] = context.options;
|
|
10
|
+
if (emojiConfig?.versionAbove &&
|
|
11
|
+
(0, unicode_emoji_utils_1.isValidEmojiVersion)(emojiConfig.versionAbove) &&
|
|
12
|
+
!versionAbove &&
|
|
13
|
+
allowedEmojis.length === 0) {
|
|
14
|
+
versionAbove = emojiConfig.versionAbove;
|
|
15
|
+
allowedEmojis = (0, unicode_emoji_utils_1.getAllEmojis)((0, unicode_emoji_utils_1.filterEmojis)(versionAbove));
|
|
16
|
+
}
|
|
9
17
|
for (const [{ message: { defaultMessage }, messageNode, },] of msgs) {
|
|
10
18
|
if (!defaultMessage || !messageNode) {
|
|
11
19
|
continue;
|
|
12
20
|
}
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
if ((0, unicode_emoji_utils_1.hasEmoji)(defaultMessage)) {
|
|
22
|
+
if (versionAbove) {
|
|
23
|
+
for (const emoji of (0, unicode_emoji_utils_1.extractEmojis)(defaultMessage)) {
|
|
24
|
+
if (!allowedEmojis.includes(emoji)) {
|
|
25
|
+
context.report({
|
|
26
|
+
node: messageNode,
|
|
27
|
+
messageId: 'notAllowedAboveVersion',
|
|
28
|
+
data: {
|
|
29
|
+
versionAbove,
|
|
30
|
+
emoji,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
context.report({
|
|
38
|
+
node: messageNode,
|
|
39
|
+
messageId: 'notAllowed',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
18
42
|
}
|
|
19
43
|
}
|
|
20
44
|
}
|
|
45
|
+
const versionAboveEnums = [
|
|
46
|
+
'0.6',
|
|
47
|
+
'0.7',
|
|
48
|
+
'1.0',
|
|
49
|
+
'2.0',
|
|
50
|
+
'3.0',
|
|
51
|
+
'4.0',
|
|
52
|
+
'5.0',
|
|
53
|
+
'11.0',
|
|
54
|
+
'12.0',
|
|
55
|
+
'12.1',
|
|
56
|
+
'13.0',
|
|
57
|
+
'13.1',
|
|
58
|
+
'14.0',
|
|
59
|
+
'15.0',
|
|
60
|
+
];
|
|
21
61
|
const rule = {
|
|
22
62
|
meta: {
|
|
23
63
|
type: 'problem',
|
|
@@ -28,6 +68,17 @@ const rule = {
|
|
|
28
68
|
url: 'https://formatjs.io/docs/tooling/linter#no-emoji',
|
|
29
69
|
},
|
|
30
70
|
fixable: 'code',
|
|
71
|
+
schema: [
|
|
72
|
+
{
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: { versionAbove: { type: 'string', enum: versionAboveEnums } },
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
messages: {
|
|
79
|
+
notAllowed: 'Emojis are not allowed',
|
|
80
|
+
notAllowedAboveVersion: 'Emojis above version {{versionAbove}} are not allowed - Emoji: {{emoji}}',
|
|
81
|
+
},
|
|
31
82
|
},
|
|
32
83
|
create(context) {
|
|
33
84
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-literal-string-in-jsx.d.ts","sourceRoot":"","sources":["no-literal-string-in-jsx.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAqDhC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"no-literal-string-in-jsx.d.ts","sourceRoot":"","sources":["no-literal-string-in-jsx.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAqDhC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA0KhB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -7,8 +7,8 @@ const propMatcherSchema = {
|
|
|
7
7
|
type: 'array',
|
|
8
8
|
items: {
|
|
9
9
|
type: 'array',
|
|
10
|
-
items: [{ type: 'string' }, { type: 'string' }]
|
|
11
|
-
}
|
|
10
|
+
items: [{ type: 'string' }, { type: 'string' }],
|
|
11
|
+
},
|
|
12
12
|
};
|
|
13
13
|
const defaultPropIncludePattern = [
|
|
14
14
|
['*', 'aria-{label,description,details,errormessage}'],
|
|
@@ -41,7 +41,7 @@ const rule = {
|
|
|
41
41
|
description: 'Disallow untranslated literal strings without translation.',
|
|
42
42
|
category: 'Errors',
|
|
43
43
|
recommended: false,
|
|
44
|
-
url: 'https://formatjs.io/docs/tooling/linter#no-literal-string-in-jsx'
|
|
44
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-literal-string-in-jsx',
|
|
45
45
|
},
|
|
46
46
|
schema: [
|
|
47
47
|
{
|
|
@@ -51,16 +51,16 @@ const rule = {
|
|
|
51
51
|
type: 'object',
|
|
52
52
|
properties: {
|
|
53
53
|
include: {
|
|
54
|
-
...propMatcherSchema
|
|
54
|
+
...propMatcherSchema,
|
|
55
55
|
},
|
|
56
56
|
exclude: {
|
|
57
|
-
...propMatcherSchema
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
57
|
+
...propMatcherSchema,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
62
|
},
|
|
63
|
-
]
|
|
63
|
+
],
|
|
64
64
|
},
|
|
65
65
|
// TODO: Vue support
|
|
66
66
|
create(context) {
|
|
@@ -109,7 +109,7 @@ const rule = {
|
|
|
109
109
|
(node.quasis.length > 1 || node.quasis[0].value.raw.length > 0))) {
|
|
110
110
|
context.report({
|
|
111
111
|
node: node,
|
|
112
|
-
message: 'Cannot have untranslated text in JSX'
|
|
112
|
+
message: 'Cannot have untranslated text in JSX',
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
else if (node.type === 'BinaryExpression' && node.operator === '+') {
|
|
@@ -120,6 +120,10 @@ const rule = {
|
|
|
120
120
|
checkJSXExpression(node.consequent);
|
|
121
121
|
checkJSXExpression(node.alternate);
|
|
122
122
|
}
|
|
123
|
+
else if (node.type === 'LogicalExpression') {
|
|
124
|
+
checkJSXExpression(node.left);
|
|
125
|
+
checkJSXExpression(node.right);
|
|
126
|
+
}
|
|
123
127
|
};
|
|
124
128
|
return {
|
|
125
129
|
JSXElement: (node) => {
|
|
@@ -146,7 +150,7 @@ const rule = {
|
|
|
146
150
|
node.value.value.length > 0) {
|
|
147
151
|
context.report({
|
|
148
152
|
node: node,
|
|
149
|
-
message: 'Cannot have untranslated text in JSX'
|
|
153
|
+
message: 'Cannot have untranslated text in JSX',
|
|
150
154
|
});
|
|
151
155
|
}
|
|
152
156
|
else if (node.value.type === 'JSXExpressionContainer' &&
|
|
@@ -161,7 +165,7 @@ const rule = {
|
|
|
161
165
|
}
|
|
162
166
|
context.report({
|
|
163
167
|
node: node,
|
|
164
|
-
message: 'Cannot have untranslated text in JSX'
|
|
168
|
+
message: 'Cannot have untranslated text in JSX',
|
|
165
169
|
});
|
|
166
170
|
},
|
|
167
171
|
// Children expression container
|
|
@@ -169,8 +173,8 @@ const rule = {
|
|
|
169
173
|
if (node.expression.type !== 'JSXEmptyExpression') {
|
|
170
174
|
checkJSXExpression(node.expression);
|
|
171
175
|
}
|
|
172
|
-
}
|
|
176
|
+
},
|
|
173
177
|
};
|
|
174
|
-
}
|
|
178
|
+
},
|
|
175
179
|
};
|
|
176
180
|
exports.default = rule;
|
|
@@ -50,13 +50,13 @@ function checkNode(context, node) {
|
|
|
50
50
|
}
|
|
51
51
|
try {
|
|
52
52
|
verifyAst((0, icu_messageformat_parser_1.parse)(defaultMessage, {
|
|
53
|
-
ignoreTag: settings.ignoreTag
|
|
53
|
+
ignoreTag: settings.ignoreTag,
|
|
54
54
|
}));
|
|
55
55
|
}
|
|
56
56
|
catch (e) {
|
|
57
57
|
context.report({
|
|
58
58
|
node: messageNode,
|
|
59
|
-
message: e instanceof Error ? e.message : String(e)
|
|
59
|
+
message: e instanceof Error ? e.message : String(e),
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -67,23 +67,23 @@ const rule = {
|
|
|
67
67
|
docs: {
|
|
68
68
|
description: 'Disallow unnecessary formatted message',
|
|
69
69
|
recommended: true,
|
|
70
|
-
url: 'https://formatjs.io/docs/tooling/linter#no-useless-message'
|
|
70
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-useless-message',
|
|
71
71
|
},
|
|
72
|
-
fixable: 'code'
|
|
72
|
+
fixable: 'code',
|
|
73
73
|
},
|
|
74
74
|
create(context) {
|
|
75
75
|
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
76
76
|
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
77
77
|
return context.parserServices.defineTemplateBodyVisitor({
|
|
78
|
-
CallExpression: callExpressionVisitor
|
|
78
|
+
CallExpression: callExpressionVisitor,
|
|
79
79
|
}, {
|
|
80
|
-
CallExpression: callExpressionVisitor
|
|
80
|
+
CallExpression: callExpressionVisitor,
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
return {
|
|
84
84
|
JSXOpeningElement: (node) => checkNode(context, node),
|
|
85
|
-
CallExpression: callExpressionVisitor
|
|
85
|
+
CallExpression: callExpressionVisitor,
|
|
86
86
|
};
|
|
87
|
-
}
|
|
87
|
+
},
|
|
88
88
|
};
|
|
89
89
|
exports.default = rule;
|