eslint-plugin-formatjs 2.17.7
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 +9 -0
- package/README.md +3 -0
- package/index.d.ts +20 -0
- package/index.d.ts.map +1 -0
- package/index.js +34 -0
- package/package.json +34 -0
- package/rules/blacklist-elements.d.ts +4 -0
- package/rules/blacklist-elements.d.ts.map +1 -0
- package/rules/blacklist-elements.js +135 -0
- package/rules/enforce-default-message.d.ts +4 -0
- package/rules/enforce-default-message.d.ts.map +1 -0
- package/rules/enforce-default-message.js +58 -0
- package/rules/enforce-description.d.ts +4 -0
- package/rules/enforce-description.d.ts.map +1 -0
- package/rules/enforce-description.js +57 -0
- package/rules/enforce-id.d.ts +4 -0
- package/rules/enforce-id.d.ts.map +1 -0
- package/rules/enforce-id.js +104 -0
- package/rules/enforce-placeholders.d.ts +4 -0
- package/rules/enforce-placeholders.d.ts.map +1 -0
- package/rules/enforce-placeholders.js +120 -0
- package/rules/enforce-plural-rules.d.ts +4 -0
- package/rules/enforce-plural-rules.d.ts.map +1 -0
- package/rules/enforce-plural-rules.js +113 -0
- package/rules/no-camel-case.d.ts +4 -0
- package/rules/no-camel-case.d.ts.map +1 -0
- package/rules/no-camel-case.js +85 -0
- package/rules/no-complex-selectors.d.ts +4 -0
- package/rules/no-complex-selectors.d.ts.map +1 -0
- package/rules/no-complex-selectors.js +80 -0
- package/rules/no-emoji.d.ts +4 -0
- package/rules/no-emoji.d.ts.map +1 -0
- package/rules/no-emoji.js +50 -0
- package/rules/no-id.d.ts +4 -0
- package/rules/no-id.d.ts.map +1 -0
- package/rules/no-id.js +58 -0
- package/rules/no-multiple-plurals.d.ts +4 -0
- package/rules/no-multiple-plurals.d.ts.map +1 -0
- package/rules/no-multiple-plurals.js +80 -0
- package/rules/no-multiple-whitespaces.d.ts +4 -0
- package/rules/no-multiple-whitespaces.d.ts.map +1 -0
- package/rules/no-multiple-whitespaces.js +57 -0
- package/rules/no-offset.d.ts +4 -0
- package/rules/no-offset.d.ts.map +1 -0
- package/rules/no-offset.js +78 -0
- package/util.d.ts +22 -0
- package/util.d.ts.map +1 -0
- package/util.js +232 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var util_1 = require("../util");
|
|
5
|
+
var icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
6
|
+
var PluralRulesEnforcement = /** @class */ (function (_super) {
|
|
7
|
+
tslib_1.__extends(PluralRulesEnforcement, _super);
|
|
8
|
+
function PluralRulesEnforcement(message) {
|
|
9
|
+
var _this = _super.call(this) || this;
|
|
10
|
+
_this.message = message;
|
|
11
|
+
return _this;
|
|
12
|
+
}
|
|
13
|
+
return PluralRulesEnforcement;
|
|
14
|
+
}(Error));
|
|
15
|
+
var LDML;
|
|
16
|
+
(function (LDML) {
|
|
17
|
+
LDML["zero"] = "zero";
|
|
18
|
+
LDML["one"] = "one";
|
|
19
|
+
LDML["two"] = "two";
|
|
20
|
+
LDML["few"] = "few";
|
|
21
|
+
LDML["many"] = "many";
|
|
22
|
+
LDML["other"] = "other";
|
|
23
|
+
})(LDML || (LDML = {}));
|
|
24
|
+
function verifyAst(plConfig, ast) {
|
|
25
|
+
for (var _i = 0, ast_1 = ast; _i < ast_1.length; _i++) {
|
|
26
|
+
var el = ast_1[_i];
|
|
27
|
+
if (icu_messageformat_parser_1.isPluralElement(el)) {
|
|
28
|
+
var rules = Object.keys(plConfig);
|
|
29
|
+
for (var _a = 0, rules_1 = rules; _a < rules_1.length; _a++) {
|
|
30
|
+
var rule_1 = rules_1[_a];
|
|
31
|
+
if (plConfig[rule_1] && !el.options[rule_1]) {
|
|
32
|
+
throw new PluralRulesEnforcement("Missing plural rule \"" + rule_1 + "\"");
|
|
33
|
+
}
|
|
34
|
+
if (!plConfig[rule_1] && el.options[rule_1]) {
|
|
35
|
+
throw new PluralRulesEnforcement("Plural rule \"" + rule_1 + "\" is forbidden");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
var options = el.options;
|
|
39
|
+
for (var _b = 0, _c = Object.keys(options); _b < _c.length; _b++) {
|
|
40
|
+
var selector = _c[_b];
|
|
41
|
+
verifyAst(plConfig, options[selector].value);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function checkNode(context, node) {
|
|
47
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
48
|
+
if (!msgs.length) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
var plConfig = context.options[0];
|
|
52
|
+
if (!plConfig) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
56
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
57
|
+
if (!defaultMessage || !messageNode) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
verifyAst(context.options[0], icu_messageformat_parser_1.parse(defaultMessage, {
|
|
62
|
+
ignoreTag: context.settings.ignoreTag,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
context.report({
|
|
67
|
+
node: messageNode,
|
|
68
|
+
message: e.message,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
var rule = {
|
|
74
|
+
meta: {
|
|
75
|
+
type: 'problem',
|
|
76
|
+
docs: {
|
|
77
|
+
description: 'Enforce plural rules to always specify certain categories like `one`/`other`',
|
|
78
|
+
category: 'Errors',
|
|
79
|
+
recommended: false,
|
|
80
|
+
url: 'https://formatjs.io/docs/tooling/linter#enforce-plural-rules',
|
|
81
|
+
},
|
|
82
|
+
fixable: 'code',
|
|
83
|
+
schema: [
|
|
84
|
+
{
|
|
85
|
+
type: 'object',
|
|
86
|
+
properties: Object.keys(LDML).reduce(function (schema, k) {
|
|
87
|
+
schema[k] = {
|
|
88
|
+
type: 'boolean',
|
|
89
|
+
};
|
|
90
|
+
return schema;
|
|
91
|
+
}, {}),
|
|
92
|
+
additionalProperties: false,
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
create: function (context) {
|
|
97
|
+
var callExpressionVisitor = function (node) {
|
|
98
|
+
return checkNode(context, node);
|
|
99
|
+
};
|
|
100
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
101
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
102
|
+
CallExpression: callExpressionVisitor,
|
|
103
|
+
}, {
|
|
104
|
+
CallExpression: callExpressionVisitor,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
109
|
+
CallExpression: callExpressionVisitor,
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-camel-case.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/no-camel-case.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AA+D3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA8BhB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
5
|
+
var util_1 = require("../util");
|
|
6
|
+
var CAMEL_CASE_REGEX = /[A-Z]/;
|
|
7
|
+
var CamelCase = /** @class */ (function (_super) {
|
|
8
|
+
tslib_1.__extends(CamelCase, _super);
|
|
9
|
+
function CamelCase() {
|
|
10
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
11
|
+
_this.message = 'Camel case arguments are not allowed';
|
|
12
|
+
return _this;
|
|
13
|
+
}
|
|
14
|
+
return CamelCase;
|
|
15
|
+
}(Error));
|
|
16
|
+
function verifyAst(ast) {
|
|
17
|
+
for (var _i = 0, ast_1 = ast; _i < ast_1.length; _i++) {
|
|
18
|
+
var el = ast_1[_i];
|
|
19
|
+
if (icu_messageformat_parser_1.isArgumentElement(el)) {
|
|
20
|
+
if (CAMEL_CASE_REGEX.test(el.value)) {
|
|
21
|
+
throw new CamelCase();
|
|
22
|
+
}
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (icu_messageformat_parser_1.isPluralElement(el)) {
|
|
26
|
+
if (CAMEL_CASE_REGEX.test(el.value)) {
|
|
27
|
+
throw new CamelCase();
|
|
28
|
+
}
|
|
29
|
+
var options = el.options;
|
|
30
|
+
for (var _a = 0, _b = Object.keys(options); _a < _b.length; _a++) {
|
|
31
|
+
var selector = _b[_a];
|
|
32
|
+
verifyAst(options[selector].value);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function checkNode(context, node) {
|
|
38
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
39
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
40
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
41
|
+
if (!defaultMessage || !messageNode) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
verifyAst(icu_messageformat_parser_1.parse(defaultMessage, {
|
|
46
|
+
ignoreTag: context.settings.ignoreTag,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
context.report({
|
|
51
|
+
node: messageNode,
|
|
52
|
+
message: e.message,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
var rule = {
|
|
58
|
+
meta: {
|
|
59
|
+
type: 'problem',
|
|
60
|
+
docs: {
|
|
61
|
+
description: 'Disallow camel case placeholders in message',
|
|
62
|
+
category: 'Errors',
|
|
63
|
+
recommended: false,
|
|
64
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-camel-case',
|
|
65
|
+
},
|
|
66
|
+
fixable: 'code',
|
|
67
|
+
},
|
|
68
|
+
create: function (context) {
|
|
69
|
+
var callExpressionVisitor = function (node) {
|
|
70
|
+
return checkNode(context, node);
|
|
71
|
+
};
|
|
72
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
73
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
74
|
+
CallExpression: callExpressionVisitor,
|
|
75
|
+
}, {
|
|
76
|
+
CallExpression: callExpressionVisitor,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
81
|
+
CallExpression: callExpressionVisitor,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-complex-selectors.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/no-complex-selectors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AA8D3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAiDhB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var util_1 = require("../util");
|
|
5
|
+
var icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
6
|
+
var manipulator_1 = require("@formatjs/icu-messageformat-parser/manipulator");
|
|
7
|
+
function calculateComplexity(ast) {
|
|
8
|
+
if (ast.length === 1) {
|
|
9
|
+
var el_1 = ast[0];
|
|
10
|
+
if (icu_messageformat_parser_1.isPluralElement(el_1) || icu_messageformat_parser_1.isSelectElement(el_1)) {
|
|
11
|
+
return Object.keys(el_1.options).reduce(function (complexity, k) {
|
|
12
|
+
return complexity + calculateComplexity(el_1.options[k].value);
|
|
13
|
+
}, 0);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return 1;
|
|
17
|
+
}
|
|
18
|
+
function checkNode(context, node) {
|
|
19
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
20
|
+
if (!msgs.length) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
var config = tslib_1.__assign({ limit: 20 }, (context.options[0] || {}));
|
|
24
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
25
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
26
|
+
if (!defaultMessage || !messageNode) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
var hoistedAst = manipulator_1.hoistSelectors(icu_messageformat_parser_1.parse(defaultMessage, {
|
|
30
|
+
ignoreTag: context.settings.ignoreTag,
|
|
31
|
+
}));
|
|
32
|
+
var complexity = calculateComplexity(hoistedAst);
|
|
33
|
+
if (complexity > config.limit) {
|
|
34
|
+
context.report({
|
|
35
|
+
node: messageNode,
|
|
36
|
+
message: "Message complexity is too high (" + complexity + " vs limit at " + config.limit + ")",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
var rule = {
|
|
42
|
+
meta: {
|
|
43
|
+
type: 'problem',
|
|
44
|
+
docs: {
|
|
45
|
+
description: "Make sure a sentence is not too complex. \nComplexity is determined by how many strings are produced when we try to\nflatten the sentence given its selectors. For example:\n\"I have {count, plural, one{a dog} other{many dogs}}\"\nhas the complexity of 2 because flattening the plural selector\nresults in 2 sentences: \"I have a dog\" & \"I have many dogs\".\nDefault complexity limit is 20 \n(using Smartling as a reference: https://help.smartling.com/hc/en-us/articles/360008030994-ICU-MessageFormat)\n",
|
|
46
|
+
category: 'Errors',
|
|
47
|
+
recommended: false,
|
|
48
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-complex-selectors',
|
|
49
|
+
},
|
|
50
|
+
schema: [
|
|
51
|
+
{
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
limit: {
|
|
55
|
+
type: 'number',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
additionalProperties: false,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
fixable: 'code',
|
|
62
|
+
},
|
|
63
|
+
create: function (context) {
|
|
64
|
+
var callExpressionVisitor = function (node) {
|
|
65
|
+
return checkNode(context, node);
|
|
66
|
+
};
|
|
67
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
68
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
69
|
+
CallExpression: callExpressionVisitor,
|
|
70
|
+
}, {
|
|
71
|
+
CallExpression: callExpressionVisitor,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
76
|
+
CallExpression: callExpressionVisitor,
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-emoji.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/no-emoji.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AA2B3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA8BhB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var util_1 = require("../util");
|
|
5
|
+
var emoji_regex_1 = tslib_1.__importDefault(require("emoji-regex"));
|
|
6
|
+
var EMOJI_REGEX = emoji_regex_1.default();
|
|
7
|
+
function checkNode(context, node) {
|
|
8
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
9
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
10
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
11
|
+
if (!defaultMessage || !messageNode) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (EMOJI_REGEX.test(defaultMessage)) {
|
|
15
|
+
context.report({
|
|
16
|
+
node: messageNode,
|
|
17
|
+
message: 'Emojis are not allowed',
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
var rule = {
|
|
23
|
+
meta: {
|
|
24
|
+
type: 'problem',
|
|
25
|
+
docs: {
|
|
26
|
+
description: 'Disallow emojis in message',
|
|
27
|
+
category: 'Errors',
|
|
28
|
+
recommended: false,
|
|
29
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-emoji',
|
|
30
|
+
},
|
|
31
|
+
fixable: 'code',
|
|
32
|
+
},
|
|
33
|
+
create: function (context) {
|
|
34
|
+
var callExpressionVisitor = function (node) {
|
|
35
|
+
return checkNode(context, node);
|
|
36
|
+
};
|
|
37
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
38
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
39
|
+
CallExpression: callExpressionVisitor,
|
|
40
|
+
}, {
|
|
41
|
+
CallExpression: callExpressionVisitor,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
46
|
+
CallExpression: callExpressionVisitor,
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
exports.default = rule;
|
package/rules/no-id.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-id.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/no-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAa,MAAM,QAAQ,CAAA;;AAgCvC,wBA8BoB"}
|
package/rules/no-id.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var util_1 = require("../util");
|
|
4
|
+
function isComment(token) {
|
|
5
|
+
return !!token && (token.type === 'Block' || token.type === 'Line');
|
|
6
|
+
}
|
|
7
|
+
function checkNode(context, node) {
|
|
8
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
9
|
+
var _loop_1 = function (idPropNode) {
|
|
10
|
+
if (idPropNode) {
|
|
11
|
+
context.report({
|
|
12
|
+
node: idPropNode,
|
|
13
|
+
message: 'Manual `id` are not allowed in message descriptor',
|
|
14
|
+
fix: function (fixer) {
|
|
15
|
+
var src = context.getSourceCode();
|
|
16
|
+
var token = src.getTokenAfter(idPropNode);
|
|
17
|
+
var fixes = [fixer.remove(idPropNode)];
|
|
18
|
+
if (token && !isComment(token) && (token === null || token === void 0 ? void 0 : token.value) === ',') {
|
|
19
|
+
fixes.push(fixer.remove(token));
|
|
20
|
+
}
|
|
21
|
+
return fixes;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
27
|
+
var idPropNode = msgs_1[_i][0].idPropNode;
|
|
28
|
+
_loop_1(idPropNode);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.default = {
|
|
32
|
+
meta: {
|
|
33
|
+
type: 'problem',
|
|
34
|
+
docs: {
|
|
35
|
+
description: 'Ban explicit ID from MessageDescriptor',
|
|
36
|
+
category: 'Errors',
|
|
37
|
+
recommended: false,
|
|
38
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-id',
|
|
39
|
+
},
|
|
40
|
+
fixable: 'code',
|
|
41
|
+
},
|
|
42
|
+
create: function (context) {
|
|
43
|
+
var callExpressionVisitor = function (node) {
|
|
44
|
+
return checkNode(context, node);
|
|
45
|
+
};
|
|
46
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
47
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
48
|
+
CallExpression: callExpressionVisitor,
|
|
49
|
+
}, {
|
|
50
|
+
CallExpression: callExpressionVisitor,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
55
|
+
CallExpression: callExpressionVisitor,
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-multiple-plurals.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/no-multiple-plurals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAuD3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA8BhB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var util_1 = require("../util");
|
|
5
|
+
var icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
6
|
+
var MultiplePlurals = /** @class */ (function (_super) {
|
|
7
|
+
tslib_1.__extends(MultiplePlurals, _super);
|
|
8
|
+
function MultiplePlurals() {
|
|
9
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
10
|
+
_this.message = 'Cannot specify more than 1 plural rules';
|
|
11
|
+
return _this;
|
|
12
|
+
}
|
|
13
|
+
return MultiplePlurals;
|
|
14
|
+
}(Error));
|
|
15
|
+
function verifyAst(ast, pluralCount) {
|
|
16
|
+
if (pluralCount === void 0) { pluralCount = { count: 0 }; }
|
|
17
|
+
for (var _i = 0, ast_1 = ast; _i < ast_1.length; _i++) {
|
|
18
|
+
var el = ast_1[_i];
|
|
19
|
+
if (icu_messageformat_parser_1.isPluralElement(el)) {
|
|
20
|
+
pluralCount.count++;
|
|
21
|
+
if (pluralCount.count > 1) {
|
|
22
|
+
throw new MultiplePlurals();
|
|
23
|
+
}
|
|
24
|
+
var options = el.options;
|
|
25
|
+
for (var _a = 0, _b = Object.keys(options); _a < _b.length; _a++) {
|
|
26
|
+
var selector = _b[_a];
|
|
27
|
+
verifyAst(options[selector].value, pluralCount);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function checkNode(context, node) {
|
|
33
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
34
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
35
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
36
|
+
if (!defaultMessage || !messageNode) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
verifyAst(icu_messageformat_parser_1.parse(defaultMessage, {
|
|
41
|
+
ignoreTag: context.settings.ignoreTag,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
context.report({
|
|
46
|
+
node: messageNode,
|
|
47
|
+
message: e.message,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
var rule = {
|
|
53
|
+
meta: {
|
|
54
|
+
type: 'problem',
|
|
55
|
+
docs: {
|
|
56
|
+
description: 'Disallow multiple plural rules in the same message',
|
|
57
|
+
category: 'Errors',
|
|
58
|
+
recommended: false,
|
|
59
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-multiple-plurals',
|
|
60
|
+
},
|
|
61
|
+
fixable: 'code',
|
|
62
|
+
},
|
|
63
|
+
create: function (context) {
|
|
64
|
+
var callExpressionVisitor = function (node) {
|
|
65
|
+
return checkNode(context, node);
|
|
66
|
+
};
|
|
67
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
68
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
69
|
+
CallExpression: callExpressionVisitor,
|
|
70
|
+
}, {
|
|
71
|
+
CallExpression: callExpressionVisitor,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
76
|
+
CallExpression: callExpressionVisitor,
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-multiple-whitespaces.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/no-multiple-whitespaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAmC3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA8BhB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var util_1 = require("../util");
|
|
4
|
+
var MULTIPLE_SPACES = /\s{2,}/g;
|
|
5
|
+
function checkNode(context, node) {
|
|
6
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
7
|
+
var _loop_1 = function (defaultMessage, messageNode) {
|
|
8
|
+
if (!defaultMessage || !messageNode) {
|
|
9
|
+
return "continue";
|
|
10
|
+
}
|
|
11
|
+
if (MULTIPLE_SPACES.test(defaultMessage)) {
|
|
12
|
+
var reportObject = {
|
|
13
|
+
node: messageNode,
|
|
14
|
+
message: 'Multiple consecutive whitespaces are not allowed',
|
|
15
|
+
};
|
|
16
|
+
if (messageNode.type === 'Literal' && messageNode.raw) {
|
|
17
|
+
reportObject.fix = function (fixer) {
|
|
18
|
+
return fixer.replaceText(messageNode, messageNode.raw.replace(MULTIPLE_SPACES, ' '));
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
context.report(reportObject);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
25
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
26
|
+
_loop_1(defaultMessage, messageNode);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
var rule = {
|
|
30
|
+
meta: {
|
|
31
|
+
type: 'problem',
|
|
32
|
+
docs: {
|
|
33
|
+
description: 'Disallow emojis in message',
|
|
34
|
+
category: 'Errors',
|
|
35
|
+
recommended: false,
|
|
36
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-emoji',
|
|
37
|
+
},
|
|
38
|
+
fixable: 'whitespace',
|
|
39
|
+
},
|
|
40
|
+
create: function (context) {
|
|
41
|
+
var callExpressionVisitor = function (node) {
|
|
42
|
+
return checkNode(context, node);
|
|
43
|
+
};
|
|
44
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
45
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
46
|
+
CallExpression: callExpressionVisitor,
|
|
47
|
+
}, {
|
|
48
|
+
CallExpression: callExpressionVisitor,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
53
|
+
CallExpression: callExpressionVisitor,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-offset.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/no-offset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAsD3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA8BhB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var util_1 = require("../util");
|
|
5
|
+
var icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
6
|
+
var NoOffsetError = /** @class */ (function (_super) {
|
|
7
|
+
tslib_1.__extends(NoOffsetError, _super);
|
|
8
|
+
function NoOffsetError() {
|
|
9
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
10
|
+
_this.message = 'offset are not allowed in plural rules';
|
|
11
|
+
return _this;
|
|
12
|
+
}
|
|
13
|
+
return NoOffsetError;
|
|
14
|
+
}(Error));
|
|
15
|
+
function verifyAst(ast) {
|
|
16
|
+
for (var _i = 0, ast_1 = ast; _i < ast_1.length; _i++) {
|
|
17
|
+
var el = ast_1[_i];
|
|
18
|
+
if (icu_messageformat_parser_1.isPluralElement(el)) {
|
|
19
|
+
if (el.offset) {
|
|
20
|
+
throw new NoOffsetError();
|
|
21
|
+
}
|
|
22
|
+
var options = el.options;
|
|
23
|
+
for (var _a = 0, _b = Object.keys(options); _a < _b.length; _a++) {
|
|
24
|
+
var selector = _b[_a];
|
|
25
|
+
verifyAst(options[selector].value);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function checkNode(context, node) {
|
|
31
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
32
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
33
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
34
|
+
if (!defaultMessage || !messageNode) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
verifyAst(icu_messageformat_parser_1.parse(defaultMessage, {
|
|
39
|
+
ignoreTag: context.settings.ignoreTag,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
context.report({
|
|
44
|
+
node: messageNode,
|
|
45
|
+
message: e.message,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
var rule = {
|
|
51
|
+
meta: {
|
|
52
|
+
type: 'problem',
|
|
53
|
+
docs: {
|
|
54
|
+
description: 'Disallow offset in plural rules',
|
|
55
|
+
category: 'Errors',
|
|
56
|
+
recommended: false,
|
|
57
|
+
url: 'https://formatjs.io/docs/tooling/linter#no-offset',
|
|
58
|
+
},
|
|
59
|
+
fixable: 'code',
|
|
60
|
+
},
|
|
61
|
+
create: function (context) {
|
|
62
|
+
var callExpressionVisitor = function (node) {
|
|
63
|
+
return checkNode(context, node);
|
|
64
|
+
};
|
|
65
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
66
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
67
|
+
CallExpression: callExpressionVisitor,
|
|
68
|
+
}, {
|
|
69
|
+
CallExpression: callExpressionVisitor,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
74
|
+
CallExpression: callExpressionVisitor,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
exports.default = rule;
|