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
package/LICENSE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 FormatJS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
package/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare const plugin: {
|
|
2
|
+
rules: {
|
|
3
|
+
'blacklist-elements': import("eslint").Rule.RuleModule;
|
|
4
|
+
'enforce-default-message': import("eslint").Rule.RuleModule;
|
|
5
|
+
'enforce-description': import("eslint").Rule.RuleModule;
|
|
6
|
+
'enforce-id': import("eslint").Rule.RuleModule;
|
|
7
|
+
'enforce-placeholders': import("eslint").Rule.RuleModule;
|
|
8
|
+
'enforce-plural-rules': import("eslint").Rule.RuleModule;
|
|
9
|
+
'no-camel-case': import("eslint").Rule.RuleModule;
|
|
10
|
+
'no-complex-selectors': import("eslint").Rule.RuleModule;
|
|
11
|
+
'no-emoji': import("eslint").Rule.RuleModule;
|
|
12
|
+
'no-id': import("eslint").Rule.RuleModule;
|
|
13
|
+
'no-multiple-plurals': import("eslint").Rule.RuleModule;
|
|
14
|
+
'no-multiple-whitespaces': import("eslint").Rule.RuleModule;
|
|
15
|
+
'no-offset': import("eslint").Rule.RuleModule;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare type Plugin = typeof plugin;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/eslint-plugin-formatjs/index.ts"],"names":[],"mappings":"AAaA,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;CAgBX,CAAA;AAED,oBAAY,MAAM,GAAG,OAAO,MAAM,CAAA"}
|
package/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var blacklist_elements_1 = tslib_1.__importDefault(require("./rules/blacklist-elements"));
|
|
5
|
+
var enforce_default_message_1 = tslib_1.__importDefault(require("./rules/enforce-default-message"));
|
|
6
|
+
var enforce_description_1 = tslib_1.__importDefault(require("./rules/enforce-description"));
|
|
7
|
+
var enforce_id_1 = tslib_1.__importDefault(require("./rules/enforce-id"));
|
|
8
|
+
var enforce_placeholders_1 = tslib_1.__importDefault(require("./rules/enforce-placeholders"));
|
|
9
|
+
var enforce_plural_rules_1 = tslib_1.__importDefault(require("./rules/enforce-plural-rules"));
|
|
10
|
+
var no_camel_case_1 = tslib_1.__importDefault(require("./rules/no-camel-case"));
|
|
11
|
+
var no_complex_selectors_1 = tslib_1.__importDefault(require("./rules/no-complex-selectors"));
|
|
12
|
+
var no_emoji_1 = tslib_1.__importDefault(require("./rules/no-emoji"));
|
|
13
|
+
var no_id_1 = tslib_1.__importDefault(require("./rules/no-id"));
|
|
14
|
+
var no_multiple_plurals_1 = tslib_1.__importDefault(require("./rules/no-multiple-plurals"));
|
|
15
|
+
var no_multiple_whitespaces_1 = tslib_1.__importDefault(require("./rules/no-multiple-whitespaces"));
|
|
16
|
+
var no_offset_1 = tslib_1.__importDefault(require("./rules/no-offset"));
|
|
17
|
+
var plugin = {
|
|
18
|
+
rules: {
|
|
19
|
+
'blacklist-elements': blacklist_elements_1.default,
|
|
20
|
+
'enforce-default-message': enforce_default_message_1.default,
|
|
21
|
+
'enforce-description': enforce_description_1.default,
|
|
22
|
+
'enforce-id': enforce_id_1.default,
|
|
23
|
+
'enforce-placeholders': enforce_placeholders_1.default,
|
|
24
|
+
'enforce-plural-rules': enforce_plural_rules_1.default,
|
|
25
|
+
'no-camel-case': no_camel_case_1.default,
|
|
26
|
+
'no-complex-selectors': no_complex_selectors_1.default,
|
|
27
|
+
'no-emoji': no_emoji_1.default,
|
|
28
|
+
'no-id': no_id_1.default,
|
|
29
|
+
'no-multiple-plurals': no_multiple_plurals_1.default,
|
|
30
|
+
'no-multiple-whitespaces': no_multiple_whitespaces_1.default,
|
|
31
|
+
'no-offset': no_offset_1.default,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
module.exports = plugin;
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-formatjs",
|
|
3
|
+
"version": "2.17.7",
|
|
4
|
+
"description": "ESLint plugin for formatjs",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+ssh://git@github.com/formatjs/formatjs.git"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"eslint",
|
|
12
|
+
"eslintplugin",
|
|
13
|
+
"i18n",
|
|
14
|
+
"formatjs"
|
|
15
|
+
],
|
|
16
|
+
"author": "Long Ho <holevietlong@gmail.com>",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/formatjs/formatjs/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/formatjs/formatjs#readme",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@formatjs/icu-messageformat-parser": "2.0.11",
|
|
24
|
+
"@formatjs/ts-transformer": "3.4.10",
|
|
25
|
+
"@types/eslint": "^7.2.0",
|
|
26
|
+
"@typescript-eslint/typescript-estree": "^4.11.0",
|
|
27
|
+
"emoji-regex": "^9.2.0",
|
|
28
|
+
"tslib": "^2.1.0",
|
|
29
|
+
"typescript": "4"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"eslint": "^7.4.0"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blacklist-elements.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/blacklist-elements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAkH3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAyChB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,135 @@
|
|
|
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 BlacklistElement = /** @class */ (function (_super) {
|
|
7
|
+
tslib_1.__extends(BlacklistElement, _super);
|
|
8
|
+
function BlacklistElement(type) {
|
|
9
|
+
var _this = _super.call(this) || this;
|
|
10
|
+
_this.message = type + " element is blacklisted";
|
|
11
|
+
return _this;
|
|
12
|
+
}
|
|
13
|
+
return BlacklistElement;
|
|
14
|
+
}(Error));
|
|
15
|
+
var Element;
|
|
16
|
+
(function (Element) {
|
|
17
|
+
Element["literal"] = "literal";
|
|
18
|
+
Element["argument"] = "argument";
|
|
19
|
+
Element["number"] = "number";
|
|
20
|
+
Element["date"] = "date";
|
|
21
|
+
Element["time"] = "time";
|
|
22
|
+
Element["select"] = "select";
|
|
23
|
+
Element["selectordinal"] = "selectordinal";
|
|
24
|
+
Element["plural"] = "plural";
|
|
25
|
+
Element["tag"] = "tag";
|
|
26
|
+
})(Element || (Element = {}));
|
|
27
|
+
function verifyAst(blacklist, ast) {
|
|
28
|
+
for (var _i = 0, ast_1 = ast; _i < ast_1.length; _i++) {
|
|
29
|
+
var el = ast_1[_i];
|
|
30
|
+
if (icu_messageformat_parser_1.isLiteralElement(el) && blacklist.includes(Element.literal)) {
|
|
31
|
+
throw new BlacklistElement(Element.literal);
|
|
32
|
+
}
|
|
33
|
+
if (icu_messageformat_parser_1.isArgumentElement(el) && blacklist.includes(Element.argument)) {
|
|
34
|
+
throw new BlacklistElement(Element.argument);
|
|
35
|
+
}
|
|
36
|
+
if (icu_messageformat_parser_1.isNumberElement(el) && blacklist.includes(Element.number)) {
|
|
37
|
+
throw new BlacklistElement(Element.number);
|
|
38
|
+
}
|
|
39
|
+
if (icu_messageformat_parser_1.isDateElement(el) && blacklist.includes(Element.date)) {
|
|
40
|
+
throw new BlacklistElement(Element.date);
|
|
41
|
+
}
|
|
42
|
+
if (icu_messageformat_parser_1.isTimeElement(el) && blacklist.includes(Element.time)) {
|
|
43
|
+
throw new BlacklistElement(Element.time);
|
|
44
|
+
}
|
|
45
|
+
if (icu_messageformat_parser_1.isSelectElement(el) && blacklist.includes(Element.select)) {
|
|
46
|
+
throw new BlacklistElement(Element.select);
|
|
47
|
+
}
|
|
48
|
+
if (icu_messageformat_parser_1.isTagElement(el) && blacklist.includes(Element.tag)) {
|
|
49
|
+
throw new BlacklistElement(Element.tag);
|
|
50
|
+
}
|
|
51
|
+
if (icu_messageformat_parser_1.isPluralElement(el)) {
|
|
52
|
+
if (blacklist.includes(Element.plural)) {
|
|
53
|
+
throw new BlacklistElement(Element.argument);
|
|
54
|
+
}
|
|
55
|
+
if (el.pluralType === 'ordinal' &&
|
|
56
|
+
blacklist.includes(Element.selectordinal)) {
|
|
57
|
+
throw new BlacklistElement(Element.selectordinal);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (icu_messageformat_parser_1.isSelectElement(el) || icu_messageformat_parser_1.isPluralElement(el)) {
|
|
61
|
+
var options = el.options;
|
|
62
|
+
for (var _a = 0, _b = Object.keys(options); _a < _b.length; _a++) {
|
|
63
|
+
var selector = _b[_a];
|
|
64
|
+
verifyAst(blacklist, options[selector].value);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function checkNode(context, node) {
|
|
70
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
71
|
+
if (!msgs.length) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
var blacklist = context.options[0];
|
|
75
|
+
if (!Array.isArray(blacklist) || !blacklist.length) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
79
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
80
|
+
if (!defaultMessage || !messageNode) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
verifyAst(context.options[0], icu_messageformat_parser_1.parse(defaultMessage, {
|
|
85
|
+
ignoreTag: context.settings.ignoreTag,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
context.report({
|
|
90
|
+
node: messageNode,
|
|
91
|
+
message: e.message,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
var rule = {
|
|
97
|
+
meta: {
|
|
98
|
+
type: 'problem',
|
|
99
|
+
docs: {
|
|
100
|
+
description: 'Disallow specific elements in ICU message format',
|
|
101
|
+
category: 'Errors',
|
|
102
|
+
recommended: false,
|
|
103
|
+
url: 'https://formatjs.io/docs/tooling/linter#blacklist-elements',
|
|
104
|
+
},
|
|
105
|
+
fixable: 'code',
|
|
106
|
+
schema: [
|
|
107
|
+
{
|
|
108
|
+
type: 'array',
|
|
109
|
+
properties: {
|
|
110
|
+
items: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
enum: Object.keys(Element),
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
create: function (context) {
|
|
119
|
+
var callExpressionVisitor = function (node) {
|
|
120
|
+
return checkNode(context, node);
|
|
121
|
+
};
|
|
122
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
123
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
124
|
+
CallExpression: callExpressionVisitor,
|
|
125
|
+
}, {
|
|
126
|
+
CallExpression: callExpressionVisitor,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
131
|
+
CallExpression: callExpressionVisitor,
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforce-default-message.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/enforce-default-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAiC3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAmChB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var util_1 = require("../util");
|
|
4
|
+
function checkNode(context, node) {
|
|
5
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
6
|
+
var type = context.options[0];
|
|
7
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
8
|
+
var _a = msgs_1[_i][0], defaultMessage = _a.message.defaultMessage, messageNode = _a.messageNode;
|
|
9
|
+
if (!defaultMessage) {
|
|
10
|
+
if (type === 'literal' && messageNode) {
|
|
11
|
+
context.report({
|
|
12
|
+
node: messageNode,
|
|
13
|
+
message: "\"defaultMessage\" must be:\n- a string literal or\n- template literal without variable",
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
else if (!messageNode) {
|
|
17
|
+
context.report({
|
|
18
|
+
node: node,
|
|
19
|
+
message: '`defaultMessage` has to be specified in message descriptor',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
var rule = {
|
|
26
|
+
meta: {
|
|
27
|
+
type: 'problem',
|
|
28
|
+
docs: {
|
|
29
|
+
description: 'Enforce defaultMessage in message descriptor',
|
|
30
|
+
category: 'Errors',
|
|
31
|
+
recommended: false,
|
|
32
|
+
url: 'https://formatjs.io/docs/tooling/linter#enforce-default-message',
|
|
33
|
+
},
|
|
34
|
+
fixable: 'code',
|
|
35
|
+
schema: [
|
|
36
|
+
{
|
|
37
|
+
enum: ['literal', 'anything'],
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
create: function (context) {
|
|
42
|
+
var callExpressionVisitor = function (node) {
|
|
43
|
+
return checkNode(context, node);
|
|
44
|
+
};
|
|
45
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
46
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
47
|
+
CallExpression: callExpressionVisitor,
|
|
48
|
+
}, {
|
|
49
|
+
CallExpression: callExpressionVisitor,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
54
|
+
CallExpression: callExpressionVisitor,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforce-description.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/enforce-description.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;;AAgC3B,wBAmCoB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var util_1 = require("../util");
|
|
4
|
+
function checkNode(context, node) {
|
|
5
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
6
|
+
var type = context.options[0];
|
|
7
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
8
|
+
var _a = msgs_1[_i][0], description = _a.message.description, descriptionNode = _a.descriptionNode;
|
|
9
|
+
if (!description) {
|
|
10
|
+
if (type === 'literal' && descriptionNode) {
|
|
11
|
+
context.report({
|
|
12
|
+
node: descriptionNode,
|
|
13
|
+
message: '`description` has to be a string literal (not function call or variable)',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
else if (!descriptionNode) {
|
|
17
|
+
context.report({
|
|
18
|
+
node: node,
|
|
19
|
+
message: '`description` has to be specified in message descriptor',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.default = {
|
|
26
|
+
meta: {
|
|
27
|
+
type: 'problem',
|
|
28
|
+
docs: {
|
|
29
|
+
description: 'Enforce description in message descriptor',
|
|
30
|
+
category: 'Errors',
|
|
31
|
+
recommended: false,
|
|
32
|
+
url: 'https://formatjs.io/docs/tooling/linter#enforce-description',
|
|
33
|
+
},
|
|
34
|
+
fixable: 'code',
|
|
35
|
+
schema: [
|
|
36
|
+
{
|
|
37
|
+
enum: ['literal', 'anything'],
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
create: function (context) {
|
|
42
|
+
var callExpressionVisitor = function (node) {
|
|
43
|
+
return checkNode(context, node);
|
|
44
|
+
};
|
|
45
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
46
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
47
|
+
CallExpression: callExpressionVisitor,
|
|
48
|
+
}, {
|
|
49
|
+
CallExpression: callExpressionVisitor,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
54
|
+
CallExpression: callExpressionVisitor,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforce-id.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/enforce-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;;AAoF3B,wBA0CoB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var util_1 = require("../util");
|
|
4
|
+
var ts_transformer_1 = require("@formatjs/ts-transformer");
|
|
5
|
+
function checkNode(context, node) {
|
|
6
|
+
var msgs = util_1.extractMessages(node, context.settings);
|
|
7
|
+
var options = context.options;
|
|
8
|
+
var _a = options[0], opt = _a === void 0 ? {} : _a;
|
|
9
|
+
var idInterpolationPattern = opt.idInterpolationPattern;
|
|
10
|
+
var _loop_1 = function (defaultMessage, description, id, idPropNode, descriptionNode, messagePropNode) {
|
|
11
|
+
if (!idInterpolationPattern && !idPropNode) {
|
|
12
|
+
context.report({
|
|
13
|
+
node: node,
|
|
14
|
+
message: "id must be specified",
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
else if (idInterpolationPattern) {
|
|
18
|
+
if (!defaultMessage) {
|
|
19
|
+
context.report({
|
|
20
|
+
node: node,
|
|
21
|
+
message: "defaultMessage must be a string literal to calculate generated IDs",
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
else if (!description && descriptionNode) {
|
|
25
|
+
context.report({
|
|
26
|
+
node: node,
|
|
27
|
+
message: "description must be a string literal to calculate generated IDs",
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
var correctId_1 = ts_transformer_1.interpolateName({
|
|
32
|
+
resourcePath: context.getFilename(),
|
|
33
|
+
}, idInterpolationPattern, {
|
|
34
|
+
content: description
|
|
35
|
+
? defaultMessage + "#" + description
|
|
36
|
+
: defaultMessage,
|
|
37
|
+
});
|
|
38
|
+
if (id !== correctId_1) {
|
|
39
|
+
context.report({
|
|
40
|
+
node: node,
|
|
41
|
+
message: "\"id\" does not match with hash pattern " + idInterpolationPattern + ".\nExpected: " + correctId_1 + "\nActual: " + id,
|
|
42
|
+
fix: function (fixer) {
|
|
43
|
+
if (idPropNode) {
|
|
44
|
+
if (idPropNode.type === 'JSXAttribute') {
|
|
45
|
+
return fixer.replaceText(idPropNode, "id=\"" + correctId_1 + "\"");
|
|
46
|
+
}
|
|
47
|
+
return fixer.replaceText(idPropNode, "id: '" + correctId_1 + "'");
|
|
48
|
+
}
|
|
49
|
+
// Insert after default message node
|
|
50
|
+
if (messagePropNode.type === 'JSXAttribute') {
|
|
51
|
+
return fixer.insertTextAfter(messagePropNode, " id=\"" + correctId_1 + "\"");
|
|
52
|
+
}
|
|
53
|
+
return fixer.replaceText(messagePropNode, "defaultMessage: '" + defaultMessage + "', id: '" + correctId_1 + "'");
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
61
|
+
var _b = msgs_1[_i][0], _c = _b.message, defaultMessage = _c.defaultMessage, description = _c.description, id = _c.id, idPropNode = _b.idPropNode, descriptionNode = _b.descriptionNode, messagePropNode = _b.messagePropNode;
|
|
62
|
+
_loop_1(defaultMessage, description, id, idPropNode, descriptionNode, messagePropNode);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.default = {
|
|
66
|
+
meta: {
|
|
67
|
+
type: 'problem',
|
|
68
|
+
docs: {
|
|
69
|
+
description: 'Enforce (generated) ID in message descriptor',
|
|
70
|
+
category: 'Errors',
|
|
71
|
+
recommended: false,
|
|
72
|
+
url: 'https://formatjs.io/docs/tooling/linter#enforce-id',
|
|
73
|
+
},
|
|
74
|
+
fixable: 'code',
|
|
75
|
+
schema: [
|
|
76
|
+
{
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
idInterpolationPattern: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
required: ['idInterpolationPattern'],
|
|
84
|
+
additionalProperties: false,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
create: function (context) {
|
|
89
|
+
var callExpressionVisitor = function (node) {
|
|
90
|
+
return checkNode(context, node);
|
|
91
|
+
};
|
|
92
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
93
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
94
|
+
CallExpression: callExpressionVisitor,
|
|
95
|
+
}, {
|
|
96
|
+
CallExpression: callExpressionVisitor,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
101
|
+
CallExpression: callExpressionVisitor,
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforce-placeholders.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/enforce-placeholders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AA2G3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA6ChB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,120 @@
|
|
|
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 PlaceholderEnforcement = /** @class */ (function (_super) {
|
|
7
|
+
tslib_1.__extends(PlaceholderEnforcement, _super);
|
|
8
|
+
function PlaceholderEnforcement(message) {
|
|
9
|
+
var _this = _super.call(this) || this;
|
|
10
|
+
_this.message = message;
|
|
11
|
+
return _this;
|
|
12
|
+
}
|
|
13
|
+
return PlaceholderEnforcement;
|
|
14
|
+
}(Error));
|
|
15
|
+
function keyExistsInExpression(key, values) {
|
|
16
|
+
if (!values) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if (values.type !== 'ObjectExpression') {
|
|
20
|
+
return true; // True bc we cannot evaluate this
|
|
21
|
+
}
|
|
22
|
+
if (values.properties.find(function (prop) { return prop.type === 'SpreadElement'; })) {
|
|
23
|
+
return true; // True bc there's a spread element
|
|
24
|
+
}
|
|
25
|
+
return !!values.properties.find(function (prop) {
|
|
26
|
+
if (prop.type !== 'Property') {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
switch (prop.key.type) {
|
|
30
|
+
case 'Identifier':
|
|
31
|
+
return prop.key.name === key;
|
|
32
|
+
case 'Literal':
|
|
33
|
+
return prop.key.value === key;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function verifyAst(ast, values, ignoreList) {
|
|
39
|
+
for (var _i = 0, ast_1 = ast; _i < ast_1.length; _i++) {
|
|
40
|
+
var el = ast_1[_i];
|
|
41
|
+
if (icu_messageformat_parser_1.isLiteralElement(el) || icu_messageformat_parser_1.isPoundElement(el)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
var key = el.value;
|
|
45
|
+
if (!ignoreList.has(key) && !keyExistsInExpression(key, values)) {
|
|
46
|
+
throw new PlaceholderEnforcement("Missing value for placeholder \"" + el.value + "\"");
|
|
47
|
+
}
|
|
48
|
+
if (icu_messageformat_parser_1.isPluralElement(el) || icu_messageformat_parser_1.isSelectElement(el)) {
|
|
49
|
+
for (var _a = 0, _b = Object.keys(el.options); _a < _b.length; _a++) {
|
|
50
|
+
var selector = _b[_a];
|
|
51
|
+
verifyAst(el.options[selector].value, values, ignoreList);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function checkNode(context, node) {
|
|
57
|
+
var msgs = util_1.extractMessages(node, tslib_1.__assign({ excludeMessageDeclCalls: true }, context.settings));
|
|
58
|
+
var opt = context.options[0];
|
|
59
|
+
var ignoreList = new Set((opt === null || opt === void 0 ? void 0 : opt.ignoreList) || []);
|
|
60
|
+
for (var _i = 0, msgs_1 = msgs; _i < msgs_1.length; _i++) {
|
|
61
|
+
var _a = msgs_1[_i], _b = _a[0], defaultMessage = _b.message.defaultMessage, messageNode = _b.messageNode, values = _a[1];
|
|
62
|
+
if (!defaultMessage || !messageNode) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
verifyAst(icu_messageformat_parser_1.parse(defaultMessage, {
|
|
67
|
+
ignoreTag: context.settings.ignoreTag,
|
|
68
|
+
}), values, ignoreList);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
context.report({
|
|
72
|
+
node: messageNode,
|
|
73
|
+
message: e.message,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
var rule = {
|
|
79
|
+
meta: {
|
|
80
|
+
type: 'problem',
|
|
81
|
+
docs: {
|
|
82
|
+
description: 'Enforce that all messages with placeholders have enough passed-in values',
|
|
83
|
+
category: 'Errors',
|
|
84
|
+
recommended: true,
|
|
85
|
+
url: 'https://formatjs.io/docs/tooling/linter#enforce-placeholders',
|
|
86
|
+
},
|
|
87
|
+
fixable: 'code',
|
|
88
|
+
schema: [
|
|
89
|
+
{
|
|
90
|
+
type: 'object',
|
|
91
|
+
properties: {
|
|
92
|
+
ignoreList: {
|
|
93
|
+
type: 'array',
|
|
94
|
+
items: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
additionalProperties: false,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
create: function (context) {
|
|
104
|
+
var callExpressionVisitor = function (node) {
|
|
105
|
+
return checkNode(context, node);
|
|
106
|
+
};
|
|
107
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
108
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
109
|
+
CallExpression: callExpressionVisitor,
|
|
110
|
+
}, {
|
|
111
|
+
CallExpression: callExpressionVisitor,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
JSXOpeningElement: function (node) { return checkNode(context, node); },
|
|
116
|
+
CallExpression: callExpressionVisitor,
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforce-plural-rules.d.ts","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-formatjs/rules/enforce-plural-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAoF3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA8ChB,CAAA;AAED,eAAe,IAAI,CAAA"}
|