eslint-plugin-formatjs 4.6.0 → 4.7.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.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +4 -0
- package/package.json +2 -1
- package/rules/no-multiple-whitespaces.d.ts.map +1 -1
- package/rules/no-multiple-whitespaces.js +15 -24
- package/rules/prefer-formatted-message.d.ts +4 -0
- package/rules/prefer-formatted-message.d.ts.map +1 -0
- package/rules/prefer-formatted-message.js +34 -0
- package/rules/prefer-pound-in-plural.d.ts +4 -0
- package/rules/prefer-pound-in-plural.d.ts.map +1 -0
- package/rules/prefer-pound-in-plural.js +187 -0
- package/util.d.ts +9 -0
- package/util.d.ts.map +1 -1
- package/util.js +26 -1
package/index.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ declare const plugin: {
|
|
|
16
16
|
'no-multiple-whitespaces': import("eslint").Rule.RuleModule;
|
|
17
17
|
'no-offset': import("eslint").Rule.RuleModule;
|
|
18
18
|
'no-useless-message': import("eslint").Rule.RuleModule;
|
|
19
|
+
'prefer-formatted-message': import("eslint").Rule.RuleModule;
|
|
20
|
+
'prefer-pound-in-plural': import("eslint").Rule.RuleModule;
|
|
19
21
|
};
|
|
20
22
|
};
|
|
21
23
|
export type Plugin = typeof plugin;
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAmBA,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;CAqBX,CAAA;AAED,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAA"}
|
package/index.js
CHANGED
|
@@ -17,6 +17,8 @@ const no_multiple_whitespaces_1 = tslib_1.__importDefault(require("./rules/no-mu
|
|
|
17
17
|
const no_offset_1 = tslib_1.__importDefault(require("./rules/no-offset"));
|
|
18
18
|
const no_literal_string_in_jsx_1 = tslib_1.__importDefault(require("./rules/no-literal-string-in-jsx"));
|
|
19
19
|
const no_useless_message_1 = tslib_1.__importDefault(require("./rules/no-useless-message"));
|
|
20
|
+
const prefer_formatted_message_1 = tslib_1.__importDefault(require("./rules/prefer-formatted-message"));
|
|
21
|
+
const prefer_pound_in_plural_1 = tslib_1.__importDefault(require("./rules/prefer-pound-in-plural"));
|
|
20
22
|
const plugin = {
|
|
21
23
|
rules: {
|
|
22
24
|
'blocklist-elements': blocklist_elements_1.default,
|
|
@@ -35,6 +37,8 @@ const plugin = {
|
|
|
35
37
|
'no-multiple-whitespaces': no_multiple_whitespaces_1.default,
|
|
36
38
|
'no-offset': no_offset_1.default,
|
|
37
39
|
'no-useless-message': no_useless_message_1.default,
|
|
40
|
+
'prefer-formatted-message': prefer_formatted_message_1.default,
|
|
41
|
+
'prefer-pound-in-plural': prefer_pound_in_plural_1.default,
|
|
38
42
|
},
|
|
39
43
|
};
|
|
40
44
|
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.7.0",
|
|
4
4
|
"description": "ESLint plugin for formatjs",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@types/picomatch": "^2.3.0",
|
|
27
27
|
"@typescript-eslint/typescript-estree": "5.45.0",
|
|
28
28
|
"emoji-regex": "^10.2.1",
|
|
29
|
+
"magic-string": "^0.29.0",
|
|
29
30
|
"picomatch": "^2.3.1",
|
|
30
31
|
"tslib": "2.4.0",
|
|
31
32
|
"typescript": "^4.7",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-multiple-whitespaces.d.ts","sourceRoot":"","sources":["no-multiple-whitespaces.ts"],"names":[],"mappings":"AAOA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"no-multiple-whitespaces.d.ts","sourceRoot":"","sources":["no-multiple-whitespaces.ts"],"names":[],"mappings":"AAOA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAiI3B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAkChB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -15,7 +15,6 @@ function isAstValid(ast) {
|
|
|
15
15
|
case icu_messageformat_parser_1.TYPE.literal:
|
|
16
16
|
case icu_messageformat_parser_1.TYPE.number:
|
|
17
17
|
case icu_messageformat_parser_1.TYPE.pound:
|
|
18
|
-
case icu_messageformat_parser_1.TYPE.tag:
|
|
19
18
|
case icu_messageformat_parser_1.TYPE.time:
|
|
20
19
|
break;
|
|
21
20
|
case icu_messageformat_parser_1.TYPE.plural:
|
|
@@ -27,6 +26,8 @@ function isAstValid(ast) {
|
|
|
27
26
|
}
|
|
28
27
|
break;
|
|
29
28
|
}
|
|
29
|
+
case icu_messageformat_parser_1.TYPE.tag:
|
|
30
|
+
return isAstValid(element.children);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
return true;
|
|
@@ -44,7 +45,6 @@ function trimMultiWhitespaces(message, ast) {
|
|
|
44
45
|
case icu_messageformat_parser_1.TYPE.literal:
|
|
45
46
|
case icu_messageformat_parser_1.TYPE.number:
|
|
46
47
|
case icu_messageformat_parser_1.TYPE.pound:
|
|
47
|
-
case icu_messageformat_parser_1.TYPE.tag:
|
|
48
48
|
case icu_messageformat_parser_1.TYPE.time:
|
|
49
49
|
break;
|
|
50
50
|
case icu_messageformat_parser_1.TYPE.plural:
|
|
@@ -54,6 +54,9 @@ function trimMultiWhitespaces(message, ast) {
|
|
|
54
54
|
}
|
|
55
55
|
break;
|
|
56
56
|
}
|
|
57
|
+
case icu_messageformat_parser_1.TYPE.tag:
|
|
58
|
+
collectLiteralElements(element.children);
|
|
59
|
+
break;
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
};
|
|
@@ -91,29 +94,14 @@ function checkNode(context, node) {
|
|
|
91
94
|
return;
|
|
92
95
|
}
|
|
93
96
|
if (!isAstValid(ast)) {
|
|
94
|
-
const
|
|
97
|
+
const newMessage = (0, util_1.patchMessage)(messageNode, ast, trimMultiWhitespaces);
|
|
98
|
+
context.report({
|
|
95
99
|
node: messageNode,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
reportObject.fix = function (fixer) {
|
|
102
|
-
return fixer.replaceText(messageNode, JSON.stringify(trimMultiWhitespaces(messageNode.value, ast)));
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
else if (messageNode.type === 'TemplateLiteral' &&
|
|
106
|
-
messageNode.quasis.length === 1 &&
|
|
107
|
-
messageNode.expressions.length === 0) {
|
|
108
|
-
reportObject.fix = function (fixer) {
|
|
109
|
-
return fixer.replaceText(messageNode, '`' +
|
|
110
|
-
trimMultiWhitespaces(messageNode.quasis[0].value.cooked, ast)
|
|
111
|
-
.replace(/\\/g, '\\\\')
|
|
112
|
-
.replace(/`/g, '\\`') +
|
|
113
|
-
'`');
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
context.report(reportObject);
|
|
100
|
+
messageId: 'noMultipleWhitespaces',
|
|
101
|
+
fix: newMessage !== null
|
|
102
|
+
? fixer => fixer.replaceText(messageNode, newMessage)
|
|
103
|
+
: null,
|
|
104
|
+
});
|
|
117
105
|
}
|
|
118
106
|
}
|
|
119
107
|
}
|
|
@@ -126,6 +114,9 @@ const rule = {
|
|
|
126
114
|
recommended: false,
|
|
127
115
|
url: 'https://formatjs.io/docs/tooling/linter#no-multiple-whitespaces',
|
|
128
116
|
},
|
|
117
|
+
messages: {
|
|
118
|
+
noMultipleWhitespaces: 'Multiple consecutive whitespaces are not allowed',
|
|
119
|
+
},
|
|
129
120
|
fixable: 'code',
|
|
130
121
|
},
|
|
131
122
|
create(context) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-formatted-message.d.ts","sourceRoot":"","sources":["prefer-formatted-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAIhC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAiChB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const util_1 = require("../util");
|
|
4
|
+
const rule = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
docs: {
|
|
8
|
+
description: 'Prefer `FormattedMessage` component over `intl.formatMessage` if applicable.',
|
|
9
|
+
recommended: false,
|
|
10
|
+
url: 'https://formatjs.io/docs/tooling/linter#prefer-formatted-message',
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
jsxChildren: 'Prefer `FormattedMessage` over `intl.formatMessage` in the JSX children expression.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
// TODO: Vue support
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
JSXElement: (node) => {
|
|
20
|
+
node.children.forEach(child => {
|
|
21
|
+
if (child.type !== 'JSXExpressionContainer' ||
|
|
22
|
+
!(0, util_1.isIntlFormatMessageCall)(child.expression)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
context.report({
|
|
26
|
+
node: node,
|
|
27
|
+
messageId: 'jsxChildren',
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
exports.default = rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-pound-in-plural.d.ts","sourceRoot":"","sources":["prefer-pound-in-plural.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AA6MhC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAmChB,CAAA;AAED,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
|
|
5
|
+
const util_1 = require("../util");
|
|
6
|
+
const magic_string_1 = tslib_1.__importDefault(require("magic-string"));
|
|
7
|
+
function verifyAst(context, messageNode, ast) {
|
|
8
|
+
const patches = [];
|
|
9
|
+
_verifyAst(ast);
|
|
10
|
+
if (patches.length > 0) {
|
|
11
|
+
const patchedMessage = (0, util_1.patchMessage)(messageNode, ast, content => {
|
|
12
|
+
return patches
|
|
13
|
+
.reduce((magicString, patch) => {
|
|
14
|
+
switch (patch.type) {
|
|
15
|
+
case 'prependLeft':
|
|
16
|
+
return magicString.prependLeft(patch.index, patch.content);
|
|
17
|
+
case 'remove':
|
|
18
|
+
return magicString.remove(patch.start, patch.end);
|
|
19
|
+
case 'update':
|
|
20
|
+
return magicString.update(patch.start, patch.end, patch.content);
|
|
21
|
+
}
|
|
22
|
+
}, new magic_string_1.default(content))
|
|
23
|
+
.toString();
|
|
24
|
+
});
|
|
25
|
+
context.report({
|
|
26
|
+
node: messageNode,
|
|
27
|
+
messageId: 'preferPoundInPlurals',
|
|
28
|
+
fix: patchedMessage !== null
|
|
29
|
+
? fixer => fixer.replaceText(messageNode, patchedMessage)
|
|
30
|
+
: null,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function _verifyAst(ast) {
|
|
34
|
+
for (let i = 0; i < ast.length; i++) {
|
|
35
|
+
const current = ast[i];
|
|
36
|
+
switch (current.type) {
|
|
37
|
+
case icu_messageformat_parser_1.TYPE.argument:
|
|
38
|
+
case icu_messageformat_parser_1.TYPE.number: {
|
|
39
|
+
// Applicable to only plain argument or number argument without any style
|
|
40
|
+
if (current.type === icu_messageformat_parser_1.TYPE.number && current.style) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
const next = ast[i + 1];
|
|
44
|
+
const nextNext = ast[i + 2];
|
|
45
|
+
if (next &&
|
|
46
|
+
nextNext &&
|
|
47
|
+
next.type === icu_messageformat_parser_1.TYPE.literal &&
|
|
48
|
+
next.value === ' ' &&
|
|
49
|
+
nextNext.type === icu_messageformat_parser_1.TYPE.plural &&
|
|
50
|
+
nextNext.value === current.value) {
|
|
51
|
+
// `{A} {A, plural, one {B} other {Bs}}` => `{A, plural, one {# B} other {# Bs}}`
|
|
52
|
+
_removeRangeAndPrependPluralClauses(current.location.start.offset, next.location.end.offset, nextNext, '# ');
|
|
53
|
+
}
|
|
54
|
+
else if (next &&
|
|
55
|
+
next.type === icu_messageformat_parser_1.TYPE.plural &&
|
|
56
|
+
next.value === current.value) {
|
|
57
|
+
// `{A}{A, plural, one {B} other {Bs}}` => `{A, plural, one {#B} other {#Bs}}`
|
|
58
|
+
_removeRangeAndPrependPluralClauses(current.location.start.offset, current.location.end.offset, next, '#');
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case icu_messageformat_parser_1.TYPE.plural: {
|
|
63
|
+
// `{A, plural, one {{A} B} other {{A} Bs}}` => `{A, plural, one {# B} other {# Bs}}`
|
|
64
|
+
const name = current.value;
|
|
65
|
+
for (const { value } of Object.values(current.options)) {
|
|
66
|
+
_replacementArgumentWithPound(name, value);
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case icu_messageformat_parser_1.TYPE.select: {
|
|
71
|
+
for (const { value } of Object.values(current.options)) {
|
|
72
|
+
_verifyAst(value);
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case icu_messageformat_parser_1.TYPE.tag:
|
|
77
|
+
_verifyAst(current.children);
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Replace plain argument of number argument w/o style option that matches
|
|
85
|
+
// the name with a pound sign.
|
|
86
|
+
function _replacementArgumentWithPound(name, ast) {
|
|
87
|
+
for (const element of ast) {
|
|
88
|
+
switch (element.type) {
|
|
89
|
+
case icu_messageformat_parser_1.TYPE.argument:
|
|
90
|
+
case icu_messageformat_parser_1.TYPE.number: {
|
|
91
|
+
if (element.value === name &&
|
|
92
|
+
// Either plain argument or number argument without any style
|
|
93
|
+
(element.type !== icu_messageformat_parser_1.TYPE.number || !element.style)) {
|
|
94
|
+
patches.push({
|
|
95
|
+
type: 'update',
|
|
96
|
+
start: element.location.start.offset,
|
|
97
|
+
end: element.location.end.offset,
|
|
98
|
+
content: '#',
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case icu_messageformat_parser_1.TYPE.tag: {
|
|
104
|
+
_replacementArgumentWithPound(name, element.children);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
case icu_messageformat_parser_1.TYPE.select: {
|
|
108
|
+
for (const { value } of Object.values(element.options)) {
|
|
109
|
+
_replacementArgumentWithPound(name, value);
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
default:
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Helper to remove a certain text range and then prepend the specified text to
|
|
119
|
+
// each plural clause.
|
|
120
|
+
function _removeRangeAndPrependPluralClauses(rangeToRemoveStart, rangeToRemoveEnd, pluralElement, prependText) {
|
|
121
|
+
// Delete both the `{A}` and ` `
|
|
122
|
+
patches.push({
|
|
123
|
+
type: 'remove',
|
|
124
|
+
start: rangeToRemoveStart,
|
|
125
|
+
end: rangeToRemoveEnd,
|
|
126
|
+
});
|
|
127
|
+
// Insert `# ` to the beginning of every option clause
|
|
128
|
+
for (const { location } of Object.values(pluralElement.options)) {
|
|
129
|
+
// location marks the entire clause with the surrounding braces
|
|
130
|
+
patches.push({
|
|
131
|
+
type: 'prependLeft',
|
|
132
|
+
index: location.start.offset + 1,
|
|
133
|
+
content: prependText,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function checkNode(context, node) {
|
|
139
|
+
const msgs = (0, util_1.extractMessages)(node, (0, util_1.getSettings)(context));
|
|
140
|
+
for (const [{ message: { defaultMessage }, messageNode, },] of msgs) {
|
|
141
|
+
if (!defaultMessage || !messageNode) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
let ast;
|
|
145
|
+
try {
|
|
146
|
+
ast = (0, icu_messageformat_parser_1.parse)(defaultMessage, { captureLocation: true });
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
context.report({
|
|
150
|
+
node: messageNode,
|
|
151
|
+
message: e instanceof Error ? e.message : String(e),
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
verifyAst(context, messageNode, ast);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const rule = {
|
|
159
|
+
meta: {
|
|
160
|
+
type: 'suggestion',
|
|
161
|
+
docs: {
|
|
162
|
+
description: 'Prefer using # to reference the count in the plural argument.',
|
|
163
|
+
recommended: false,
|
|
164
|
+
url: 'https://formatjs.io/docs/tooling/linter#prefer-pound-in-plurals',
|
|
165
|
+
},
|
|
166
|
+
messages: {
|
|
167
|
+
preferPoundInPlurals: 'Prefer using # to reference the count in the plural argument instead of repeating the argument.',
|
|
168
|
+
},
|
|
169
|
+
fixable: 'code',
|
|
170
|
+
},
|
|
171
|
+
// TODO: Vue support
|
|
172
|
+
create(context) {
|
|
173
|
+
const callExpressionVisitor = (node) => checkNode(context, node);
|
|
174
|
+
if (context.parserServices.defineTemplateBodyVisitor) {
|
|
175
|
+
return context.parserServices.defineTemplateBodyVisitor({
|
|
176
|
+
CallExpression: callExpressionVisitor,
|
|
177
|
+
}, {
|
|
178
|
+
CallExpression: callExpressionVisitor,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
JSXOpeningElement: (node) => checkNode(context, node),
|
|
183
|
+
CallExpression: callExpressionVisitor,
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
exports.default = rule;
|
package/util.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Rule } from 'eslint';
|
|
2
2
|
import { TSESTree } from '@typescript-eslint/typescript-estree';
|
|
3
|
+
import { MessageFormatElement } from '@formatjs/icu-messageformat-parser';
|
|
3
4
|
export interface MessageDescriptor {
|
|
4
5
|
id?: string;
|
|
5
6
|
defaultMessage?: string;
|
|
@@ -20,5 +21,13 @@ export interface MessageDescriptorNodeInfo {
|
|
|
20
21
|
idPropNode?: TSESTree.Property | TSESTree.JSXAttribute;
|
|
21
22
|
}
|
|
22
23
|
export declare function getSettings({ settings }: Rule.RuleContext): Settings;
|
|
24
|
+
export declare function isIntlFormatMessageCall(node: TSESTree.Node): node is TSESTree.CallExpression;
|
|
25
|
+
export declare function extractMessageDescriptor(node?: TSESTree.Expression): MessageDescriptorNodeInfo | undefined;
|
|
23
26
|
export declare function extractMessages(node: TSESTree.Node, { additionalComponentNames, additionalFunctionNames, excludeMessageDeclCalls, }?: Settings): Array<[MessageDescriptorNodeInfo, TSESTree.Expression | undefined]>;
|
|
27
|
+
/**
|
|
28
|
+
* Apply changes to the ICU message in code. The return value can be used in
|
|
29
|
+
* `fixer.replaceText(messageNode, <return value>)`. If the return value is null,
|
|
30
|
+
* it means that the patch cannot be applied.
|
|
31
|
+
*/
|
|
32
|
+
export declare function patchMessage(messageNode: TSESTree.Node, ast: MessageFormatElement[], patcher: (messageContent: string, ast: MessageFormatElement[]) => string): string | null;
|
|
24
33
|
//# sourceMappingURL=util.d.ts.map
|
package/util.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC3B,OAAO,EAAC,QAAQ,EAAC,MAAM,sCAAsC,CAAA;
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC3B,OAAO,EAAC,QAAQ,EAAC,MAAM,sCAAsC,CAAA;AAC7D,OAAO,EAAC,oBAAoB,EAAC,MAAM,oCAAoC,CAAA;AAEvE,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAC9B;AAMD,MAAM,WAAW,QAAQ;IACvB,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAA;IAClC,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAA;IACnC,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AACD,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,iBAAiB,CAAA;IAC1B,WAAW,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IACzE,eAAe,CAAC,EAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAA;IAC3D,eAAe,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IAC7E,WAAW,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IACzE,UAAU,CAAC,EAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAA;CACvD;AAED,wBAAgB,WAAW,CAAC,EAAC,QAAQ,EAAC,EAAE,IAAI,CAAC,WAAW,GAAG,QAAQ,CAElE;AA8BD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,QAAQ,CAAC,IAAI,GAClB,IAAI,IAAI,QAAQ,CAAC,cAAc,CAWjC;AAqBD,wBAAgB,wBAAwB,CACtC,IAAI,CAAC,EAAE,QAAQ,CAAC,UAAU,GACzB,yBAAyB,GAAG,SAAS,CA8CvC;AA8GD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,QAAQ,CAAC,IAAI,EACnB,EACE,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,GACxB,GAAE,QAAa,GACf,KAAK,CAAC,CAAC,yBAAyB,EAAE,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC,CAiDrE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,QAAQ,CAAC,IAAI,EAC1B,GAAG,EAAE,oBAAoB,EAAE,EAC3B,OAAO,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,oBAAoB,EAAE,KAAK,MAAM,GACvE,MAAM,GAAG,IAAI,CAsBf"}
|
package/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractMessages = exports.getSettings = void 0;
|
|
3
|
+
exports.patchMessage = exports.extractMessages = exports.extractMessageDescriptor = exports.isIntlFormatMessageCall = exports.getSettings = void 0;
|
|
4
4
|
const FORMAT_FUNCTION_NAMES = new Set(['$formatMessage', 'formatMessage', '$t']);
|
|
5
5
|
const COMPONENT_NAMES = new Set(['FormattedMessage']);
|
|
6
6
|
const DECLARATION_FUNCTION_NAMES = new Set(['defineMessage']);
|
|
@@ -37,6 +37,7 @@ function isIntlFormatMessageCall(node) {
|
|
|
37
37
|
node.arguments.length >= 1 &&
|
|
38
38
|
node.arguments[0].type === 'ObjectExpression');
|
|
39
39
|
}
|
|
40
|
+
exports.isIntlFormatMessageCall = isIntlFormatMessageCall;
|
|
40
41
|
function isSingleMessageDescriptorDeclaration(node, functionNames) {
|
|
41
42
|
return (node.type === 'CallExpression' &&
|
|
42
43
|
node.callee.type === 'Identifier' &&
|
|
@@ -95,6 +96,7 @@ function extractMessageDescriptor(node) {
|
|
|
95
96
|
}
|
|
96
97
|
return result;
|
|
97
98
|
}
|
|
99
|
+
exports.extractMessageDescriptor = extractMessageDescriptor;
|
|
98
100
|
function extractMessageDescriptorFromJSXElement(node) {
|
|
99
101
|
if (!node || !node.attributes) {
|
|
100
102
|
return;
|
|
@@ -238,3 +240,26 @@ function extractMessages(node, { additionalComponentNames, additionalFunctionNam
|
|
|
238
240
|
return [];
|
|
239
241
|
}
|
|
240
242
|
exports.extractMessages = extractMessages;
|
|
243
|
+
/**
|
|
244
|
+
* Apply changes to the ICU message in code. The return value can be used in
|
|
245
|
+
* `fixer.replaceText(messageNode, <return value>)`. If the return value is null,
|
|
246
|
+
* it means that the patch cannot be applied.
|
|
247
|
+
*/
|
|
248
|
+
function patchMessage(messageNode, ast, patcher) {
|
|
249
|
+
if (messageNode.type === 'Literal' &&
|
|
250
|
+
messageNode.value &&
|
|
251
|
+
typeof messageNode.value === 'string') {
|
|
252
|
+
return JSON.stringify(patcher(messageNode.value, ast));
|
|
253
|
+
}
|
|
254
|
+
else if (messageNode.type === 'TemplateLiteral' &&
|
|
255
|
+
messageNode.quasis.length === 1 &&
|
|
256
|
+
messageNode.expressions.length === 0) {
|
|
257
|
+
return ('`' +
|
|
258
|
+
patcher(messageNode.quasis[0].value.cooked, ast)
|
|
259
|
+
.replace(/\\/g, '\\\\')
|
|
260
|
+
.replace(/`/g, '\\`') +
|
|
261
|
+
'`');
|
|
262
|
+
}
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
exports.patchMessage = patchMessage;
|