@lingui/macro 4.0.0-next.3 → 4.0.0-next.5

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/build/macroJs.js DELETED
@@ -1,340 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _types = require("@babel/types");
8
- var _icu = _interopRequireDefault(require("./icu"));
9
- var _utils = require("./utils");
10
- var _constants = require("./constants");
11
- var _api = require("@lingui/cli/api");
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
- const keepSpaceRe = /(?:\\(?:\r\n|\r|\n))+\s+/g;
14
- const keepNewLineRe = /(?:\r\n|\r|\n)+\s+/g;
15
- function normalizeWhitespace(text) {
16
- return text.replace(keepSpaceRe, " ").replace(keepNewLineRe, "\n").trim();
17
- }
18
- function buildICUFromTokens(tokens) {
19
- const messageFormat = new _icu.default();
20
- const {
21
- message,
22
- values
23
- } = messageFormat.fromTokens(tokens);
24
- return {
25
- message: normalizeWhitespace(message),
26
- values
27
- };
28
- }
29
- class MacroJs {
30
- // Babel Types
31
-
32
- // Identifier of i18n object
33
-
34
- // Positional expressions counter (e.g. for placeholders `Hello {0}, today is {1}`)
35
- _expressionIndex = (0, _utils.makeCounter)();
36
- constructor({
37
- types
38
- }, opts) {
39
- this.types = types;
40
- this.i18nImportName = opts.i18nImportName;
41
- this.stripNonEssentialProps = opts.stripNonEssentialProps;
42
- this.nameMap = opts.nameMap;
43
- this.nameMapReversed = Array.from(opts.nameMap.entries()).reduce((map, [key, value]) => map.set(value, key), new Map());
44
- }
45
- replacePathWithMessage = (path, tokens, linguiInstance) => {
46
- const newNode = this.createI18nCall(this.createMessageDescriptorFromTokens(tokens, path.node.loc), linguiInstance);
47
- path.replaceWith(newNode);
48
- };
49
-
50
- // Returns a boolean indicating if the replacement requires i18n import
51
- replacePath = path => {
52
- // reset the expression counter
53
- this._expressionIndex = (0, _utils.makeCounter)();
54
-
55
- // defineMessage({ message: "Message", context: "My" }) -> {id: <hash + context>, message: "Message"}
56
- if (this.types.isCallExpression(path.node) && this.isDefineMessage(path.node.callee)) {
57
- let descriptor = this.processDescriptor(path.node.arguments[0]);
58
- path.replaceWith(descriptor);
59
- return false;
60
- }
61
-
62
- // defineMessage`Message` -> {id: <hash>, message: "Message"}
63
- if (this.types.isTaggedTemplateExpression(path.node) && this.isDefineMessage(path.node.tag)) {
64
- const tokens = this.tokenizeTemplateLiteral(path.node.quasi);
65
- const descriptor = this.createMessageDescriptorFromTokens(tokens, path.node.loc);
66
- path.replaceWith(descriptor);
67
- return false;
68
- }
69
-
70
- // t(i18nInstance)`Message` -> i18nInstance._(messageDescriptor)
71
- 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")) {
72
- // Use the first argument as i18n instance instead of the default i18n instance
73
- const i18nInstance = path.node.arguments[0];
74
- const tokens = this.tokenizeNode(path.parentPath.node);
75
- this.replacePathWithMessage(path.parentPath, tokens, i18nInstance);
76
- return false;
77
- }
78
-
79
- // t(i18nInstance)(messageDescriptor) -> i18nInstance._(messageDescriptor)
80
- 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")) {
81
- const i18nInstance = path.node.arguments[0];
82
- this.replaceTAsFunction(path.parentPath, i18nInstance);
83
- return false;
84
- }
85
-
86
- // t({...})
87
- if (this.types.isCallExpression(path.node) && this.isLinguiIdentifier(path.node.callee, "t")) {
88
- this.replaceTAsFunction(path);
89
- return true;
90
- }
91
- const tokens = this.tokenizeNode(path.node);
92
- this.replacePathWithMessage(path, tokens);
93
- return true;
94
- };
95
-
96
- /**
97
- * macro `t` is called with MessageDescriptor, after that
98
- * we create a new node to append it to i18n._
99
- */
100
- replaceTAsFunction = (path, linguiInstance) => {
101
- const descriptor = this.processDescriptor(path.node.arguments[0]);
102
- path.replaceWith(this.createI18nCall(descriptor, linguiInstance));
103
- };
104
-
105
- /**
106
- * `processDescriptor` expand macros inside message descriptor.
107
- * Message descriptor is used in `defineMessage`.
108
- *
109
- * {
110
- * comment: "Description",
111
- * message: plural("value", { one: "book", other: "books" })
112
- * }
113
- *
114
- * ↓ ↓ ↓ ↓ ↓ ↓
115
- *
116
- * {
117
- * comment: "Description",
118
- * id: <hash>
119
- * message: "{value, plural, one {book} other {books}}"
120
- * }
121
- *
122
- */
123
- processDescriptor = descriptor_ => {
124
- const descriptor = descriptor_;
125
- const messageProperty = this.getObjectPropertyByKey(descriptor, _constants.MESSAGE);
126
- const idProperty = this.getObjectPropertyByKey(descriptor, _constants.ID);
127
- const contextProperty = this.getObjectPropertyByKey(descriptor, _constants.CONTEXT);
128
- const properties = [idProperty];
129
- if (!this.stripNonEssentialProps) {
130
- properties.push(contextProperty);
131
- }
132
-
133
- // if there's `message` property, replace macros with formatted message
134
- if (messageProperty) {
135
- // Inside message descriptor the `t` macro in `message` prop is optional.
136
- // Template strings are always processed as if they were wrapped by `t`.
137
- const tokens = this.types.isTemplateLiteral(messageProperty.value) ? this.tokenizeTemplateLiteral(messageProperty.value) : this.tokenizeNode(messageProperty.value, true);
138
- let messageNode = messageProperty.value;
139
- if (tokens) {
140
- const {
141
- message,
142
- values
143
- } = buildICUFromTokens(tokens);
144
- messageNode = this.types.stringLiteral(message);
145
- properties.push(this.createValuesProperty(values));
146
- }
147
- if (!this.stripNonEssentialProps) {
148
- properties.push(this.createObjectProperty(_constants.MESSAGE, messageNode));
149
- }
150
- if (!idProperty && this.types.isStringLiteral(messageNode)) {
151
- const context = contextProperty && this.getTextFromExpression(contextProperty.value);
152
- properties.push(this.createIdProperty(messageNode.value, context));
153
- }
154
- }
155
- if (!this.stripNonEssentialProps) {
156
- properties.push(this.getObjectPropertyByKey(descriptor, _constants.COMMENT));
157
- }
158
- return this.createMessageDescriptor(properties, descriptor.loc);
159
- };
160
- createIdProperty(message, context) {
161
- return this.createObjectProperty(_constants.ID, this.types.stringLiteral((0, _api.generateMessageId)(message, context)));
162
- }
163
- createValuesProperty(values) {
164
- const valuesObject = Object.keys(values).map(key => this.types.objectProperty(this.types.identifier(key), values[key]));
165
- if (!valuesObject.length) return;
166
- return this.types.objectProperty(this.types.identifier("values"), this.types.objectExpression(valuesObject));
167
- }
168
- tokenizeNode(node, ignoreExpression = false) {
169
- if (this.isI18nMethod(node)) {
170
- // t
171
- return this.tokenizeTemplateLiteral(node);
172
- } else if (this.isChoiceMethod(node)) {
173
- // plural, select and selectOrdinal
174
- return [this.tokenizeChoiceComponent(node)];
175
- // } else if (isFormatMethod(node.callee)) {
176
- // // date, number
177
- // return transformFormatMethod(node, file, props, root)
178
- } else if (!ignoreExpression) {
179
- return [this.tokenizeExpression(node)];
180
- }
181
- }
182
-
183
- /**
184
- * `node` is a TemplateLiteral. node.quasi contains
185
- * text chunks and node.expressions contains expressions.
186
- * Both arrays must be zipped together to get the final list of tokens.
187
- */
188
- tokenizeTemplateLiteral(node) {
189
- const tpl = this.types.isTaggedTemplateExpression(node) ? node.quasi : node;
190
- const expressions = tpl.expressions;
191
- return tpl.quasis.flatMap((text, i) => {
192
- // if it's an unicode we keep the cooked value because it's the parsed value by babel (without unicode chars)
193
- // This regex will detect if a string contains unicode chars, when they're we should interpolate them
194
- // why? because platforms like react native doesn't parse them, just doing a JSON.parse makes them UTF-8 friendly
195
- 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;
196
- let argTokens = [];
197
- const currExp = expressions[i];
198
- if (currExp) {
199
- argTokens = this.types.isCallExpression(currExp) ? this.tokenizeNode(currExp) : [this.tokenizeExpression(currExp)];
200
- }
201
- return [...(value ? [{
202
- type: "text",
203
- value: this.clearBackslashes(value)
204
- }] : []), ...argTokens];
205
- });
206
- }
207
- tokenizeChoiceComponent(node) {
208
- const name = node.callee.name;
209
- const format = (this.nameMapReversed.get(name) || name).toLowerCase();
210
- const token = {
211
- ...this.tokenizeExpression(node.arguments[0]),
212
- format,
213
- options: {
214
- offset: undefined
215
- }
216
- };
217
- const props = node.arguments[1].properties;
218
- for (const attr of props) {
219
- const {
220
- key,
221
- value: attrValue
222
- } = attr;
223
-
224
- // name is either:
225
- // NumericLiteral => convert to `={number}`
226
- // StringLiteral => key.value
227
- // Identifier => key.name
228
- const name = this.types.isNumericLiteral(key) ? `=${key.value}` : key.name || key.value;
229
- if (format !== "select" && name === "offset") {
230
- token.options.offset = attrValue.value;
231
- } else {
232
- let value;
233
- if (this.types.isTemplateLiteral(attrValue)) {
234
- value = this.tokenizeTemplateLiteral(attrValue);
235
- } else if (this.types.isCallExpression(attrValue)) {
236
- value = this.tokenizeNode(attrValue);
237
- } else if (this.types.isStringLiteral(attrValue)) {
238
- value = attrValue.value;
239
- } else if (this.types.isExpression(attrValue)) {
240
- value = this.tokenizeExpression(attrValue);
241
- } else {
242
- value = attrValue.value;
243
- }
244
- token.options[name] = value;
245
- }
246
- }
247
- return token;
248
- }
249
- tokenizeExpression(node) {
250
- if (this.isArg(node) && this.types.isCallExpression(node)) {
251
- return {
252
- type: "arg",
253
- name: node.arguments[0].value,
254
- value: undefined
255
- };
256
- }
257
- return {
258
- type: "arg",
259
- name: this.expressionToArgument(node),
260
- value: node
261
- };
262
- }
263
- expressionToArgument(exp) {
264
- if (this.types.isIdentifier(exp)) {
265
- return exp.name;
266
- } else if (this.types.isStringLiteral(exp)) {
267
- return exp.value;
268
- } else {
269
- return String(this._expressionIndex());
270
- }
271
- }
272
-
273
- /**
274
- * We clean '//\` ' to just '`'
275
- */
276
- clearBackslashes(value) {
277
- // if not we replace the extra scaped literals
278
- return value.replace(/\\`/g, "`");
279
- }
280
- createI18nCall(messageDescriptor, linguiInstance) {
281
- return this.types.callExpression(this.types.memberExpression(linguiInstance ?? this.types.identifier(this.i18nImportName), this.types.identifier("_")), [messageDescriptor]);
282
- }
283
- createMessageDescriptorFromTokens(tokens, oldLoc) {
284
- const {
285
- message,
286
- values
287
- } = buildICUFromTokens(tokens);
288
- const properties = [this.createIdProperty(message), !this.stripNonEssentialProps ? this.createObjectProperty(_constants.MESSAGE, this.types.stringLiteral(message)) : null, this.createValuesProperty(values)];
289
- return this.createMessageDescriptor(properties,
290
- // preserve line numbers for extractor
291
- oldLoc);
292
- }
293
- createMessageDescriptor(properties, oldLoc) {
294
- const newDescriptor = this.types.objectExpression(properties.filter(Boolean));
295
- this.types.addComment(newDescriptor, "leading", _constants.EXTRACT_MARK);
296
- if (oldLoc) {
297
- newDescriptor.loc = oldLoc;
298
- }
299
- return newDescriptor;
300
- }
301
- createObjectProperty(key, value) {
302
- return this.types.objectProperty(this.types.identifier(key), value);
303
- }
304
- getObjectPropertyByKey(objectExp, key) {
305
- return objectExp.properties.find(property => (0, _types.isObjectProperty)(property) && this.isLinguiIdentifier(property.key, key));
306
- }
307
-
308
- /**
309
- * Custom matchers
310
- */
311
- isLinguiIdentifier(node, name) {
312
- return this.types.isIdentifier(node, {
313
- name: this.nameMap.get(name) || name
314
- });
315
- }
316
- isDefineMessage(node) {
317
- return this.isLinguiIdentifier(node, "defineMessage") || this.isLinguiIdentifier(node, "msg");
318
- }
319
- isArg(node) {
320
- return this.types.isCallExpression(node) && this.isLinguiIdentifier(node.callee, "arg");
321
- }
322
- isI18nMethod(node) {
323
- return this.types.isTaggedTemplateExpression(node) && (this.isLinguiIdentifier(node.tag, "t") || this.types.isCallExpression(node.tag) && this.isLinguiIdentifier(node.tag.callee, "t"));
324
- }
325
- isChoiceMethod(node) {
326
- return this.types.isCallExpression(node) && (this.isLinguiIdentifier(node.callee, "plural") || this.isLinguiIdentifier(node.callee, "select") || this.isLinguiIdentifier(node.callee, "selectOrdinal"));
327
- }
328
- getTextFromExpression(exp) {
329
- if (this.types.isStringLiteral(exp)) {
330
- return exp.value;
331
- }
332
- if (this.types.isTemplateLiteral(exp)) {
333
- if ((exp === null || exp === void 0 ? void 0 : exp.quasis.length) === 1) {
334
- var _exp$quasis$, _exp$quasis$$value;
335
- return (_exp$quasis$ = exp.quasis[0]) === null || _exp$quasis$ === void 0 ? void 0 : (_exp$quasis$$value = _exp$quasis$.value) === null || _exp$quasis$$value === void 0 ? void 0 : _exp$quasis$$value.cooked;
336
- }
337
- }
338
- }
339
- }
340
- exports.default = MacroJs;
package/build/macroJsx.js DELETED
@@ -1,313 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- exports.normalizeWhitespace = normalizeWhitespace;
8
- var _icu = _interopRequireDefault(require("./icu"));
9
- var _utils = require("./utils");
10
- var _constants = require("./constants");
11
- var _api = require("@lingui/cli/api");
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
- const pluralRuleRe = /(_[\d\w]+|zero|one|two|few|many|other)/;
14
- const jsx2icuExactChoice = value => value.replace(/_(\d+)/, "=$1").replace(/_(\w+)/, "$1");
15
- // replace whitespace before/after newline with single space
16
- const keepSpaceRe = /\s*(?:\r\n|\r|\n)+\s*/g;
17
- // remove whitespace before/after tag or expression
18
- const stripAroundTagsRe = /(?:([>}])(?:\r\n|\r|\n)+\s*|(?:\r\n|\r|\n)+\s*(?=[<{]))/g;
19
- function maybeNodeValue(node) {
20
- if (!node) return null;
21
- if (node.type === "StringLiteral") return node.value;
22
- if (node.type === "JSXAttribute") return maybeNodeValue(node.value);
23
- if (node.type === "JSXExpressionContainer") return maybeNodeValue(node.expression);
24
- if (node.type === "TemplateLiteral" && node.expressions.length === 0) return node.quasis[0].value.raw;
25
- return null;
26
- }
27
- function normalizeWhitespace(text) {
28
- return text.replace(stripAroundTagsRe, "$1").replace(keepSpaceRe, " ")
29
- // keep escaped newlines
30
- .replace(/\\n/g, "\n").replace(/\\s/g, " ")
31
- // we remove trailing whitespace inside Plural
32
- .replace(/(\s+})/gm, "}")
33
- // we remove leading whitespace inside Plural
34
- .replace(/({\s+)/gm, "{").trim();
35
- }
36
- class MacroJSX {
37
- expressionIndex = (0, _utils.makeCounter)();
38
- elementIndex = (0, _utils.makeCounter)();
39
- constructor({
40
- types
41
- }, opts) {
42
- this.types = types;
43
- this.stripNonEssentialProps = opts.stripNonEssentialProps;
44
- this.nameMap = opts.nameMap;
45
- this.nameMapReversed = Array.from(opts.nameMap.entries()).reduce((map, [key, value]) => map.set(value, key), new Map());
46
- }
47
- createStringJsxAttribute = (name, value) => {
48
- // This handles quoted JSX attributes and html entities.
49
- return this.types.jsxAttribute(this.types.jsxIdentifier(name), this.types.jsxExpressionContainer(this.types.stringLiteral(value)));
50
- };
51
- replacePath = path => {
52
- const tokens = this.tokenizeNode(path);
53
- const messageFormat = new _icu.default();
54
- const {
55
- message: messageRaw,
56
- values,
57
- jsxElements
58
- } = messageFormat.fromTokens(tokens);
59
- const message = normalizeWhitespace(messageRaw);
60
- const {
61
- attributes,
62
- id,
63
- comment,
64
- context
65
- } = this.stripMacroAttributes(path);
66
- if (!id && !message) {
67
- return;
68
- }
69
- if (id) {
70
- attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier(_constants.ID), this.types.stringLiteral(id)));
71
- } else {
72
- attributes.push(this.createStringJsxAttribute(_constants.ID, (0, _api.generateMessageId)(message, context)));
73
- }
74
- if (!this.stripNonEssentialProps) {
75
- if (message) {
76
- attributes.push(this.createStringJsxAttribute(_constants.MESSAGE, message));
77
- }
78
- if (comment) {
79
- attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier(_constants.COMMENT), this.types.stringLiteral(comment)));
80
- }
81
- if (context) {
82
- attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier(_constants.CONTEXT), this.types.stringLiteral(context)));
83
- }
84
- }
85
-
86
- // Parameters for variable substitution
87
- const valuesObject = Object.keys(values).map(key => this.types.objectProperty(this.types.identifier(key), values[key]));
88
- if (valuesObject.length) {
89
- attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier("values"), this.types.jsxExpressionContainer(this.types.objectExpression(valuesObject))));
90
- }
91
-
92
- // Inline elements
93
- if (Object.keys(jsxElements).length) {
94
- attributes.push(this.types.jsxAttribute(this.types.jsxIdentifier("components"), this.types.jsxExpressionContainer(this.types.objectExpression(Object.keys(jsxElements).map(key => this.types.objectProperty(this.types.identifier(key), jsxElements[key]))))));
95
- }
96
- const newNode = this.types.jsxElement(this.types.jsxOpeningElement(this.types.jsxIdentifier("Trans"), attributes, true), null, [], true);
97
- newNode.loc = path.node.loc;
98
- path.replaceWith(newNode);
99
- };
100
- attrName = (names, exclude = false) => {
101
- const namesRe = new RegExp("^(" + names.join("|") + ")$");
102
- return attr => {
103
- const name = attr.name.name;
104
- return exclude ? !namesRe.test(name) : namesRe.test(name);
105
- };
106
- };
107
- stripMacroAttributes = path => {
108
- const {
109
- attributes
110
- } = path.node.openingElement;
111
- const id = attributes.find(this.attrName([_constants.ID]));
112
- const message = attributes.find(this.attrName([_constants.MESSAGE]));
113
- const comment = attributes.find(this.attrName([_constants.COMMENT]));
114
- const context = attributes.find(this.attrName([_constants.CONTEXT]));
115
- let reserved = [_constants.ID, _constants.MESSAGE, _constants.COMMENT, _constants.CONTEXT];
116
- if (this.isChoiceComponent(path)) {
117
- reserved = [...reserved, "_\\w+", "_\\d+", "zero", "one", "two", "few", "many", "other", "value", "offset"];
118
- }
119
- return {
120
- id: maybeNodeValue(id),
121
- message: maybeNodeValue(message),
122
- comment: maybeNodeValue(comment),
123
- context: maybeNodeValue(context),
124
- attributes: attributes.filter(this.attrName(reserved, true))
125
- };
126
- };
127
- tokenizeNode = path => {
128
- if (this.isTransComponent(path)) {
129
- // t
130
- return this.tokenizeTrans(path);
131
- } else if (this.isChoiceComponent(path)) {
132
- // plural, select and selectOrdinal
133
- return [this.tokenizeChoiceComponent(path)];
134
- } else if (path.isJSXElement()) {
135
- return [this.tokenizeElement(path)];
136
- } else {
137
- return [this.tokenizeExpression(path)];
138
- }
139
- };
140
- tokenizeTrans = path => {
141
- return path.get("children").flatMap(child => this.tokenizeChildren(child)).filter(Boolean);
142
- };
143
- tokenizeChildren = path => {
144
- if (path.isJSXExpressionContainer()) {
145
- const exp = path.get("expression");
146
- if (exp.isStringLiteral()) {
147
- // Escape forced newlines to keep them in message.
148
- return [this.tokenizeText(exp.node.value.replace(/\n/g, "\\n"))];
149
- }
150
- if (exp.isTemplateLiteral()) {
151
- return this.tokenizeTemplateLiteral(exp);
152
- }
153
- if (exp.isConditionalExpression()) {
154
- return [this.tokenizeConditionalExpression(exp)];
155
- }
156
- if (exp.isJSXElement()) {
157
- return this.tokenizeNode(exp);
158
- }
159
- return [this.tokenizeExpression(exp)];
160
- } else if (path.isJSXElement()) {
161
- return this.tokenizeNode(path);
162
- } else if (path.isJSXSpreadChild()) {
163
- // just do nothing
164
- } else if (path.isJSXText()) {
165
- return [this.tokenizeText(path.node.value)];
166
- } else {
167
- // impossible path
168
- // return this.tokenizeText(node.value)
169
- }
170
- };
171
- tokenizeTemplateLiteral(exp) {
172
- const expressions = exp.get("expressions");
173
- return exp.get("quasis").flatMap(({
174
- node: text
175
- }, i) => {
176
- // if it's an unicode we keep the cooked value because it's the parsed value by babel (without unicode chars)
177
- // This regex will detect if a string contains unicode chars, when they're we should interpolate them
178
- // why? because platforms like react native doesn't parse them, just doing a JSON.parse makes them UTF-8 friendly
179
- 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;
180
- let argTokens = [];
181
- const currExp = expressions[i];
182
- if (currExp) {
183
- argTokens = currExp.isCallExpression() ? this.tokenizeNode(currExp) : [this.tokenizeExpression(currExp)];
184
- }
185
- return [...(value ? [this.tokenizeText(this.clearBackslashes(value))] : []), ...argTokens];
186
- });
187
- }
188
- tokenizeChoiceComponent = path => {
189
- const element = path.get("openingElement");
190
- const name = this.getJsxTagName(path.node);
191
- const format = (this.nameMapReversed.get(name) || name).toLowerCase();
192
- const props = element.get("attributes").filter(attr => {
193
- return this.attrName([_constants.ID, _constants.COMMENT, _constants.MESSAGE, _constants.CONTEXT, "key",
194
- // we remove <Trans /> react props that are not useful for translation
195
- "render", "component", "components"], true)(attr.node);
196
- });
197
- const token = {
198
- type: "arg",
199
- format,
200
- name: null,
201
- value: undefined,
202
- options: {
203
- offset: undefined
204
- }
205
- };
206
- for (const _attr of props) {
207
- if (_attr.isJSXSpreadAttribute()) {
208
- continue;
209
- }
210
- const attr = _attr;
211
- if (this.types.isJSXNamespacedName(attr.node.name)) {
212
- continue;
213
- }
214
- const name = attr.node.name.name;
215
- const value = attr.get("value");
216
- if (name === "value") {
217
- const exp = value.isLiteral() ? value : value.get("expression");
218
- token.name = this.expressionToArgument(exp);
219
- token.value = exp.node;
220
- } else if (format !== "select" && name === "offset") {
221
- // offset is static parameter, so it must be either string or number
222
- token.options.offset = value.isStringLiteral() || value.isNumericLiteral() ? value.node.value : value.get("expression").node.value;
223
- } else {
224
- let option;
225
- if (value.isStringLiteral()) {
226
- option = value.node.extra.raw.replace(/(["'])(.*)\1/, "$2");
227
- } else {
228
- option = this.tokenizeChildren(value);
229
- }
230
- if (pluralRuleRe.test(name)) {
231
- token.options[jsx2icuExactChoice(name)] = option;
232
- } else {
233
- token.options[name] = option;
234
- }
235
- }
236
- }
237
- return token;
238
- };
239
- tokenizeElement = path => {
240
- // !!! Important: Calculate element index before traversing children.
241
- // That way outside elements are numbered before inner elements. (...and it looks pretty).
242
- const name = this.elementIndex();
243
- return {
244
- type: "element",
245
- name,
246
- value: {
247
- ...path.node,
248
- children: [],
249
- openingElement: {
250
- ...path.node.openingElement,
251
- selfClosing: true
252
- }
253
- },
254
- children: this.tokenizeTrans(path)
255
- };
256
- };
257
- tokenizeExpression = path => {
258
- return {
259
- type: "arg",
260
- name: this.expressionToArgument(path),
261
- value: path.node
262
- };
263
- };
264
- tokenizeConditionalExpression = exp => {
265
- exp.traverse({
266
- JSXElement: el => {
267
- if (this.isTransComponent(el) || this.isChoiceComponent(el)) {
268
- this.replacePath(el);
269
- el.skip();
270
- }
271
- }
272
- });
273
- return {
274
- type: "arg",
275
- name: this.expressionToArgument(exp),
276
- value: exp.node
277
- };
278
- };
279
- tokenizeText = value => {
280
- return {
281
- type: "text",
282
- value
283
- };
284
- };
285
- expressionToArgument(path) {
286
- return path.isIdentifier() ? path.node.name : String(this.expressionIndex());
287
- }
288
-
289
- /**
290
- * We clean '//\` ' to just '`'
291
- **/
292
- clearBackslashes(value) {
293
- // if not we replace the extra scaped literals
294
- return value.replace(/\\`/g, "`");
295
- }
296
- isLinguiComponent = (path, name) => {
297
- return path.isJSXElement() && this.types.isJSXIdentifier(path.node.openingElement.name, {
298
- name: this.nameMap.get(name) || name
299
- });
300
- };
301
- isTransComponent = path => {
302
- return this.isLinguiComponent(path, "Trans");
303
- };
304
- isChoiceComponent = path => {
305
- return this.isLinguiComponent(path, "Plural") || this.isLinguiComponent(path, "Select") || this.isLinguiComponent(path, "SelectOrdinal");
306
- };
307
- getJsxTagName = node => {
308
- if (this.types.isJSXIdentifier(node.openingElement.name)) {
309
- return node.openingElement.name.name;
310
- }
311
- };
312
- }
313
- exports.default = MacroJSX;
package/build/utils.js DELETED
@@ -1,8 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.makeCounter = void 0;
7
- const makeCounter = (index = 0) => () => index++;
8
- exports.makeCounter = makeCounter;