@lingui/babel-plugin-extract-messages 5.9.2 → 6.0.0-next.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.d.mts CHANGED
@@ -18,4 +18,5 @@ declare function export_default({ types: t }: {
18
18
  types: BabelTypes;
19
19
  }): PluginObj;
20
20
 
21
- export { type ExtractPluginOpts, type ExtractedMessage, type Origin, export_default as default };
21
+ export { export_default as default };
22
+ export type { ExtractPluginOpts, ExtractedMessage, Origin };
package/dist/index.mjs CHANGED
@@ -1,16 +1,15 @@
1
1
  function collectMessage(path, props, ctx) {
2
- if (props.id === void 0)
3
- return;
2
+ if (props.id === void 0) return;
4
3
  const node = path.node;
5
- const line = node.loc ? node.loc.start.line : null;
6
- const column = node.loc ? node.loc.start.column : null;
4
+ const line = node.loc ? node.loc.start.line : void 0;
5
+ const column = node.loc ? node.loc.start.column : void 0;
7
6
  ctx.opts.onMessageExtracted({
8
7
  id: props.id,
9
8
  message: props.message,
10
9
  context: props.context,
11
10
  comment: props.comment,
12
11
  placeholders: props.placeholders || {},
13
- origin: [ctx.file.opts.filename, line, column]
12
+ origin: ctx.file.opts.filename ? [ctx.file.opts.filename, line, column] : void 0
14
13
  });
15
14
  }
16
15
  function getTextFromExpression(t, exp, hub, emitErrorOnVariable = true) {
@@ -41,7 +40,7 @@ function getTextFromExpression(t, exp, hub, emitErrorOnVariable = true) {
41
40
  );
42
41
  return "";
43
42
  }
44
- return exp.quasis[0]?.value?.cooked;
43
+ return exp.quasis[0]?.value?.cooked || "";
45
44
  }
46
45
  if (emitErrorOnVariable) {
47
46
  console.warn(
@@ -52,6 +51,7 @@ function getTextFromExpression(t, exp, hub, emitErrorOnVariable = true) {
52
51
  ).message
53
52
  );
54
53
  }
54
+ return "";
55
55
  }
56
56
  function getNodeSource(fileContents, node) {
57
57
  return fileContents.slice(node.start, node.end);
@@ -102,7 +102,7 @@ function extractFromObjectExpression(t, exp, hub) {
102
102
  }
103
103
  const I18N_OBJECT = "i18n";
104
104
  function hasComment(node, comment) {
105
- return node.leadingComments && node.leadingComments.some((comm) => comm.value.trim() === comment);
105
+ return !!node.leadingComments?.some((comm) => comm.value.trim() === comment);
106
106
  }
107
107
  function hasIgnoreComment(node) {
108
108
  return hasComment(node, "lingui-extract-ignore");
@@ -130,8 +130,7 @@ function index({ types: t }) {
130
130
  // Extract translation from <Trans /> component.
131
131
  JSXElement(path, ctx) {
132
132
  const { node } = path;
133
- if (!isTransComponent(path))
134
- return;
133
+ if (!isTransComponent(path)) return;
135
134
  const attrs = node.openingElement.attributes || [];
136
135
  if (attrs.find(
137
136
  (attr) => t.isJSXSpreadAttribute(attr) && hasI18nComment(attr.argument)
@@ -233,8 +232,7 @@ function index({ types: t }) {
233
232
  },
234
233
  // Extract message descriptors
235
234
  ObjectExpression(path, ctx) {
236
- if (!hasI18nComment(path.node))
237
- return;
235
+ if (!hasI18nComment(path.node)) return;
238
236
  extractFromMessageDescriptor(path, ctx);
239
237
  }
240
238
  }
package/package.json CHANGED
@@ -1,10 +1,8 @@
1
1
  {
2
2
  "name": "@lingui/babel-plugin-extract-messages",
3
- "version": "5.9.2",
3
+ "version": "6.0.0-next.0",
4
4
  "description": "Babel plugin for collecting messages from source code for internationalization",
5
- "main": "./dist/index.cjs",
6
- "module": "./dist/index.mjs",
7
- "types": "./dist/index.d.ts",
5
+ "type": "module",
8
6
  "author": {
9
7
  "name": "Tomáš Ehrlich",
10
8
  "email": "tomas.ehrlich@gmail.com"
@@ -21,14 +19,17 @@
21
19
  "multilingual"
22
20
  ],
23
21
  "scripts": {
24
- "build": "rimraf ./dist && unbuild",
25
- "stub": "unbuild --stub"
22
+ "build": "unbuild",
23
+ "check-types": "tsc --noEmit"
26
24
  },
27
25
  "files": [
28
26
  "LICENSE",
29
27
  "README.md",
30
28
  "dist/"
31
29
  ],
30
+ "exports": {
31
+ ".": "./dist/index.mjs"
32
+ },
32
33
  "homepage": "https://lingui.dev",
33
34
  "repository": {
34
35
  "type": "git",
@@ -39,15 +40,19 @@
39
40
  "url": "https://github.com/lingui/js-lingui/issues"
40
41
  },
41
42
  "engines": {
42
- "node": ">=20.0.0"
43
+ "node": ">=22.19.0"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@babel/core": "^7.21.0",
46
47
  "@babel/traverse": "^7.20.12",
47
48
  "@babel/types": "^7.20.7",
48
- "@lingui/babel-plugin-lingui-macro": "5.9.2",
49
- "@lingui/jest-mocks": "3.0.3",
50
- "unbuild": "2.0.0"
49
+ "@lingui/babel-plugin-lingui-macro": "6.0.0-next.0",
50
+ "@lingui/test-utils": "3.0.3",
51
+ "unbuild": "3.6.1",
52
+ "vitest": "4.0.18"
53
+ },
54
+ "unbuild": {
55
+ "declaration": "node16"
51
56
  },
52
- "gitHead": "7b30f31b5510c98442eabbcef531a6b70e1c1381"
57
+ "gitHead": "a9576050487a4f7dfbc88db20814d5a1bb861c8c"
53
58
  }
package/dist/index.cjs DELETED
@@ -1,246 +0,0 @@
1
- 'use strict';
2
-
3
- function collectMessage(path, props, ctx) {
4
- if (props.id === void 0)
5
- return;
6
- const node = path.node;
7
- const line = node.loc ? node.loc.start.line : null;
8
- const column = node.loc ? node.loc.start.column : null;
9
- ctx.opts.onMessageExtracted({
10
- id: props.id,
11
- message: props.message,
12
- context: props.context,
13
- comment: props.comment,
14
- placeholders: props.placeholders || {},
15
- origin: [ctx.file.opts.filename, line, column]
16
- });
17
- }
18
- function getTextFromExpression(t, exp, hub, emitErrorOnVariable = true) {
19
- if (t.isStringLiteral(exp)) {
20
- return exp.value;
21
- }
22
- if (t.isBinaryExpression(exp)) {
23
- return getTextFromExpression(
24
- t,
25
- exp.left,
26
- hub,
27
- emitErrorOnVariable
28
- ) + getTextFromExpression(
29
- t,
30
- exp.right,
31
- hub,
32
- emitErrorOnVariable
33
- );
34
- }
35
- if (t.isTemplateLiteral(exp)) {
36
- if (exp?.quasis.length > 1) {
37
- console.warn(
38
- hub.buildError(
39
- exp,
40
- "Could not extract from template literal with expressions.",
41
- SyntaxError
42
- ).message
43
- );
44
- return "";
45
- }
46
- return exp.quasis[0]?.value?.cooked;
47
- }
48
- if (emitErrorOnVariable) {
49
- console.warn(
50
- hub.buildError(
51
- exp,
52
- "Only strings or template literals could be extracted.",
53
- SyntaxError
54
- ).message
55
- );
56
- }
57
- }
58
- function getNodeSource(fileContents, node) {
59
- return fileContents.slice(node.start, node.end);
60
- }
61
- function valuesObjectExpressionToPlaceholdersRecord(t, exp, hub) {
62
- const props = {};
63
- exp.properties.forEach(({ key, value }, i) => {
64
- let name;
65
- if (t.isStringLiteral(key) || t.isNumericLiteral(key)) {
66
- name = key.value.toString();
67
- } else if (t.isIdentifier(key)) {
68
- name = key.name;
69
- } else {
70
- console.warn(
71
- hub.buildError(
72
- exp,
73
- `Could not extract values to placeholders. The key #${i} has unsupported syntax`,
74
- SyntaxError
75
- ).message
76
- );
77
- }
78
- if (name) {
79
- props[name] = getNodeSource(hub.getCode(), value);
80
- }
81
- });
82
- return props;
83
- }
84
- function extractFromObjectExpression(t, exp, hub) {
85
- const props = {};
86
- const textKeys = ["id", "message", "comment", "context"];
87
- exp.properties.forEach(({ key, value }, i) => {
88
- const name = key.name;
89
- if (name === "values" && t.isObjectExpression(value)) {
90
- props.placeholders = valuesObjectExpressionToPlaceholdersRecord(
91
- t,
92
- value,
93
- hub
94
- );
95
- } else if (textKeys.includes(name)) {
96
- props[name] = getTextFromExpression(
97
- t,
98
- value,
99
- hub
100
- );
101
- }
102
- });
103
- return props;
104
- }
105
- const I18N_OBJECT = "i18n";
106
- function hasComment(node, comment) {
107
- return node.leadingComments && node.leadingComments.some((comm) => comm.value.trim() === comment);
108
- }
109
- function hasIgnoreComment(node) {
110
- return hasComment(node, "lingui-extract-ignore");
111
- }
112
- function hasI18nComment(node) {
113
- return hasComment(node, "i18n");
114
- }
115
- function index({ types: t }) {
116
- function isTransComponent(path) {
117
- return path.isJSXElement() && path.get("openingElement").get("name").referencesImport("@lingui/react", "Trans");
118
- }
119
- const isI18nMethod = (node) => t.isMemberExpression(node) && (t.isIdentifier(node.object, { name: I18N_OBJECT }) || t.isMemberExpression(node.object) && t.isIdentifier(node.object.property, { name: I18N_OBJECT })) && (t.isIdentifier(node.property, { name: "_" }) || t.isIdentifier(node.property, { name: "t" }));
120
- const extractFromMessageDescriptor = (path, ctx) => {
121
- const props = extractFromObjectExpression(t, path.node, ctx.file.hub);
122
- if (!props.id) {
123
- console.warn(
124
- path.buildCodeFrameError("Missing message ID, skipping.").message
125
- );
126
- return;
127
- }
128
- collectMessage(path, props, ctx);
129
- };
130
- return {
131
- visitor: {
132
- // Extract translation from <Trans /> component.
133
- JSXElement(path, ctx) {
134
- const { node } = path;
135
- if (!isTransComponent(path))
136
- return;
137
- const attrs = node.openingElement.attributes || [];
138
- if (attrs.find(
139
- (attr) => t.isJSXSpreadAttribute(attr) && hasI18nComment(attr.argument)
140
- )) {
141
- return;
142
- }
143
- const props = attrs.reduce((acc, item) => {
144
- if (t.isJSXSpreadAttribute(item)) {
145
- return acc;
146
- }
147
- const key = item.name.name;
148
- if (key === "id" || key === "message" || key === "comment" || key === "context") {
149
- if (t.isStringLiteral(item.value)) {
150
- acc[key] = item.value.value;
151
- } else if (t.isJSXExpressionContainer(item.value) && t.isStringLiteral(item.value.expression)) {
152
- acc[key] = item.value.expression.value;
153
- }
154
- }
155
- if (key === "values" && t.isJSXExpressionContainer(item.value) && t.isObjectExpression(item.value.expression)) {
156
- acc.placeholders = valuesObjectExpressionToPlaceholdersRecord(
157
- t,
158
- item.value.expression,
159
- ctx.file.hub
160
- );
161
- }
162
- return acc;
163
- }, {});
164
- if (!props.id) {
165
- const idProp = attrs.filter(
166
- (item) => t.isJSXAttribute(item) && item.name.name === "id"
167
- )[0];
168
- if (idProp === void 0 || t.isLiteral(props.id)) {
169
- console.warn(
170
- path.buildCodeFrameError("Missing message ID, skipping.").message
171
- );
172
- }
173
- return;
174
- }
175
- collectMessage(path, props, ctx);
176
- },
177
- CallExpression(path, ctx) {
178
- if ([path.node, path.parent].some((node) => hasIgnoreComment(node))) {
179
- return;
180
- }
181
- const firstArgument = path.get("arguments")[0];
182
- if (!isI18nMethod(path.node.callee)) {
183
- return;
184
- }
185
- if (hasI18nComment(firstArgument.node)) {
186
- return;
187
- }
188
- if (firstArgument.isObjectExpression()) {
189
- extractFromMessageDescriptor(firstArgument, ctx);
190
- return;
191
- } else {
192
- let props = {
193
- id: getTextFromExpression(
194
- t,
195
- firstArgument.node,
196
- ctx.file.hub,
197
- false
198
- )
199
- };
200
- if (!props.id) {
201
- return;
202
- }
203
- const secondArgument = path.node.arguments[1];
204
- if (secondArgument && t.isObjectExpression(secondArgument)) {
205
- props.placeholders = valuesObjectExpressionToPlaceholdersRecord(
206
- t,
207
- secondArgument,
208
- ctx.file.hub
209
- );
210
- }
211
- const msgDescArg = path.node.arguments[2];
212
- if (t.isObjectExpression(msgDescArg)) {
213
- props = {
214
- ...props,
215
- ...extractFromObjectExpression(t, msgDescArg, ctx.file.hub)
216
- };
217
- }
218
- collectMessage(path, props, ctx);
219
- }
220
- },
221
- StringLiteral(path, ctx) {
222
- if (!hasI18nComment(path.node)) {
223
- return;
224
- }
225
- const props = {
226
- id: path.node.value
227
- };
228
- if (!props.id) {
229
- console.warn(
230
- path.buildCodeFrameError("Empty StringLiteral, skipping.").message
231
- );
232
- return;
233
- }
234
- collectMessage(path, props, ctx);
235
- },
236
- // Extract message descriptors
237
- ObjectExpression(path, ctx) {
238
- if (!hasI18nComment(path.node))
239
- return;
240
- extractFromMessageDescriptor(path, ctx);
241
- }
242
- }
243
- };
244
- }
245
-
246
- module.exports = index;
package/dist/index.d.cts DELETED
@@ -1,21 +0,0 @@
1
- import * as BabelTypesNamespace from '@babel/types';
2
- import { PluginObj } from '@babel/core';
3
-
4
- type BabelTypes = typeof BabelTypesNamespace;
5
- type ExtractedMessage = {
6
- id: string;
7
- message?: string;
8
- context?: string;
9
- origin?: Origin;
10
- comment?: string;
11
- placeholders?: Record<string, string>;
12
- };
13
- type ExtractPluginOpts = {
14
- onMessageExtracted(msg: ExtractedMessage): void;
15
- };
16
- type Origin = [filename: string, line: number, column?: number];
17
- declare function export_default({ types: t }: {
18
- types: BabelTypes;
19
- }): PluginObj;
20
-
21
- export { type ExtractPluginOpts, type ExtractedMessage, type Origin, export_default as default };
package/dist/index.d.ts DELETED
@@ -1,21 +0,0 @@
1
- import * as BabelTypesNamespace from '@babel/types';
2
- import { PluginObj } from '@babel/core';
3
-
4
- type BabelTypes = typeof BabelTypesNamespace;
5
- type ExtractedMessage = {
6
- id: string;
7
- message?: string;
8
- context?: string;
9
- origin?: Origin;
10
- comment?: string;
11
- placeholders?: Record<string, string>;
12
- };
13
- type ExtractPluginOpts = {
14
- onMessageExtracted(msg: ExtractedMessage): void;
15
- };
16
- type Origin = [filename: string, line: number, column?: number];
17
- declare function export_default({ types: t }: {
18
- types: BabelTypes;
19
- }): PluginObj;
20
-
21
- export { type ExtractPluginOpts, type ExtractedMessage, type Origin, export_default as default };