@lingui/macro 4.8.0-next.1 → 4.8.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/dist/index.cjs +897 -30
- package/dist/index.d.cts +7 -1
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.mjs +896 -29
- package/index.d.ts +1 -34
- package/package.json +6 -21
- package/dist/plugin.cjs +0 -10
- package/dist/plugin.d.cts +0 -13
- package/dist/plugin.d.mts +0 -13
- package/dist/plugin.d.ts +0 -13
- package/dist/plugin.mjs +0 -4
- package/dist/shared/macro.0c5d598c.mjs +0 -1059
- package/dist/shared/macro.1cca3fdc.cjs +0 -1063
package/dist/index.cjs
CHANGED
|
@@ -1,36 +1,903 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const babelPluginMacros = require('babel-plugin-macros');
|
|
4
|
-
const
|
|
5
|
-
require('@babel/types');
|
|
6
|
-
require('@lingui/message-utils/generateMessageId');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
4
|
+
const conf = require('@lingui/conf');
|
|
5
|
+
const types = require('@babel/types');
|
|
6
|
+
const generateMessageId = require('@lingui/message-utils/generateMessageId');
|
|
7
|
+
|
|
8
|
+
const metaOptions = ["id", "comment", "props"];
|
|
9
|
+
const escapedMetaOptionsRe = new RegExp(`^_(${metaOptions.join("|")})$`);
|
|
10
|
+
class ICUMessageFormat {
|
|
11
|
+
fromTokens(tokens) {
|
|
12
|
+
return (Array.isArray(tokens) ? tokens : [tokens]).map((token) => this.processToken(token)).filter(Boolean).reduce(
|
|
13
|
+
(props, message) => ({
|
|
14
|
+
...message,
|
|
15
|
+
message: props.message + message.message,
|
|
16
|
+
values: { ...props.values, ...message.values },
|
|
17
|
+
jsxElements: { ...props.jsxElements, ...message.jsxElements }
|
|
18
|
+
}),
|
|
19
|
+
{
|
|
20
|
+
message: "",
|
|
21
|
+
values: {},
|
|
22
|
+
jsxElements: {}
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
processToken(token) {
|
|
27
|
+
const jsxElements = {};
|
|
28
|
+
if (token.type === "text") {
|
|
29
|
+
return {
|
|
30
|
+
message: token.value
|
|
31
|
+
};
|
|
32
|
+
} else if (token.type === "arg") {
|
|
33
|
+
if (token.value !== void 0 && types.isJSXEmptyExpression(token.value)) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const values = token.value !== void 0 ? { [token.name]: token.value } : {};
|
|
37
|
+
switch (token.format) {
|
|
38
|
+
case "plural":
|
|
39
|
+
case "select":
|
|
40
|
+
case "selectordinal":
|
|
41
|
+
const formatOptions = Object.keys(token.options).filter((key) => token.options[key] != null).map((key) => {
|
|
42
|
+
let value = token.options[key];
|
|
43
|
+
key = key.replace(escapedMetaOptionsRe, "$1");
|
|
44
|
+
if (key === "offset") {
|
|
45
|
+
return `offset:${value}`;
|
|
46
|
+
}
|
|
47
|
+
if (typeof value !== "string") {
|
|
48
|
+
const {
|
|
49
|
+
message,
|
|
50
|
+
values: childValues,
|
|
51
|
+
jsxElements: childJsxElements
|
|
52
|
+
} = this.fromTokens(value);
|
|
53
|
+
Object.assign(values, childValues);
|
|
54
|
+
Object.assign(jsxElements, childJsxElements);
|
|
55
|
+
value = message;
|
|
56
|
+
}
|
|
57
|
+
return `${key} {${value}}`;
|
|
58
|
+
}).join(" ");
|
|
59
|
+
return {
|
|
60
|
+
message: `{${token.name}, ${token.format}, ${formatOptions}}`,
|
|
61
|
+
values,
|
|
62
|
+
jsxElements
|
|
63
|
+
};
|
|
64
|
+
default:
|
|
65
|
+
return {
|
|
66
|
+
message: `{${token.name}}`,
|
|
67
|
+
values
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
} else if (token.type === "element") {
|
|
71
|
+
let message = "";
|
|
72
|
+
let elementValues = {};
|
|
73
|
+
Object.assign(jsxElements, { [token.name]: token.value });
|
|
74
|
+
token.children.forEach((child) => {
|
|
75
|
+
const {
|
|
76
|
+
message: childMessage,
|
|
77
|
+
values: childValues,
|
|
78
|
+
jsxElements: childJsxElements
|
|
79
|
+
} = this.fromTokens(child);
|
|
80
|
+
message += childMessage;
|
|
81
|
+
Object.assign(elementValues, childValues);
|
|
82
|
+
Object.assign(jsxElements, childJsxElements);
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
message: token.children.length ? `<${token.name}>${message}</${token.name}>` : `<${token.name}/>`,
|
|
86
|
+
values: elementValues,
|
|
87
|
+
jsxElements
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
throw new Error(`Unknown token type ${token.type}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const makeCounter = (index = 0) => () => index++;
|
|
95
|
+
|
|
96
|
+
const ID = "id";
|
|
97
|
+
const MESSAGE = "message";
|
|
98
|
+
const COMMENT = "comment";
|
|
99
|
+
const EXTRACT_MARK = "i18n";
|
|
100
|
+
const CONTEXT = "context";
|
|
101
|
+
|
|
102
|
+
var __defProp$1 = Object.defineProperty;
|
|
103
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
104
|
+
var __publicField$1 = (obj, key, value) => {
|
|
105
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
106
|
+
return value;
|
|
107
|
+
};
|
|
108
|
+
const keepSpaceRe$1 = /(?:\\(?:\r\n|\r|\n))+\s+/g;
|
|
109
|
+
const keepNewLineRe = /(?:\r\n|\r|\n)+\s+/g;
|
|
110
|
+
function normalizeWhitespace$1(text) {
|
|
111
|
+
return text.replace(keepSpaceRe$1, " ").replace(keepNewLineRe, "\n").trim();
|
|
112
|
+
}
|
|
113
|
+
function buildICUFromTokens(tokens) {
|
|
114
|
+
const messageFormat = new ICUMessageFormat();
|
|
115
|
+
const { message, values } = messageFormat.fromTokens(tokens);
|
|
116
|
+
return { message: normalizeWhitespace$1(message), values };
|
|
117
|
+
}
|
|
118
|
+
class MacroJs {
|
|
119
|
+
constructor({ types }, opts) {
|
|
120
|
+
// Babel Types
|
|
121
|
+
__publicField$1(this, "types");
|
|
122
|
+
// Identifier of i18n object
|
|
123
|
+
__publicField$1(this, "i18nImportName");
|
|
124
|
+
__publicField$1(this, "stripNonEssentialProps");
|
|
125
|
+
__publicField$1(this, "nameMap");
|
|
126
|
+
__publicField$1(this, "nameMapReversed");
|
|
127
|
+
// Positional expressions counter (e.g. for placeholders `Hello {0}, today is {1}`)
|
|
128
|
+
__publicField$1(this, "_expressionIndex", makeCounter());
|
|
129
|
+
__publicField$1(this, "replacePathWithMessage", (path, tokens, linguiInstance) => {
|
|
130
|
+
const newNode = this.createI18nCall(
|
|
131
|
+
this.createMessageDescriptorFromTokens(tokens, path.node.loc),
|
|
132
|
+
linguiInstance
|
|
133
|
+
);
|
|
134
|
+
path.replaceWith(newNode);
|
|
135
|
+
});
|
|
136
|
+
// Returns a boolean indicating if the replacement requires i18n import
|
|
137
|
+
__publicField$1(this, "replacePath", (path) => {
|
|
138
|
+
this._expressionIndex = makeCounter();
|
|
139
|
+
if (this.types.isCallExpression(path.node) && this.isDefineMessage(path.node.callee)) {
|
|
140
|
+
let descriptor = this.processDescriptor(path.node.arguments[0]);
|
|
141
|
+
path.replaceWith(descriptor);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (this.types.isTaggedTemplateExpression(path.node) && this.isDefineMessage(path.node.tag)) {
|
|
145
|
+
const tokens2 = this.tokenizeTemplateLiteral(path.node.quasi);
|
|
146
|
+
const descriptor = this.createMessageDescriptorFromTokens(
|
|
147
|
+
tokens2,
|
|
148
|
+
path.node.loc
|
|
149
|
+
);
|
|
150
|
+
path.replaceWith(descriptor);
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
if (this.types.isCallExpression(path.node) && this.types.isTaggedTemplateExpression(path.parentPath.node) && this.types.isExpression(path.node.arguments[0]) && this.isLinguiIdentifier(path.node.callee, "t")) {
|
|
154
|
+
const i18nInstance = path.node.arguments[0];
|
|
155
|
+
const tokens2 = this.tokenizeNode(path.parentPath.node);
|
|
156
|
+
this.replacePathWithMessage(path.parentPath, tokens2, i18nInstance);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
if (this.types.isCallExpression(path.node) && this.types.isCallExpression(path.parentPath.node) && this.types.isExpression(path.node.arguments[0]) && path.parentPath.node.callee === path.node && this.isLinguiIdentifier(path.node.callee, "t")) {
|
|
160
|
+
const i18nInstance = path.node.arguments[0];
|
|
161
|
+
this.replaceTAsFunction(
|
|
162
|
+
path.parentPath,
|
|
163
|
+
i18nInstance
|
|
164
|
+
);
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
if (this.types.isCallExpression(path.node) && this.isLinguiIdentifier(path.node.callee, "t")) {
|
|
168
|
+
this.replaceTAsFunction(path);
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
const tokens = this.tokenizeNode(path.node);
|
|
172
|
+
this.replacePathWithMessage(path, tokens);
|
|
173
|
+
return true;
|
|
174
|
+
});
|
|
175
|
+
/**
|
|
176
|
+
* macro `t` is called with MessageDescriptor, after that
|
|
177
|
+
* we create a new node to append it to i18n._
|
|
178
|
+
*/
|
|
179
|
+
__publicField$1(this, "replaceTAsFunction", (path, linguiInstance) => {
|
|
180
|
+
const descriptor = this.processDescriptor(path.node.arguments[0]);
|
|
181
|
+
path.replaceWith(this.createI18nCall(descriptor, linguiInstance));
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* `processDescriptor` expand macros inside message descriptor.
|
|
185
|
+
* Message descriptor is used in `defineMessage`.
|
|
186
|
+
*
|
|
187
|
+
* {
|
|
188
|
+
* comment: "Description",
|
|
189
|
+
* message: plural("value", { one: "book", other: "books" })
|
|
190
|
+
* }
|
|
191
|
+
*
|
|
192
|
+
* ↓ ↓ ↓ ↓ ↓ ↓
|
|
193
|
+
*
|
|
194
|
+
* {
|
|
195
|
+
* comment: "Description",
|
|
196
|
+
* id: <hash>
|
|
197
|
+
* message: "{value, plural, one {book} other {books}}"
|
|
198
|
+
* }
|
|
199
|
+
*
|
|
200
|
+
*/
|
|
201
|
+
__publicField$1(this, "processDescriptor", (descriptor_) => {
|
|
202
|
+
const descriptor = descriptor_;
|
|
203
|
+
const messageProperty = this.getObjectPropertyByKey(descriptor, MESSAGE);
|
|
204
|
+
const idProperty = this.getObjectPropertyByKey(descriptor, ID);
|
|
205
|
+
const contextProperty = this.getObjectPropertyByKey(descriptor, CONTEXT);
|
|
206
|
+
const properties = [idProperty];
|
|
207
|
+
if (!this.stripNonEssentialProps) {
|
|
208
|
+
properties.push(contextProperty);
|
|
209
|
+
}
|
|
210
|
+
if (messageProperty) {
|
|
211
|
+
const tokens = this.types.isTemplateLiteral(messageProperty.value) ? this.tokenizeTemplateLiteral(messageProperty.value) : this.tokenizeNode(messageProperty.value, true);
|
|
212
|
+
let messageNode = messageProperty.value;
|
|
213
|
+
if (tokens) {
|
|
214
|
+
const { message, values } = buildICUFromTokens(tokens);
|
|
215
|
+
messageNode = this.types.stringLiteral(message);
|
|
216
|
+
properties.push(this.createValuesProperty(values));
|
|
217
|
+
}
|
|
218
|
+
if (!this.stripNonEssentialProps) {
|
|
219
|
+
properties.push(
|
|
220
|
+
this.createObjectProperty(MESSAGE, messageNode)
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
if (!idProperty && this.types.isStringLiteral(messageNode)) {
|
|
224
|
+
const context = contextProperty && this.getTextFromExpression(contextProperty.value);
|
|
225
|
+
properties.push(this.createIdProperty(messageNode.value, context));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (!this.stripNonEssentialProps) {
|
|
229
|
+
properties.push(this.getObjectPropertyByKey(descriptor, COMMENT));
|
|
230
|
+
}
|
|
231
|
+
return this.createMessageDescriptor(properties, descriptor.loc);
|
|
232
|
+
});
|
|
233
|
+
this.types = types;
|
|
234
|
+
this.i18nImportName = opts.i18nImportName;
|
|
235
|
+
this.stripNonEssentialProps = opts.stripNonEssentialProps;
|
|
236
|
+
this.nameMap = opts.nameMap;
|
|
237
|
+
this.nameMapReversed = Array.from(opts.nameMap.entries()).reduce(
|
|
238
|
+
(map, [key, value]) => map.set(value, key),
|
|
239
|
+
/* @__PURE__ */ new Map()
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
createIdProperty(message, context) {
|
|
243
|
+
return this.createObjectProperty(
|
|
244
|
+
ID,
|
|
245
|
+
this.types.stringLiteral(generateMessageId.generateMessageId(message, context))
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
createValuesProperty(values) {
|
|
249
|
+
const valuesObject = Object.keys(values).map(
|
|
250
|
+
(key) => this.types.objectProperty(this.types.identifier(key), values[key])
|
|
251
|
+
);
|
|
252
|
+
if (!valuesObject.length)
|
|
253
|
+
return;
|
|
254
|
+
return this.types.objectProperty(
|
|
255
|
+
this.types.identifier("values"),
|
|
256
|
+
this.types.objectExpression(valuesObject)
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
tokenizeNode(node, ignoreExpression = false) {
|
|
260
|
+
if (this.isI18nMethod(node)) {
|
|
261
|
+
return this.tokenizeTemplateLiteral(node);
|
|
262
|
+
} else if (this.isChoiceMethod(node)) {
|
|
263
|
+
return [this.tokenizeChoiceComponent(node)];
|
|
264
|
+
} else if (!ignoreExpression) {
|
|
265
|
+
return [this.tokenizeExpression(node)];
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* `node` is a TemplateLiteral. node.quasi contains
|
|
270
|
+
* text chunks and node.expressions contains expressions.
|
|
271
|
+
* Both arrays must be zipped together to get the final list of tokens.
|
|
272
|
+
*/
|
|
273
|
+
tokenizeTemplateLiteral(node) {
|
|
274
|
+
const tpl = this.types.isTaggedTemplateExpression(node) ? node.quasi : node;
|
|
275
|
+
const expressions = tpl.expressions;
|
|
276
|
+
return tpl.quasis.flatMap((text, i) => {
|
|
277
|
+
const value = /\\u[a-fA-F0-9]{4}|\\x[a-fA-F0-9]{2}/g.test(text.value.raw) ? text.value.cooked : text.value.raw;
|
|
278
|
+
let argTokens = [];
|
|
279
|
+
const currExp = expressions[i];
|
|
280
|
+
if (currExp) {
|
|
281
|
+
argTokens = this.types.isCallExpression(currExp) ? this.tokenizeNode(currExp) : [this.tokenizeExpression(currExp)];
|
|
282
|
+
}
|
|
283
|
+
const textToken = {
|
|
284
|
+
type: "text",
|
|
285
|
+
value: this.clearBackslashes(value)
|
|
286
|
+
};
|
|
287
|
+
return [...value ? [textToken] : [], ...argTokens];
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
tokenizeChoiceComponent(node) {
|
|
291
|
+
const name = node.callee.name;
|
|
292
|
+
const format = (this.nameMapReversed.get(name) || name).toLowerCase();
|
|
293
|
+
const token = {
|
|
294
|
+
...this.tokenizeExpression(node.arguments[0]),
|
|
295
|
+
format,
|
|
296
|
+
options: {
|
|
297
|
+
offset: void 0
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
const props = node.arguments[1].properties;
|
|
301
|
+
for (const attr of props) {
|
|
302
|
+
const { key, value: attrValue } = attr;
|
|
303
|
+
const name2 = this.types.isNumericLiteral(key) ? `=${key.value}` : key.name || key.value;
|
|
304
|
+
if (format !== "select" && name2 === "offset") {
|
|
305
|
+
token.options.offset = attrValue.value;
|
|
306
|
+
} else {
|
|
307
|
+
let value;
|
|
308
|
+
if (this.types.isTemplateLiteral(attrValue)) {
|
|
309
|
+
value = this.tokenizeTemplateLiteral(attrValue);
|
|
310
|
+
} else if (this.types.isCallExpression(attrValue)) {
|
|
311
|
+
value = this.tokenizeNode(attrValue);
|
|
312
|
+
} else if (this.types.isStringLiteral(attrValue)) {
|
|
313
|
+
value = attrValue.value;
|
|
314
|
+
} else if (this.types.isExpression(attrValue)) {
|
|
315
|
+
value = this.tokenizeExpression(attrValue);
|
|
316
|
+
} else {
|
|
317
|
+
value = attrValue.value;
|
|
318
|
+
}
|
|
319
|
+
token.options[name2] = value;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return token;
|
|
323
|
+
}
|
|
324
|
+
tokenizeExpression(node) {
|
|
325
|
+
return {
|
|
326
|
+
type: "arg",
|
|
327
|
+
name: this.expressionToArgument(node),
|
|
328
|
+
value: node
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
expressionToArgument(exp) {
|
|
332
|
+
if (this.types.isIdentifier(exp)) {
|
|
333
|
+
return exp.name;
|
|
334
|
+
} else if (this.types.isStringLiteral(exp)) {
|
|
335
|
+
return exp.value;
|
|
336
|
+
} else {
|
|
337
|
+
return String(this._expressionIndex());
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* We clean '//\` ' to just '`'
|
|
342
|
+
*/
|
|
343
|
+
clearBackslashes(value) {
|
|
344
|
+
return value.replace(/\\`/g, "`");
|
|
345
|
+
}
|
|
346
|
+
createI18nCall(messageDescriptor, linguiInstance) {
|
|
347
|
+
return this.types.callExpression(
|
|
348
|
+
this.types.memberExpression(
|
|
349
|
+
linguiInstance ?? this.types.identifier(this.i18nImportName),
|
|
350
|
+
this.types.identifier("_")
|
|
351
|
+
),
|
|
352
|
+
[messageDescriptor]
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
createMessageDescriptorFromTokens(tokens, oldLoc) {
|
|
356
|
+
const { message, values } = buildICUFromTokens(tokens);
|
|
357
|
+
const properties = [
|
|
358
|
+
this.createIdProperty(message),
|
|
359
|
+
!this.stripNonEssentialProps ? this.createObjectProperty(MESSAGE, this.types.stringLiteral(message)) : null,
|
|
360
|
+
this.createValuesProperty(values)
|
|
361
|
+
];
|
|
362
|
+
return this.createMessageDescriptor(
|
|
363
|
+
properties,
|
|
364
|
+
// preserve line numbers for extractor
|
|
365
|
+
oldLoc
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
createMessageDescriptor(properties, oldLoc) {
|
|
369
|
+
const newDescriptor = this.types.objectExpression(
|
|
370
|
+
properties.filter(Boolean)
|
|
371
|
+
);
|
|
372
|
+
this.types.addComment(newDescriptor, "leading", EXTRACT_MARK);
|
|
373
|
+
if (oldLoc) {
|
|
374
|
+
newDescriptor.loc = oldLoc;
|
|
375
|
+
}
|
|
376
|
+
return newDescriptor;
|
|
377
|
+
}
|
|
378
|
+
createObjectProperty(key, value) {
|
|
379
|
+
return this.types.objectProperty(this.types.identifier(key), value);
|
|
380
|
+
}
|
|
381
|
+
getObjectPropertyByKey(objectExp, key) {
|
|
382
|
+
return objectExp.properties.find(
|
|
383
|
+
(property) => types.isObjectProperty(property) && this.isLinguiIdentifier(property.key, key)
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Custom matchers
|
|
388
|
+
*/
|
|
389
|
+
isLinguiIdentifier(node, name) {
|
|
390
|
+
return this.types.isIdentifier(node, {
|
|
391
|
+
name: this.nameMap.get(name) || name
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
isDefineMessage(node) {
|
|
395
|
+
return this.isLinguiIdentifier(node, "defineMessage") || this.isLinguiIdentifier(node, "msg");
|
|
396
|
+
}
|
|
397
|
+
isI18nMethod(node) {
|
|
398
|
+
return this.types.isTaggedTemplateExpression(node) && (this.isLinguiIdentifier(node.tag, "t") || this.types.isCallExpression(node.tag) && this.isLinguiIdentifier(node.tag.callee, "t"));
|
|
399
|
+
}
|
|
400
|
+
isChoiceMethod(node) {
|
|
401
|
+
return this.types.isCallExpression(node) && (this.isLinguiIdentifier(node.callee, "plural") || this.isLinguiIdentifier(node.callee, "select") || this.isLinguiIdentifier(node.callee, "selectOrdinal"));
|
|
402
|
+
}
|
|
403
|
+
getTextFromExpression(exp) {
|
|
404
|
+
if (this.types.isStringLiteral(exp)) {
|
|
405
|
+
return exp.value;
|
|
406
|
+
}
|
|
407
|
+
if (this.types.isTemplateLiteral(exp)) {
|
|
408
|
+
if (exp?.quasis.length === 1) {
|
|
409
|
+
return exp.quasis[0]?.value?.cooked;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
var __defProp = Object.defineProperty;
|
|
416
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
417
|
+
var __publicField = (obj, key, value) => {
|
|
418
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
419
|
+
return value;
|
|
420
|
+
};
|
|
421
|
+
const pluralRuleRe = /(_[\d\w]+|zero|one|two|few|many|other)/;
|
|
422
|
+
const jsx2icuExactChoice = (value) => value.replace(/_(\d+)/, "=$1").replace(/_(\w+)/, "$1");
|
|
423
|
+
const keepSpaceRe = /\s*(?:\r\n|\r|\n)+\s*/g;
|
|
424
|
+
const stripAroundTagsRe = /(?:([>}])(?:\r\n|\r|\n)+\s*|(?:\r\n|\r|\n)+\s*(?=[<{]))/g;
|
|
425
|
+
function maybeNodeValue(node) {
|
|
426
|
+
if (!node)
|
|
427
|
+
return null;
|
|
428
|
+
if (node.type === "StringLiteral")
|
|
429
|
+
return node.value;
|
|
430
|
+
if (node.type === "JSXAttribute")
|
|
431
|
+
return maybeNodeValue(node.value);
|
|
432
|
+
if (node.type === "JSXExpressionContainer")
|
|
433
|
+
return maybeNodeValue(node.expression);
|
|
434
|
+
if (node.type === "TemplateLiteral" && node.expressions.length === 0)
|
|
435
|
+
return node.quasis[0].value.raw;
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
function normalizeWhitespace(text) {
|
|
439
|
+
return text.replace(stripAroundTagsRe, "$1").replace(keepSpaceRe, " ").replace(/\\n/g, "\n").replace(/\\s/g, " ").replace(/(\s+})/gm, "}").replace(/({\s+)/gm, "{").trim();
|
|
440
|
+
}
|
|
441
|
+
class MacroJSX {
|
|
442
|
+
constructor({ types }, opts) {
|
|
443
|
+
__publicField(this, "types");
|
|
444
|
+
__publicField(this, "expressionIndex", makeCounter());
|
|
445
|
+
__publicField(this, "elementIndex", makeCounter());
|
|
446
|
+
__publicField(this, "stripNonEssentialProps");
|
|
447
|
+
__publicField(this, "nameMap");
|
|
448
|
+
__publicField(this, "nameMapReversed");
|
|
449
|
+
__publicField(this, "createStringJsxAttribute", (name, value) => {
|
|
450
|
+
return this.types.jsxAttribute(
|
|
451
|
+
this.types.jsxIdentifier(name),
|
|
452
|
+
this.types.jsxExpressionContainer(this.types.stringLiteral(value))
|
|
453
|
+
);
|
|
454
|
+
});
|
|
455
|
+
__publicField(this, "replacePath", (path) => {
|
|
456
|
+
if (!path.isJSXElement()) {
|
|
457
|
+
return path;
|
|
458
|
+
}
|
|
459
|
+
const tokens = this.tokenizeNode(path);
|
|
460
|
+
const messageFormat = new ICUMessageFormat();
|
|
461
|
+
const {
|
|
462
|
+
message: messageRaw,
|
|
463
|
+
values,
|
|
464
|
+
jsxElements
|
|
465
|
+
} = messageFormat.fromTokens(tokens);
|
|
466
|
+
const message = normalizeWhitespace(messageRaw);
|
|
467
|
+
const { attributes, id, comment, context } = this.stripMacroAttributes(
|
|
468
|
+
path
|
|
469
|
+
);
|
|
470
|
+
if (!id && !message) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
if (id) {
|
|
474
|
+
attributes.push(
|
|
475
|
+
this.types.jsxAttribute(
|
|
476
|
+
this.types.jsxIdentifier(ID),
|
|
477
|
+
this.types.stringLiteral(id)
|
|
478
|
+
)
|
|
479
|
+
);
|
|
480
|
+
} else {
|
|
481
|
+
attributes.push(
|
|
482
|
+
this.createStringJsxAttribute(ID, generateMessageId.generateMessageId(message, context))
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
if (!this.stripNonEssentialProps) {
|
|
486
|
+
if (message) {
|
|
487
|
+
attributes.push(this.createStringJsxAttribute(MESSAGE, message));
|
|
488
|
+
}
|
|
489
|
+
if (comment) {
|
|
490
|
+
attributes.push(
|
|
491
|
+
this.types.jsxAttribute(
|
|
492
|
+
this.types.jsxIdentifier(COMMENT),
|
|
493
|
+
this.types.stringLiteral(comment)
|
|
494
|
+
)
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
if (context) {
|
|
498
|
+
attributes.push(
|
|
499
|
+
this.types.jsxAttribute(
|
|
500
|
+
this.types.jsxIdentifier(CONTEXT),
|
|
501
|
+
this.types.stringLiteral(context)
|
|
502
|
+
)
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const valuesObject = Object.keys(values).map(
|
|
507
|
+
(key) => this.types.objectProperty(this.types.identifier(key), values[key])
|
|
508
|
+
);
|
|
509
|
+
if (valuesObject.length) {
|
|
510
|
+
attributes.push(
|
|
511
|
+
this.types.jsxAttribute(
|
|
512
|
+
this.types.jsxIdentifier("values"),
|
|
513
|
+
this.types.jsxExpressionContainer(
|
|
514
|
+
this.types.objectExpression(valuesObject)
|
|
515
|
+
)
|
|
516
|
+
)
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
if (Object.keys(jsxElements).length) {
|
|
520
|
+
attributes.push(
|
|
521
|
+
this.types.jsxAttribute(
|
|
522
|
+
this.types.jsxIdentifier("components"),
|
|
523
|
+
this.types.jsxExpressionContainer(
|
|
524
|
+
this.types.objectExpression(
|
|
525
|
+
Object.keys(jsxElements).map(
|
|
526
|
+
(key) => this.types.objectProperty(
|
|
527
|
+
this.types.identifier(key),
|
|
528
|
+
jsxElements[key]
|
|
529
|
+
)
|
|
530
|
+
)
|
|
531
|
+
)
|
|
532
|
+
)
|
|
533
|
+
)
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
const newNode = this.types.jsxElement(
|
|
537
|
+
this.types.jsxOpeningElement(
|
|
538
|
+
this.types.jsxIdentifier("Trans"),
|
|
539
|
+
attributes,
|
|
540
|
+
true
|
|
541
|
+
),
|
|
542
|
+
null,
|
|
543
|
+
[],
|
|
544
|
+
true
|
|
545
|
+
);
|
|
546
|
+
newNode.loc = path.node.loc;
|
|
547
|
+
path.replaceWith(newNode);
|
|
548
|
+
});
|
|
549
|
+
__publicField(this, "attrName", (names, exclude = false) => {
|
|
550
|
+
const namesRe = new RegExp("^(" + names.join("|") + ")$");
|
|
551
|
+
return (attr) => {
|
|
552
|
+
const name = attr.name.name;
|
|
553
|
+
return exclude ? !namesRe.test(name) : namesRe.test(name);
|
|
554
|
+
};
|
|
555
|
+
});
|
|
556
|
+
__publicField(this, "stripMacroAttributes", (path) => {
|
|
557
|
+
const { attributes } = path.node.openingElement;
|
|
558
|
+
const id = attributes.find(this.attrName([ID]));
|
|
559
|
+
const message = attributes.find(this.attrName([MESSAGE]));
|
|
560
|
+
const comment = attributes.find(this.attrName([COMMENT]));
|
|
561
|
+
const context = attributes.find(this.attrName([CONTEXT]));
|
|
562
|
+
let reserved = [ID, MESSAGE, COMMENT, CONTEXT];
|
|
563
|
+
if (this.isChoiceComponent(path)) {
|
|
564
|
+
reserved = [
|
|
565
|
+
...reserved,
|
|
566
|
+
"_\\w+",
|
|
567
|
+
"_\\d+",
|
|
568
|
+
"zero",
|
|
569
|
+
"one",
|
|
570
|
+
"two",
|
|
571
|
+
"few",
|
|
572
|
+
"many",
|
|
573
|
+
"other",
|
|
574
|
+
"value",
|
|
575
|
+
"offset"
|
|
576
|
+
];
|
|
577
|
+
}
|
|
578
|
+
return {
|
|
579
|
+
id: maybeNodeValue(id),
|
|
580
|
+
message: maybeNodeValue(message),
|
|
581
|
+
comment: maybeNodeValue(comment),
|
|
582
|
+
context: maybeNodeValue(context),
|
|
583
|
+
attributes: attributes.filter(this.attrName(reserved, true))
|
|
584
|
+
};
|
|
585
|
+
});
|
|
586
|
+
__publicField(this, "tokenizeNode", (path) => {
|
|
587
|
+
if (this.isTransComponent(path)) {
|
|
588
|
+
return this.tokenizeTrans(path);
|
|
589
|
+
} else if (this.isChoiceComponent(path)) {
|
|
590
|
+
return [this.tokenizeChoiceComponent(path)];
|
|
591
|
+
} else if (path.isJSXElement()) {
|
|
592
|
+
return [this.tokenizeElement(path)];
|
|
593
|
+
} else {
|
|
594
|
+
return [this.tokenizeExpression(path)];
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
__publicField(this, "tokenizeTrans", (path) => {
|
|
598
|
+
return path.get("children").flatMap((child) => this.tokenizeChildren(child)).filter(Boolean);
|
|
599
|
+
});
|
|
600
|
+
__publicField(this, "tokenizeChildren", (path) => {
|
|
601
|
+
if (path.isJSXExpressionContainer()) {
|
|
602
|
+
const exp = path.get("expression");
|
|
603
|
+
if (exp.isStringLiteral()) {
|
|
604
|
+
return [this.tokenizeText(exp.node.value.replace(/\n/g, "\\n"))];
|
|
605
|
+
}
|
|
606
|
+
if (exp.isTemplateLiteral()) {
|
|
607
|
+
return this.tokenizeTemplateLiteral(exp);
|
|
608
|
+
}
|
|
609
|
+
if (exp.isConditionalExpression()) {
|
|
610
|
+
return [this.tokenizeConditionalExpression(exp)];
|
|
611
|
+
}
|
|
612
|
+
if (exp.isJSXElement()) {
|
|
613
|
+
return this.tokenizeNode(exp);
|
|
614
|
+
}
|
|
615
|
+
return [this.tokenizeExpression(exp)];
|
|
616
|
+
} else if (path.isJSXElement()) {
|
|
617
|
+
return this.tokenizeNode(path);
|
|
618
|
+
} else if (path.isJSXSpreadChild()) ; else if (path.isJSXText()) {
|
|
619
|
+
return [this.tokenizeText(path.node.value)];
|
|
620
|
+
} else ;
|
|
621
|
+
});
|
|
622
|
+
__publicField(this, "tokenizeChoiceComponent", (path) => {
|
|
623
|
+
const element = path.get("openingElement");
|
|
624
|
+
const name = this.getJsxTagName(path.node);
|
|
625
|
+
const format = (this.nameMapReversed.get(name) || name).toLowerCase();
|
|
626
|
+
const props = element.get("attributes").filter((attr) => {
|
|
627
|
+
return this.attrName(
|
|
628
|
+
[
|
|
629
|
+
ID,
|
|
630
|
+
COMMENT,
|
|
631
|
+
MESSAGE,
|
|
632
|
+
CONTEXT,
|
|
633
|
+
"key",
|
|
634
|
+
// we remove <Trans /> react props that are not useful for translation
|
|
635
|
+
"render",
|
|
636
|
+
"component",
|
|
637
|
+
"components"
|
|
638
|
+
],
|
|
639
|
+
true
|
|
640
|
+
)(attr.node);
|
|
641
|
+
});
|
|
642
|
+
const token = {
|
|
643
|
+
type: "arg",
|
|
644
|
+
format,
|
|
645
|
+
name: null,
|
|
646
|
+
value: void 0,
|
|
647
|
+
options: {
|
|
648
|
+
offset: void 0
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
for (const _attr of props) {
|
|
652
|
+
if (_attr.isJSXSpreadAttribute()) {
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
const attr = _attr;
|
|
656
|
+
if (this.types.isJSXNamespacedName(attr.node.name)) {
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
const name2 = attr.node.name.name;
|
|
660
|
+
const value = attr.get("value");
|
|
661
|
+
if (name2 === "value") {
|
|
662
|
+
const exp = value.isLiteral() ? value : value.get("expression");
|
|
663
|
+
token.name = this.expressionToArgument(exp);
|
|
664
|
+
token.value = exp.node;
|
|
665
|
+
} else if (format !== "select" && name2 === "offset") {
|
|
666
|
+
token.options.offset = value.isStringLiteral() || value.isNumericLiteral() ? value.node.value : value.get(
|
|
667
|
+
"expression"
|
|
668
|
+
).node.value;
|
|
669
|
+
} else {
|
|
670
|
+
let option;
|
|
671
|
+
if (value.isStringLiteral()) {
|
|
672
|
+
option = value.node.extra.raw.replace(
|
|
673
|
+
/(["'])(.*)\1/,
|
|
674
|
+
"$2"
|
|
675
|
+
);
|
|
676
|
+
} else {
|
|
677
|
+
option = this.tokenizeChildren(value);
|
|
678
|
+
}
|
|
679
|
+
if (pluralRuleRe.test(name2)) {
|
|
680
|
+
token.options[jsx2icuExactChoice(name2)] = option;
|
|
681
|
+
} else {
|
|
682
|
+
token.options[name2] = option;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return token;
|
|
687
|
+
});
|
|
688
|
+
__publicField(this, "tokenizeElement", (path) => {
|
|
689
|
+
const name = this.elementIndex();
|
|
690
|
+
return {
|
|
691
|
+
type: "element",
|
|
692
|
+
name,
|
|
693
|
+
value: {
|
|
694
|
+
...path.node,
|
|
695
|
+
children: [],
|
|
696
|
+
openingElement: {
|
|
697
|
+
...path.node.openingElement,
|
|
698
|
+
selfClosing: true
|
|
699
|
+
}
|
|
700
|
+
},
|
|
701
|
+
children: this.tokenizeTrans(path)
|
|
702
|
+
};
|
|
703
|
+
});
|
|
704
|
+
__publicField(this, "tokenizeExpression", (path) => {
|
|
705
|
+
return {
|
|
706
|
+
type: "arg",
|
|
707
|
+
name: this.expressionToArgument(path),
|
|
708
|
+
value: path.node
|
|
709
|
+
};
|
|
710
|
+
});
|
|
711
|
+
__publicField(this, "tokenizeConditionalExpression", (exp) => {
|
|
712
|
+
exp.traverse({
|
|
713
|
+
JSXElement: (el) => {
|
|
714
|
+
if (this.isTransComponent(el) || this.isChoiceComponent(el)) {
|
|
715
|
+
this.replacePath(el);
|
|
716
|
+
el.skip();
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
return {
|
|
721
|
+
type: "arg",
|
|
722
|
+
name: this.expressionToArgument(exp),
|
|
723
|
+
value: exp.node
|
|
724
|
+
};
|
|
725
|
+
});
|
|
726
|
+
__publicField(this, "tokenizeText", (value) => {
|
|
727
|
+
return {
|
|
728
|
+
type: "text",
|
|
729
|
+
value
|
|
730
|
+
};
|
|
731
|
+
});
|
|
732
|
+
__publicField(this, "isLinguiComponent", (path, name) => {
|
|
733
|
+
return path.isJSXElement() && this.types.isJSXIdentifier(path.node.openingElement.name, {
|
|
734
|
+
name: this.nameMap.get(name) || name
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
__publicField(this, "isTransComponent", (path) => {
|
|
738
|
+
return this.isLinguiComponent(path, "Trans");
|
|
739
|
+
});
|
|
740
|
+
__publicField(this, "isChoiceComponent", (path) => {
|
|
741
|
+
return this.isLinguiComponent(path, "Plural") || this.isLinguiComponent(path, "Select") || this.isLinguiComponent(path, "SelectOrdinal");
|
|
742
|
+
});
|
|
743
|
+
__publicField(this, "getJsxTagName", (node) => {
|
|
744
|
+
if (this.types.isJSXIdentifier(node.openingElement.name)) {
|
|
745
|
+
return node.openingElement.name.name;
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
this.types = types;
|
|
749
|
+
this.stripNonEssentialProps = opts.stripNonEssentialProps;
|
|
750
|
+
this.nameMap = opts.nameMap;
|
|
751
|
+
this.nameMapReversed = Array.from(opts.nameMap.entries()).reduce(
|
|
752
|
+
(map, [key, value]) => map.set(value, key),
|
|
753
|
+
/* @__PURE__ */ new Map()
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
tokenizeTemplateLiteral(exp) {
|
|
757
|
+
const expressions = exp.get("expressions");
|
|
758
|
+
return exp.get("quasis").flatMap(({ node: text }, i) => {
|
|
759
|
+
const value = /\\u[a-fA-F0-9]{4}|\\x[a-fA-F0-9]{2}/g.test(text.value.raw) ? text.value.cooked : text.value.raw;
|
|
760
|
+
let argTokens = [];
|
|
761
|
+
const currExp = expressions[i];
|
|
762
|
+
if (currExp) {
|
|
763
|
+
argTokens = currExp.isCallExpression() ? this.tokenizeNode(currExp) : [this.tokenizeExpression(currExp)];
|
|
764
|
+
}
|
|
765
|
+
return [
|
|
766
|
+
...value ? [this.tokenizeText(this.clearBackslashes(value))] : [],
|
|
767
|
+
...argTokens
|
|
768
|
+
];
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
expressionToArgument(path) {
|
|
772
|
+
return path.isIdentifier() ? path.node.name : String(this.expressionIndex());
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* We clean '//\` ' to just '`'
|
|
776
|
+
**/
|
|
777
|
+
clearBackslashes(value) {
|
|
778
|
+
return value.replace(/\\`/g, "`");
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
const jsMacroTags = /* @__PURE__ */ new Set([
|
|
783
|
+
"defineMessage",
|
|
784
|
+
"msg",
|
|
785
|
+
"arg",
|
|
786
|
+
"t",
|
|
787
|
+
"plural",
|
|
788
|
+
"select",
|
|
789
|
+
"selectOrdinal"
|
|
790
|
+
]);
|
|
791
|
+
const jsxMacroTags = /* @__PURE__ */ new Set(["Trans", "Plural", "Select", "SelectOrdinal"]);
|
|
792
|
+
let config;
|
|
793
|
+
function getConfig(_config) {
|
|
794
|
+
if (_config) {
|
|
795
|
+
config = _config;
|
|
796
|
+
}
|
|
797
|
+
if (!config) {
|
|
798
|
+
config = conf.getConfig();
|
|
799
|
+
}
|
|
800
|
+
return config;
|
|
801
|
+
}
|
|
802
|
+
function macro({ references, state, babel, config: config2 }) {
|
|
803
|
+
const opts = config2;
|
|
804
|
+
const {
|
|
805
|
+
i18nImportModule,
|
|
806
|
+
i18nImportName,
|
|
807
|
+
TransImportModule,
|
|
808
|
+
TransImportName
|
|
809
|
+
} = getConfig(opts.linguiConfig).runtimeConfigModule;
|
|
810
|
+
const jsxNodes = /* @__PURE__ */ new Set();
|
|
811
|
+
const jsNodes = /* @__PURE__ */ new Set();
|
|
812
|
+
let needsI18nImport = false;
|
|
813
|
+
let nameMap = /* @__PURE__ */ new Map();
|
|
814
|
+
Object.keys(references).forEach((tagName) => {
|
|
815
|
+
const nodes = references[tagName];
|
|
816
|
+
if (jsMacroTags.has(tagName)) {
|
|
817
|
+
nodes.forEach((path) => {
|
|
818
|
+
nameMap.set(tagName, path.node.name);
|
|
819
|
+
jsNodes.add(path.parentPath);
|
|
820
|
+
});
|
|
821
|
+
} else if (jsxMacroTags.has(tagName)) {
|
|
822
|
+
nodes.forEach((path) => {
|
|
823
|
+
nameMap.set(tagName, path.node.name);
|
|
824
|
+
jsxNodes.add(path.parentPath.parentPath);
|
|
825
|
+
});
|
|
826
|
+
} else {
|
|
827
|
+
throw nodes[0].buildCodeFrameError(`Unknown macro ${tagName}`);
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
const stripNonEssentialProps = process.env.NODE_ENV == "production" && !opts.extract;
|
|
831
|
+
const jsNodesArray = Array.from(jsNodes);
|
|
832
|
+
jsNodesArray.filter(isRootPath(jsNodesArray)).forEach((path) => {
|
|
833
|
+
const macro2 = new MacroJs(babel, {
|
|
834
|
+
i18nImportName,
|
|
835
|
+
stripNonEssentialProps,
|
|
836
|
+
nameMap
|
|
837
|
+
});
|
|
838
|
+
try {
|
|
839
|
+
if (macro2.replacePath(path))
|
|
840
|
+
needsI18nImport = true;
|
|
841
|
+
} catch (e) {
|
|
842
|
+
reportUnsupportedSyntax(path, e);
|
|
843
|
+
}
|
|
844
|
+
});
|
|
845
|
+
const jsxNodesArray = Array.from(jsxNodes);
|
|
846
|
+
jsxNodesArray.filter(isRootPath(jsxNodesArray)).forEach((path) => {
|
|
847
|
+
const macro2 = new MacroJSX(babel, { stripNonEssentialProps, nameMap });
|
|
848
|
+
try {
|
|
849
|
+
macro2.replacePath(path);
|
|
850
|
+
} catch (e) {
|
|
851
|
+
reportUnsupportedSyntax(path, e);
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
if (needsI18nImport) {
|
|
855
|
+
addImport(babel, state, i18nImportModule, i18nImportName);
|
|
856
|
+
}
|
|
857
|
+
if (jsxNodes.size) {
|
|
858
|
+
addImport(babel, state, TransImportModule, TransImportName);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
function reportUnsupportedSyntax(path, e) {
|
|
862
|
+
throw path.buildCodeFrameError(
|
|
863
|
+
`Unsupported macro usage. Please check the examples at https://lingui.dev/ref/macro#examples-of-js-macros.
|
|
864
|
+
If you think this is a bug, fill in an issue at https://github.com/lingui/js-lingui/issues
|
|
865
|
+
|
|
866
|
+
Error: ${e.message}`
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
function addImport(babel, state, module2, importName) {
|
|
870
|
+
const { types: t } = babel;
|
|
871
|
+
const linguiImport = state.file.path.node.body.find(
|
|
872
|
+
(importNode) => t.isImportDeclaration(importNode) && importNode.source.value === module2 && // https://github.com/lingui/js-lingui/issues/777
|
|
873
|
+
importNode.importKind !== "type"
|
|
874
|
+
);
|
|
875
|
+
const tIdentifier = t.identifier(importName);
|
|
876
|
+
if (linguiImport) {
|
|
877
|
+
if (linguiImport.specifiers.findIndex(
|
|
878
|
+
(specifier) => types.isImportSpecifier(specifier) && types.isIdentifier(specifier.imported, { name: importName })
|
|
879
|
+
) === -1) {
|
|
880
|
+
linguiImport.specifiers.push(t.importSpecifier(tIdentifier, tIdentifier));
|
|
881
|
+
}
|
|
882
|
+
} else {
|
|
883
|
+
state.file.path.node.body.unshift(
|
|
884
|
+
t.importDeclaration(
|
|
885
|
+
[t.importSpecifier(tIdentifier, tIdentifier)],
|
|
886
|
+
t.stringLiteral(module2)
|
|
887
|
+
)
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
function isRootPath(allPath) {
|
|
892
|
+
return (node) => function traverse(path) {
|
|
893
|
+
if (!path.parentPath) {
|
|
894
|
+
return true;
|
|
895
|
+
} else {
|
|
896
|
+
return !allPath.includes(path.parentPath) && traverse(path.parentPath);
|
|
897
|
+
}
|
|
898
|
+
}(node);
|
|
899
|
+
}
|
|
900
|
+
[...jsMacroTags, ...jsxMacroTags].forEach((name) => {
|
|
34
901
|
Object.defineProperty(module.exports, name, {
|
|
35
902
|
get() {
|
|
36
903
|
throw new Error(
|