experimental-ciao-babel 1.1.10 → 1.1.11

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 CHANGED
@@ -6,14 +6,29 @@ function formatLocation(state, loc) {
6
6
  if (loc) return `${filename}:${loc.line}:${loc.column}`;
7
7
  return filename;
8
8
  }
9
- function extractTransTemplate(children) {
9
+ function getFilename(state) {
10
+ return state.filename || state.file?.opts?.filename || "unknown";
11
+ }
12
+ function isCTContextBlock(name) {
13
+ if (name.type === "JSXIdentifier") return name.name === "CTContextBlock";
14
+ if (name.type === "JSXMemberExpression") return name.property.type === "JSXIdentifier" && name.property.name === "CTContextBlock";
15
+ return false;
16
+ }
17
+ function isTrans(name) {
18
+ if (name.type === "JSXIdentifier") return name.name === "Trans";
19
+ if (name.type === "JSXMemberExpression") return name.property.type === "JSXIdentifier" && name.property.name === "Trans";
20
+ return false;
21
+ }
22
+ function extractTransTemplate(children, expressionCounter) {
10
23
  let elementIndex = 0;
24
+ const exprCounter = expressionCounter || { current: 0 };
11
25
  function processNode(node) {
12
26
  if (node.type === "JSXText") return node.value.replace(/\s+/g, " ");
13
27
  if (node.type === "JSXExpressionContainer") {
14
28
  const expr = node.expression;
15
29
  if (expr.type === "StringLiteral") return expr.value;
16
- return "";
30
+ if (expr.type === "JSXEmptyExpression") return "";
31
+ return `{${exprCounter.current++}}`;
17
32
  }
18
33
  if (node.type === "JSXElement") {
19
34
  const elem = node;
@@ -31,7 +46,7 @@ function getContextBlockIdForJSX(path) {
31
46
  if (current.isJSXElement()) {
32
47
  const openingElement = current.node.openingElement;
33
48
  const name = openingElement.name;
34
- if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
49
+ if (isCTContextBlock(name)) {
35
50
  for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id" && attr.value?.type === "StringLiteral") return attr.value.value;
36
51
  }
37
52
  }
@@ -45,7 +60,7 @@ function getContextBlockId(path) {
45
60
  if (current.isJSXElement()) {
46
61
  const openingElement = current.node.openingElement;
47
62
  const name = openingElement.name;
48
- if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
63
+ if (isCTContextBlock(name)) {
49
64
  for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id" && attr.value?.type === "StringLiteral") return attr.value.value;
50
65
  }
51
66
  }
@@ -60,6 +75,11 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
60
75
  const id = path.node.id;
61
76
  if (init && init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "useCt") {
62
77
  if (id.type === "Identifier") ctVariableNames.add(id.name);
78
+ else if (id.type === "ObjectPattern") {
79
+ for (const prop of id.properties) if (prop.type === "ObjectProperty") {
80
+ if (prop.value.type === "Identifier") ctVariableNames.add(prop.value.name);
81
+ } else if (prop.type === "RestElement" && prop.argument.type === "Identifier") ctVariableNames.add(prop.argument.name);
82
+ }
63
83
  }
64
84
  },
65
85
  CallExpression(path, state) {
@@ -67,7 +87,7 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
67
87
  if (callee.type === "Identifier" && ctVariableNames.has(callee.name)) {
68
88
  const loc = path.node.loc;
69
89
  if (loc) {
70
- const locationKey = `${loc.start.line}:${loc.start.column}`;
90
+ const locationKey = `${getFilename(state)}:${loc.start.line}:${loc.start.column}`;
71
91
  if (processedLocations.has(locationKey)) return;
72
92
  processedLocations.add(locationKey);
73
93
  }
@@ -100,13 +120,13 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
100
120
  const openingElement = path.node.openingElement;
101
121
  const name = openingElement.name;
102
122
  const loc = path.node.loc;
103
- if (name.type === "JSXIdentifier" && name.name === "Trans") {
123
+ if (isTrans(name)) {
104
124
  if (loc) {
105
- const locationKey = `jsx:${loc.start.line}:${loc.start.column}`;
125
+ const locationKey = `${getFilename(state)}:jsx:${loc.start.line}:${loc.start.column}`;
106
126
  if (processedLocations.has(locationKey)) return;
107
127
  processedLocations.add(locationKey);
108
128
  }
109
- const template = extractTransTemplate(path.node.children);
129
+ const template = extractTransTemplate(path.node.children, { current: 0 });
110
130
  if (!template) return;
111
131
  let context = null;
112
132
  for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "context") {
@@ -122,7 +142,7 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
122
142
  collectedStrings.push(entry);
123
143
  }
124
144
  }
125
- if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
145
+ if (isCTContextBlock(name)) {
126
146
  for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id") {
127
147
  if (attr.value && attr.value.type === "StringLiteral") {
128
148
  const id = attr.value.value;
@@ -134,6 +154,92 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
134
154
  }
135
155
  };
136
156
  }
157
+ function createExtractionVisitorWithState() {
158
+ return {
159
+ VariableDeclarator(path, state) {
160
+ const init = path.node.init;
161
+ const id = path.node.id;
162
+ if (init && init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "useCt") {
163
+ if (id.type === "Identifier") state.ctVariableNames.add(id.name);
164
+ else if (id.type === "ObjectPattern") {
165
+ for (const prop of id.properties) if (prop.type === "ObjectProperty") {
166
+ if (prop.value.type === "Identifier") state.ctVariableNames.add(prop.value.name);
167
+ } else if (prop.type === "RestElement" && prop.argument.type === "Identifier") state.ctVariableNames.add(prop.argument.name);
168
+ }
169
+ }
170
+ },
171
+ CallExpression(path, state) {
172
+ const callee = path.node.callee;
173
+ if (callee.type === "Identifier" && state.ctVariableNames.has(callee.name)) {
174
+ const loc = path.node.loc;
175
+ if (loc) {
176
+ const locationKey = `${getFilename(state)}:${loc.start.line}:${loc.start.column}`;
177
+ if (state.processedLocations.has(locationKey)) return;
178
+ state.processedLocations.add(locationKey);
179
+ }
180
+ const args = path.node.arguments;
181
+ if (args.length === 0) {
182
+ console.warn(`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`);
183
+ return;
184
+ }
185
+ const textArg = args[0];
186
+ if (textArg.type !== "StringLiteral") {
187
+ console.warn(`[ciao-tools] Warning: ${callee.name}() called with non-string literal at ${formatLocation(state, loc?.start)}. Only string literals are supported. Skipping dynamic string.`);
188
+ return;
189
+ }
190
+ const text = textArg.value;
191
+ let context = null;
192
+ if (args.length >= 2) {
193
+ const contextArg = args[1];
194
+ if (contextArg.type === "StringLiteral") context = contextArg.value;
195
+ }
196
+ const parentContextBlockId = getContextBlockId(path);
197
+ if (!state.collectedStrings.some((s) => s.text === text && s.context === (context ?? void 0) && s.parentContextBlockId === (parentContextBlockId ?? void 0))) {
198
+ const entry = { text };
199
+ if (context) entry.context = context;
200
+ if (parentContextBlockId) entry.parentContextBlockId = parentContextBlockId;
201
+ state.collectedStrings.push(entry);
202
+ }
203
+ }
204
+ },
205
+ JSXElement(path, state) {
206
+ const openingElement = path.node.openingElement;
207
+ const name = openingElement.name;
208
+ const loc = path.node.loc;
209
+ if (isTrans(name)) {
210
+ if (loc) {
211
+ const locationKey = `${getFilename(state)}:jsx:${loc.start.line}:${loc.start.column}`;
212
+ if (state.processedLocations.has(locationKey)) return;
213
+ state.processedLocations.add(locationKey);
214
+ }
215
+ const template = extractTransTemplate(path.node.children, { current: 0 });
216
+ if (!template) return;
217
+ let context = null;
218
+ for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "context") {
219
+ if (attr.value?.type === "StringLiteral") context = attr.value.value;
220
+ else if (attr.value?.type === "JSXExpressionContainer" && attr.value.expression.type === "StringLiteral") context = attr.value.expression.value;
221
+ break;
222
+ }
223
+ const parentContextBlockId = getContextBlockIdForJSX(path);
224
+ if (!state.collectedStrings.some((s) => s.text === template && s.context === (context ?? void 0) && s.parentContextBlockId === (parentContextBlockId ?? void 0))) {
225
+ const entry = { text: template };
226
+ if (context) entry.context = context;
227
+ if (parentContextBlockId) entry.parentContextBlockId = parentContextBlockId;
228
+ state.collectedStrings.push(entry);
229
+ }
230
+ }
231
+ if (isCTContextBlock(name)) {
232
+ for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id") {
233
+ if (attr.value && attr.value.type === "StringLiteral") {
234
+ const id = attr.value.value;
235
+ if (!state.collectedContextBlocks.some((b) => b.id === id)) state.collectedContextBlocks.push({ id });
236
+ } else console.warn(`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`);
237
+ break;
238
+ }
239
+ }
240
+ }
241
+ };
242
+ }
137
243
  function createExtractionPlugin(options = {}) {
138
244
  const { onComplete } = options;
139
245
  const collectedStrings = [];
@@ -157,7 +263,13 @@ function createExtractionPlugin(options = {}) {
157
263
  function ciaoToolsBabelPlugin() {
158
264
  return {
159
265
  name: "@ciao-tools/babel",
160
- visitor: createExtractionVisitor([], [], /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set())
266
+ pre() {
267
+ this.collectedStrings = [];
268
+ this.collectedContextBlocks = [];
269
+ this.ctVariableNames = /* @__PURE__ */ new Set();
270
+ this.processedLocations = /* @__PURE__ */ new Set();
271
+ },
272
+ visitor: createExtractionVisitorWithState()
161
273
  };
162
274
  }
163
275
  function buildSchema(result) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["current: NodePath | null","context: string | null","entry: TranslatableString","collectedStrings: TranslatableString[]","collectedContextBlocks: ContextBlock[]"],"sources":["../src/visitor.ts","../src/index.ts"],"sourcesContent":["import type { NodePath, PluginObj, PluginPass } from \"@babel/core\";\nimport type {\n\tCallExpression,\n\tJSXElement,\n\tJSXText,\n\tJSXExpressionContainer,\n\tJSXFragment,\n\tVariableDeclarator,\n\tNode,\n} from \"@babel/types\";\nimport type {\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n} from \"./types\";\n\nfunction formatLocation(\n\tstate: PluginPass,\n\tloc: { line: number; column: number } | null | undefined,\n): string {\n\tconst filename = state.filename || state.file?.opts?.filename || \"unknown\";\n\tif (loc) {\n\t\treturn `${filename}:${loc.line}:${loc.column}`;\n\t}\n\treturn filename;\n}\n\nfunction extractTransTemplate(children: Node[]): string {\n\tlet elementIndex = 0;\n\n\tfunction processNode(node: Node): string {\n\t\tif (node.type === \"JSXText\") {\n\t\t\treturn (node as JSXText).value.replace(/\\s+/g, \" \");\n\t\t}\n\n\t\tif (node.type === \"JSXExpressionContainer\") {\n\t\t\tconst expr = (node as JSXExpressionContainer).expression;\n\t\t\tif (expr.type === \"StringLiteral\") {\n\t\t\t\treturn expr.value;\n\t\t\t}\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (node.type === \"JSXElement\") {\n\t\t\tconst elem = node as JSXElement;\n\t\t\tconst idx = elementIndex++;\n\t\t\tconst innerContent = elem.children.map(processNode).join(\"\");\n\t\t\treturn `<${idx}>${innerContent}</${idx}>`;\n\t\t}\n\n\t\tif (node.type === \"JSXFragment\") {\n\t\t\tconst frag = node as JSXFragment;\n\t\t\treturn frag.children.map(processNode).join(\"\");\n\t\t}\n\n\t\treturn \"\";\n\t}\n\n\treturn children.map(processNode).join(\"\").trim();\n}\n\nfunction getContextBlockIdForJSX(path: NodePath<JSXElement>): string | null {\n\tlet current: NodePath | null = path.parentPath;\n\n\twhile (current) {\n\t\tif (current.isJSXElement()) {\n\t\t\tconst openingElement = current.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\n\t\t\tif (name.type === \"JSXIdentifier\" && name.name === \"CTContextBlock\") {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\" &&\n\t\t\t\t\t\tattr.value?.type === \"StringLiteral\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn attr.value.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentPath;\n\t}\n\n\treturn null;\n}\n\nfunction getContextBlockId(path: NodePath<CallExpression>): string | null {\n\tlet current: NodePath | null = path.parentPath;\n\n\twhile (current) {\n\t\tif (current.isJSXElement()) {\n\t\t\tconst openingElement = current.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\n\t\t\tif (name.type === \"JSXIdentifier\" && name.name === \"CTContextBlock\") {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\" &&\n\t\t\t\t\t\tattr.value?.type === \"StringLiteral\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn attr.value.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentPath;\n\t}\n\n\treturn null;\n}\n\nexport function createExtractionVisitor(\n\tcollectedStrings: TranslatableString[],\n\tcollectedContextBlocks: ContextBlock[],\n\tctVariableNames: Set<string>,\n\tprocessedLocations: Set<string>,\n): PluginObj[\"visitor\"] {\n\treturn {\n\t\tVariableDeclarator(path: NodePath<VariableDeclarator>) {\n\t\t\tconst init = path.node.init;\n\t\t\tconst id = path.node.id;\n\n\t\t\tif (\n\t\t\t\tinit &&\n\t\t\t\tinit.type === \"CallExpression\" &&\n\t\t\t\tinit.callee.type === \"Identifier\" &&\n\t\t\t\tinit.callee.name === \"useCt\"\n\t\t\t) {\n\t\t\t\tif (id.type === \"Identifier\") {\n\t\t\t\t\tctVariableNames.add(id.name);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tCallExpression(path: NodePath<CallExpression>, state: PluginPass) {\n\t\t\tconst callee = path.node.callee;\n\n\t\t\tif (callee.type === \"Identifier\" && ctVariableNames.has(callee.name)) {\n\t\t\t\tconst loc = path.node.loc;\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst locationKey = `${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst args = path.node.arguments;\n\n\t\t\t\tif (args.length === 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst textArg = args[0];\n\n\t\t\t\tif (textArg.type !== \"StringLiteral\") {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with non-string literal at ${formatLocation(state, loc?.start)}. Only string literals are supported. Skipping dynamic string.`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst text = textArg.value;\n\t\t\t\tlet context: string | null = null;\n\n\t\t\t\tif (args.length >= 2) {\n\t\t\t\t\tconst contextArg = args[1];\n\t\t\t\t\tif (contextArg.type === \"StringLiteral\") {\n\t\t\t\t\t\tcontext = contextArg.value;\n\t\t\t\t\t}\n\t\t\t\t\t// Note: ObjectExpression is valid (interpolation values), so we don't warn about it\n\t\t\t\t\t// Only warn for dynamic context strings (identifiers, member expressions, etc.)\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockId(path);\n\n\t\t\t\tconst isDuplicate = collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === text &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tcollectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tJSXElement(path: NodePath<JSXElement>, state: PluginPass) {\n\t\t\tconst openingElement = path.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\t\t\tconst loc = path.node.loc;\n\n\t\t\tif (name.type === \"JSXIdentifier\" && name.name === \"Trans\") {\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst locationKey = `jsx:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst template = extractTransTemplate(path.node.children);\n\t\t\t\tif (!template) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Extract context prop from Trans component\n\t\t\t\tlet context: string | null = null;\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"context\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value?.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tcontext = attr.value.value;\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tattr.value?.type === \"JSXExpressionContainer\" &&\n\t\t\t\t\t\t\tattr.value.expression.type === \"StringLiteral\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcontext = attr.value.expression.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockIdForJSX(path);\n\n\t\t\t\tconst isDuplicate = collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === template &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text: template };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tcollectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (name.type === \"JSXIdentifier\" && name.name === \"CTContextBlock\") {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value && attr.value.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tconst id = attr.value.value;\n\t\t\t\t\t\t\tconst isDuplicate = collectedContextBlocks.some(\n\t\t\t\t\t\t\t\t(b) => b.id === id,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\t\t\t\tcollectedContextBlocks.push({ id });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createExtractionPlugin(\n\toptions: ExtractionPluginOptions = {},\n): () => PluginObj {\n\tconst { onComplete } = options;\n\tconst collectedStrings: TranslatableString[] = [];\n\tconst collectedContextBlocks: ContextBlock[] = [];\n\tconst ctVariableNames = new Set<string>();\n\tconst processedLocations = new Set<string>();\n\n\treturn (): PluginObj => ({\n\t\tname: \"@ciao-tools/babel-extraction\",\n\t\tvisitor: createExtractionVisitor(\n\t\t\tcollectedStrings,\n\t\t\tcollectedContextBlocks,\n\t\t\tctVariableNames,\n\t\t\tprocessedLocations,\n\t\t),\n\t\tpost() {\n\t\t\tif (onComplete) {\n\t\t\t\tconst result: ExtractionResult = {\n\t\t\t\t\tstrings: [...collectedStrings],\n\t\t\t\t\tcontextBlocks: [...collectedContextBlocks],\n\t\t\t\t};\n\t\t\t\tonComplete(result);\n\t\t\t}\n\t\t},\n\t});\n}\n\nexport function getCollectedData(\n\tcollectedStrings: TranslatableString[],\n\tcollectedContextBlocks: ContextBlock[],\n): ExtractionResult {\n\treturn {\n\t\tstrings: [...collectedStrings],\n\t\tcontextBlocks: [...collectedContextBlocks],\n\t};\n}\n","import type { PluginObj } from \"@babel/core\";\nimport type {\n\tBuildSchema,\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n} from \"./types\";\nimport { createExtractionVisitor } from \"./visitor\";\n\nexport type {\n\tBuildSchema,\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n};\nexport { createExtractionPlugin } from \"./visitor\";\n\nexport default function ciaoToolsBabelPlugin(): PluginObj {\n\tconst collectedStrings: TranslatableString[] = [];\n\tconst collectedContextBlocks: ContextBlock[] = [];\n\tconst ctVariableNames = new Set<string>();\n\tconst processedLocations = new Set<string>();\n\n\treturn {\n\t\tname: \"@ciao-tools/babel\",\n\t\tvisitor: createExtractionVisitor(\n\t\t\tcollectedStrings,\n\t\t\tcollectedContextBlocks,\n\t\t\tctVariableNames,\n\t\t\tprocessedLocations,\n\t\t),\n\t};\n}\n\nexport function buildSchema(result: ExtractionResult): BuildSchema {\n\treturn {\n\t\tversion: \"1.0\",\n\t\tstrings: result.strings,\n\t\tcontextBlocks: result.contextBlocks,\n\t\tmetadata: {\n\t\t\tgeneratedAt: new Date().toISOString(),\n\t\t\ttotalStrings: result.strings.length,\n\t\t\ttotalContextBlocks: result.contextBlocks.length,\n\t\t},\n\t};\n}\n"],"mappings":";;;AAiBA,SAAS,eACR,OACA,KACS;CACT,MAAM,WAAW,MAAM,YAAY,MAAM,MAAM,MAAM,YAAY;AACjE,KAAI,IACH,QAAO,GAAG,SAAS,GAAG,IAAI,KAAK,GAAG,IAAI;AAEvC,QAAO;;AAGR,SAAS,qBAAqB,UAA0B;CACvD,IAAI,eAAe;CAEnB,SAAS,YAAY,MAAoB;AACxC,MAAI,KAAK,SAAS,UACjB,QAAQ,KAAiB,MAAM,QAAQ,QAAQ,IAAI;AAGpD,MAAI,KAAK,SAAS,0BAA0B;GAC3C,MAAM,OAAQ,KAAgC;AAC9C,OAAI,KAAK,SAAS,gBACjB,QAAO,KAAK;AAEb,UAAO;;AAGR,MAAI,KAAK,SAAS,cAAc;GAC/B,MAAM,OAAO;GACb,MAAM,MAAM;AAEZ,UAAO,IAAI,IAAI,GADM,KAAK,SAAS,IAAI,YAAY,CAAC,KAAK,GAAG,CAC7B,IAAI,IAAI;;AAGxC,MAAI,KAAK,SAAS,cAEjB,QADa,KACD,SAAS,IAAI,YAAY,CAAC,KAAK,GAAG;AAG/C,SAAO;;AAGR,QAAO,SAAS,IAAI,YAAY,CAAC,KAAK,GAAG,CAAC,MAAM;;AAGjD,SAAS,wBAAwB,MAA2C;CAC3E,IAAIA,UAA2B,KAAK;AAEpC,QAAO,SAAS;AACf,MAAI,QAAQ,cAAc,EAAE;GAC3B,MAAM,iBAAiB,QAAQ,KAAK;GACpC,MAAM,OAAO,eAAe;AAE5B,OAAI,KAAK,SAAS,mBAAmB,KAAK,SAAS,kBAClD;SAAK,MAAM,QAAQ,eAAe,WACjC,KACC,KAAK,SAAS,kBACd,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,QACnB,KAAK,OAAO,SAAS,gBAErB,QAAO,KAAK,MAAM;;;AAKtB,YAAU,QAAQ;;AAGnB,QAAO;;AAGR,SAAS,kBAAkB,MAA+C;CACzE,IAAIA,UAA2B,KAAK;AAEpC,QAAO,SAAS;AACf,MAAI,QAAQ,cAAc,EAAE;GAC3B,MAAM,iBAAiB,QAAQ,KAAK;GACpC,MAAM,OAAO,eAAe;AAE5B,OAAI,KAAK,SAAS,mBAAmB,KAAK,SAAS,kBAClD;SAAK,MAAM,QAAQ,eAAe,WACjC,KACC,KAAK,SAAS,kBACd,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,QACnB,KAAK,OAAO,SAAS,gBAErB,QAAO,KAAK,MAAM;;;AAKtB,YAAU,QAAQ;;AAGnB,QAAO;;AAGR,SAAgB,wBACf,kBACA,wBACA,iBACA,oBACuB;AACvB,QAAO;EACN,mBAAmB,MAAoC;GACtD,MAAM,OAAO,KAAK,KAAK;GACvB,MAAM,KAAK,KAAK,KAAK;AAErB,OACC,QACA,KAAK,SAAS,oBACd,KAAK,OAAO,SAAS,gBACrB,KAAK,OAAO,SAAS,SAErB;QAAI,GAAG,SAAS,aACf,iBAAgB,IAAI,GAAG,KAAK;;;EAK/B,eAAe,MAAgC,OAAmB;GACjE,MAAM,SAAS,KAAK,KAAK;AAEzB,OAAI,OAAO,SAAS,gBAAgB,gBAAgB,IAAI,OAAO,KAAK,EAAE;IACrE,MAAM,MAAM,KAAK,KAAK;AACtB,QAAI,KAAK;KACR,MAAM,cAAc,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM;AACnD,SAAI,mBAAmB,IAAI,YAAY,CACtC;AAED,wBAAmB,IAAI,YAAY;;IAGpC,MAAM,OAAO,KAAK,KAAK;AAEvB,QAAI,KAAK,WAAW,GAAG;AACtB,aAAQ,KACP,yBAAyB,OAAO,KAAK,iCAAiC,eAAe,OAAO,KAAK,MAAM,GACvG;AACD;;IAGD,MAAM,UAAU,KAAK;AAErB,QAAI,QAAQ,SAAS,iBAAiB;AACrC,aAAQ,KACP,yBAAyB,OAAO,KAAK,uCAAuC,eAAe,OAAO,KAAK,MAAM,CAAC,gEAC9G;AACD;;IAGD,MAAM,OAAO,QAAQ;IACrB,IAAIC,UAAyB;AAE7B,QAAI,KAAK,UAAU,GAAG;KACrB,MAAM,aAAa,KAAK;AACxB,SAAI,WAAW,SAAS,gBACvB,WAAU,WAAW;;IAMvB,MAAM,uBAAuB,kBAAkB,KAAK;AAQpD,QAAI,CANgB,iBAAiB,MACnC,MACA,EAAE,SAAS,QACX,EAAE,aAAa,WAAW,WAC1B,EAAE,0BAA0B,wBAAwB,QACrD,EACiB;KACjB,MAAMC,QAA4B,EAAE,MAAM;AAC1C,SAAI,QACH,OAAM,UAAU;AAEjB,SAAI,qBACH,OAAM,uBAAuB;AAE9B,sBAAiB,KAAK,MAAM;;;;EAK/B,WAAW,MAA4B,OAAmB;GACzD,MAAM,iBAAiB,KAAK,KAAK;GACjC,MAAM,OAAO,eAAe;GAC5B,MAAM,MAAM,KAAK,KAAK;AAEtB,OAAI,KAAK,SAAS,mBAAmB,KAAK,SAAS,SAAS;AAC3D,QAAI,KAAK;KACR,MAAM,cAAc,OAAO,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM;AACvD,SAAI,mBAAmB,IAAI,YAAY,CACtC;AAED,wBAAmB,IAAI,YAAY;;IAGpC,MAAM,WAAW,qBAAqB,KAAK,KAAK,SAAS;AACzD,QAAI,CAAC,SACJ;IAID,IAAID,UAAyB;AAC7B,SAAK,MAAM,QAAQ,eAAe,WACjC,KACC,KAAK,SAAS,kBACd,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,WAClB;AACD,SAAI,KAAK,OAAO,SAAS,gBACxB,WAAU,KAAK,MAAM;cAErB,KAAK,OAAO,SAAS,4BACrB,KAAK,MAAM,WAAW,SAAS,gBAE/B,WAAU,KAAK,MAAM,WAAW;AAEjC;;IAIF,MAAM,uBAAuB,wBAAwB,KAAK;AAS1D,QAAI,CAPgB,iBAAiB,MACnC,MACA,EAAE,SAAS,YACX,EAAE,aAAa,WAAW,WAC1B,EAAE,0BAA0B,wBAAwB,QACrD,EAEiB;KACjB,MAAMC,QAA4B,EAAE,MAAM,UAAU;AACpD,SAAI,QACH,OAAM,UAAU;AAEjB,SAAI,qBACH,OAAM,uBAAuB;AAE9B,sBAAiB,KAAK,MAAM;;;AAI9B,OAAI,KAAK,SAAS,mBAAmB,KAAK,SAAS,kBAClD;SAAK,MAAM,QAAQ,eAAe,WACjC,KACC,KAAK,SAAS,kBACd,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,MAClB;AACD,SAAI,KAAK,SAAS,KAAK,MAAM,SAAS,iBAAiB;MACtD,MAAM,KAAK,KAAK,MAAM;AAItB,UAAI,CAHgB,uBAAuB,MACzC,MAAM,EAAE,OAAO,GAChB,CAEA,wBAAuB,KAAK,EAAE,IAAI,CAAC;WAGpC,SAAQ,KACP,uEAAuE,eAAe,OAAO,KAAK,MAAM,GACxG;AAEF;;;;EAKJ;;AAGF,SAAgB,uBACf,UAAmC,EAAE,EACnB;CAClB,MAAM,EAAE,eAAe;CACvB,MAAMC,mBAAyC,EAAE;CACjD,MAAMC,yBAAyC,EAAE;CACjD,MAAM,kCAAkB,IAAI,KAAa;CACzC,MAAM,qCAAqB,IAAI,KAAa;AAE5C,eAAyB;EACxB,MAAM;EACN,SAAS,wBACR,kBACA,wBACA,iBACA,mBACA;EACD,OAAO;AACN,OAAI,WAKH,YAJiC;IAChC,SAAS,CAAC,GAAG,iBAAiB;IAC9B,eAAe,CAAC,GAAG,uBAAuB;IAC1C,CACiB;;EAGpB;;;;;AC1SF,SAAwB,uBAAkC;AAMzD,QAAO;EACN,MAAM;EACN,SAAS,wBAPqC,EAAE,EACF,EAAE,kBACzB,IAAI,KAAa,kBACd,IAAI,KAAa,CAS1C;EACD;;AAGF,SAAgB,YAAY,QAAuC;AAClE,QAAO;EACN,SAAS;EACT,SAAS,OAAO;EAChB,eAAe,OAAO;EACtB,UAAU;GACT,8BAAa,IAAI,MAAM,EAAC,aAAa;GACrC,cAAc,OAAO,QAAQ;GAC7B,oBAAoB,OAAO,cAAc;GACzC;EACD"}
1
+ {"version":3,"file":"index.cjs","names":["current: NodePath | null","context: string | null","entry: TranslatableString","collectedStrings: TranslatableString[]","collectedContextBlocks: ContextBlock[]"],"sources":["../src/visitor.ts","../src/index.ts"],"sourcesContent":["import type { NodePath, PluginObj, PluginPass } from \"@babel/core\";\nimport type {\n\tCallExpression,\n\tJSXElement,\n\tJSXText,\n\tJSXExpressionContainer,\n\tJSXFragment,\n\tJSXIdentifier,\n\tJSXMemberExpression,\n\tJSXNamespacedName,\n\tVariableDeclarator,\n\tNode,\n} from \"@babel/types\";\nimport type {\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n} from \"./types\";\n\ninterface BabelPluginState extends PluginPass {\n\tcollectedStrings: TranslatableString[];\n\tcollectedContextBlocks: ContextBlock[];\n\tctVariableNames: Set<string>;\n\tprocessedLocations: Set<string>;\n}\n\nfunction formatLocation(\n\tstate: PluginPass,\n\tloc: { line: number; column: number } | null | undefined,\n): string {\n\tconst filename = state.filename || state.file?.opts?.filename || \"unknown\";\n\tif (loc) {\n\t\treturn `${filename}:${loc.line}:${loc.column}`;\n\t}\n\treturn filename;\n}\n\nfunction getFilename(state: PluginPass): string {\n\treturn state.filename || state.file?.opts?.filename || \"unknown\";\n}\n\nfunction isCTContextBlock(\n\tname: JSXIdentifier | JSXMemberExpression | JSXNamespacedName,\n): boolean {\n\tif (name.type === \"JSXIdentifier\") {\n\t\treturn name.name === \"CTContextBlock\";\n\t}\n\tif (name.type === \"JSXMemberExpression\") {\n\t\treturn (\n\t\t\tname.property.type === \"JSXIdentifier\" &&\n\t\t\tname.property.name === \"CTContextBlock\"\n\t\t);\n\t}\n\treturn false;\n}\n\nfunction isTrans(\n\tname: JSXIdentifier | JSXMemberExpression | JSXNamespacedName,\n): boolean {\n\tif (name.type === \"JSXIdentifier\") {\n\t\treturn name.name === \"Trans\";\n\t}\n\tif (name.type === \"JSXMemberExpression\") {\n\t\treturn (\n\t\t\tname.property.type === \"JSXIdentifier\" && name.property.name === \"Trans\"\n\t\t);\n\t}\n\treturn false;\n}\n\ninterface ExpressionCounter {\n\tcurrent: number;\n}\n\nfunction extractTransTemplate(\n\tchildren: Node[],\n\texpressionCounter?: ExpressionCounter,\n): string {\n\tlet elementIndex = 0;\n\tconst exprCounter = expressionCounter || { current: 0 };\n\n\tfunction processNode(node: Node): string {\n\t\tif (node.type === \"JSXText\") {\n\t\t\treturn (node as JSXText).value.replace(/\\s+/g, \" \");\n\t\t}\n\n\t\tif (node.type === \"JSXExpressionContainer\") {\n\t\t\tconst expr = (node as JSXExpressionContainer).expression;\n\t\t\tif (expr.type === \"StringLiteral\") {\n\t\t\t\treturn expr.value;\n\t\t\t}\n\t\t\tif (expr.type === \"JSXEmptyExpression\") {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\tconst idx = exprCounter.current++;\n\t\t\treturn `{${idx}}`;\n\t\t}\n\n\t\tif (node.type === \"JSXElement\") {\n\t\t\tconst elem = node as JSXElement;\n\t\t\tconst idx = elementIndex++;\n\t\t\tconst innerContent = elem.children.map(processNode).join(\"\");\n\t\t\treturn `<${idx}>${innerContent}</${idx}>`;\n\t\t}\n\n\t\tif (node.type === \"JSXFragment\") {\n\t\t\tconst frag = node as JSXFragment;\n\t\t\treturn frag.children.map(processNode).join(\"\");\n\t\t}\n\n\t\treturn \"\";\n\t}\n\n\treturn children.map(processNode).join(\"\").trim();\n}\n\nfunction getContextBlockIdForJSX(path: NodePath<JSXElement>): string | null {\n\tlet current: NodePath | null = path.parentPath;\n\n\twhile (current) {\n\t\tif (current.isJSXElement()) {\n\t\t\tconst openingElement = current.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\n\t\t\tif (isCTContextBlock(name)) {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\" &&\n\t\t\t\t\t\tattr.value?.type === \"StringLiteral\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn attr.value.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentPath;\n\t}\n\n\treturn null;\n}\n\nfunction getContextBlockId(path: NodePath<CallExpression>): string | null {\n\tlet current: NodePath | null = path.parentPath;\n\n\twhile (current) {\n\t\tif (current.isJSXElement()) {\n\t\t\tconst openingElement = current.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\n\t\t\tif (isCTContextBlock(name)) {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\" &&\n\t\t\t\t\t\tattr.value?.type === \"StringLiteral\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn attr.value.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentPath;\n\t}\n\n\treturn null;\n}\n\nexport function createExtractionVisitor(\n\tcollectedStrings: TranslatableString[],\n\tcollectedContextBlocks: ContextBlock[],\n\tctVariableNames: Set<string>,\n\tprocessedLocations: Set<string>,\n): PluginObj[\"visitor\"] {\n\treturn {\n\t\tVariableDeclarator(path: NodePath<VariableDeclarator>) {\n\t\t\tconst init = path.node.init;\n\t\t\tconst id = path.node.id;\n\n\t\t\tif (\n\t\t\t\tinit &&\n\t\t\t\tinit.type === \"CallExpression\" &&\n\t\t\t\tinit.callee.type === \"Identifier\" &&\n\t\t\t\tinit.callee.name === \"useCt\"\n\t\t\t) {\n\t\t\t\tif (id.type === \"Identifier\") {\n\t\t\t\t\tctVariableNames.add(id.name);\n\t\t\t\t} else if (id.type === \"ObjectPattern\") {\n\t\t\t\t\tfor (const prop of id.properties) {\n\t\t\t\t\t\tif (prop.type === \"ObjectProperty\") {\n\t\t\t\t\t\t\tif (prop.value.type === \"Identifier\") {\n\t\t\t\t\t\t\t\tctVariableNames.add(prop.value.name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tprop.type === \"RestElement\" &&\n\t\t\t\t\t\t\tprop.argument.type === \"Identifier\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tctVariableNames.add(prop.argument.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tCallExpression(path: NodePath<CallExpression>, state: PluginPass) {\n\t\t\tconst callee = path.node.callee;\n\n\t\t\tif (callee.type === \"Identifier\" && ctVariableNames.has(callee.name)) {\n\t\t\t\tconst loc = path.node.loc;\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst filename = getFilename(state);\n\t\t\t\t\tconst locationKey = `${filename}:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst args = path.node.arguments;\n\n\t\t\t\tif (args.length === 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst textArg = args[0];\n\n\t\t\t\tif (textArg.type !== \"StringLiteral\") {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with non-string literal at ${formatLocation(state, loc?.start)}. Only string literals are supported. Skipping dynamic string.`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst text = textArg.value;\n\t\t\t\tlet context: string | null = null;\n\n\t\t\t\tif (args.length >= 2) {\n\t\t\t\t\tconst contextArg = args[1];\n\t\t\t\t\tif (contextArg.type === \"StringLiteral\") {\n\t\t\t\t\t\tcontext = contextArg.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockId(path);\n\n\t\t\t\tconst isDuplicate = collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === text &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tcollectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tJSXElement(path: NodePath<JSXElement>, state: PluginPass) {\n\t\t\tconst openingElement = path.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\t\t\tconst loc = path.node.loc;\n\n\t\t\tif (isTrans(name)) {\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst filename = getFilename(state);\n\t\t\t\t\tconst locationKey = `${filename}:jsx:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst expressionCounter = { current: 0 };\n\t\t\t\tconst template = extractTransTemplate(\n\t\t\t\t\tpath.node.children,\n\t\t\t\t\texpressionCounter,\n\t\t\t\t);\n\t\t\t\tif (!template) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet context: string | null = null;\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"context\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value?.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tcontext = attr.value.value;\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tattr.value?.type === \"JSXExpressionContainer\" &&\n\t\t\t\t\t\t\tattr.value.expression.type === \"StringLiteral\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcontext = attr.value.expression.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockIdForJSX(path);\n\n\t\t\t\tconst isDuplicate = collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === template &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text: template };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tcollectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isCTContextBlock(name)) {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value && attr.value.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tconst id = attr.value.value;\n\t\t\t\t\t\t\tconst isDuplicate = collectedContextBlocks.some(\n\t\t\t\t\t\t\t\t(b) => b.id === id,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\t\t\t\tcollectedContextBlocks.push({ id });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createExtractionVisitorWithState(): PluginObj<BabelPluginState>[\"visitor\"] {\n\treturn {\n\t\tVariableDeclarator(\n\t\t\tpath: NodePath<VariableDeclarator>,\n\t\t\tstate: BabelPluginState,\n\t\t) {\n\t\t\tconst init = path.node.init;\n\t\t\tconst id = path.node.id;\n\n\t\t\tif (\n\t\t\t\tinit &&\n\t\t\t\tinit.type === \"CallExpression\" &&\n\t\t\t\tinit.callee.type === \"Identifier\" &&\n\t\t\t\tinit.callee.name === \"useCt\"\n\t\t\t) {\n\t\t\t\tif (id.type === \"Identifier\") {\n\t\t\t\t\tstate.ctVariableNames.add(id.name);\n\t\t\t\t} else if (id.type === \"ObjectPattern\") {\n\t\t\t\t\tfor (const prop of id.properties) {\n\t\t\t\t\t\tif (prop.type === \"ObjectProperty\") {\n\t\t\t\t\t\t\tif (prop.value.type === \"Identifier\") {\n\t\t\t\t\t\t\t\tstate.ctVariableNames.add(prop.value.name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tprop.type === \"RestElement\" &&\n\t\t\t\t\t\t\tprop.argument.type === \"Identifier\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tstate.ctVariableNames.add(prop.argument.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tCallExpression(path: NodePath<CallExpression>, state: BabelPluginState) {\n\t\t\tconst callee = path.node.callee;\n\n\t\t\tif (\n\t\t\t\tcallee.type === \"Identifier\" &&\n\t\t\t\tstate.ctVariableNames.has(callee.name)\n\t\t\t) {\n\t\t\t\tconst loc = path.node.loc;\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst filename = getFilename(state);\n\t\t\t\t\tconst locationKey = `${filename}:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (state.processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tstate.processedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst args = path.node.arguments;\n\n\t\t\t\tif (args.length === 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst textArg = args[0];\n\n\t\t\t\tif (textArg.type !== \"StringLiteral\") {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with non-string literal at ${formatLocation(state, loc?.start)}. Only string literals are supported. Skipping dynamic string.`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst text = textArg.value;\n\t\t\t\tlet context: string | null = null;\n\n\t\t\t\tif (args.length >= 2) {\n\t\t\t\t\tconst contextArg = args[1];\n\t\t\t\t\tif (contextArg.type === \"StringLiteral\") {\n\t\t\t\t\t\tcontext = contextArg.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockId(path);\n\n\t\t\t\tconst isDuplicate = state.collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === text &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tstate.collectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tJSXElement(path: NodePath<JSXElement>, state: BabelPluginState) {\n\t\t\tconst openingElement = path.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\t\t\tconst loc = path.node.loc;\n\n\t\t\tif (isTrans(name)) {\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst filename = getFilename(state);\n\t\t\t\t\tconst locationKey = `${filename}:jsx:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (state.processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tstate.processedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst expressionCounter = { current: 0 };\n\t\t\t\tconst template = extractTransTemplate(\n\t\t\t\t\tpath.node.children,\n\t\t\t\t\texpressionCounter,\n\t\t\t\t);\n\t\t\t\tif (!template) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet context: string | null = null;\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"context\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value?.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tcontext = attr.value.value;\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tattr.value?.type === \"JSXExpressionContainer\" &&\n\t\t\t\t\t\t\tattr.value.expression.type === \"StringLiteral\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcontext = attr.value.expression.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockIdForJSX(path);\n\n\t\t\t\tconst isDuplicate = state.collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === template &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text: template };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tstate.collectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isCTContextBlock(name)) {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value && attr.value.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tconst id = attr.value.value;\n\t\t\t\t\t\t\tconst isDuplicate = state.collectedContextBlocks.some(\n\t\t\t\t\t\t\t\t(b) => b.id === id,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\t\t\t\tstate.collectedContextBlocks.push({ id });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createExtractionPlugin(\n\toptions: ExtractionPluginOptions = {},\n): () => PluginObj {\n\tconst { onComplete } = options;\n\tconst collectedStrings: TranslatableString[] = [];\n\tconst collectedContextBlocks: ContextBlock[] = [];\n\tconst ctVariableNames = new Set<string>();\n\tconst processedLocations = new Set<string>();\n\n\treturn (): PluginObj => ({\n\t\tname: \"@ciao-tools/babel-extraction\",\n\t\tvisitor: createExtractionVisitor(\n\t\t\tcollectedStrings,\n\t\t\tcollectedContextBlocks,\n\t\t\tctVariableNames,\n\t\t\tprocessedLocations,\n\t\t),\n\t\tpost() {\n\t\t\tif (onComplete) {\n\t\t\t\tconst result: ExtractionResult = {\n\t\t\t\t\tstrings: [...collectedStrings],\n\t\t\t\t\tcontextBlocks: [...collectedContextBlocks],\n\t\t\t\t};\n\t\t\t\tonComplete(result);\n\t\t\t}\n\t\t},\n\t});\n}\n\nexport function getCollectedData(\n\tcollectedStrings: TranslatableString[],\n\tcollectedContextBlocks: ContextBlock[],\n): ExtractionResult {\n\treturn {\n\t\tstrings: [...collectedStrings],\n\t\tcontextBlocks: [...collectedContextBlocks],\n\t};\n}\n","import type { PluginObj, PluginPass } from \"@babel/core\";\nimport type {\n\tBuildSchema,\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n} from \"./types\";\nimport { createExtractionVisitorWithState } from \"./visitor\";\n\nexport type {\n\tBuildSchema,\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n};\nexport { createExtractionPlugin } from \"./visitor\";\n\nexport interface BabelPluginState extends PluginPass {\n\tcollectedStrings: TranslatableString[];\n\tcollectedContextBlocks: ContextBlock[];\n\tctVariableNames: Set<string>;\n\tprocessedLocations: Set<string>;\n}\n\nexport default function ciaoToolsBabelPlugin(): PluginObj<BabelPluginState> {\n\treturn {\n\t\tname: \"@ciao-tools/babel\",\n\t\tpre() {\n\t\t\tthis.collectedStrings = [];\n\t\t\tthis.collectedContextBlocks = [];\n\t\t\tthis.ctVariableNames = new Set<string>();\n\t\t\tthis.processedLocations = new Set<string>();\n\t\t},\n\t\tvisitor: createExtractionVisitorWithState(),\n\t};\n}\n\nexport function buildSchema(result: ExtractionResult): BuildSchema {\n\treturn {\n\t\tversion: \"1.0\",\n\t\tstrings: result.strings,\n\t\tcontextBlocks: result.contextBlocks,\n\t\tmetadata: {\n\t\t\tgeneratedAt: new Date().toISOString(),\n\t\t\ttotalStrings: result.strings.length,\n\t\t\ttotalContextBlocks: result.contextBlocks.length,\n\t\t},\n\t};\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { PluginObj } from "@babel/core";
1
+ import { PluginObj, PluginPass } from "@babel/core";
2
2
 
3
3
  //#region src/types.d.ts
4
4
  interface TranslatableString {
@@ -31,8 +31,14 @@ interface ExtractionPluginOptions {
31
31
  declare function createExtractionPlugin(options?: ExtractionPluginOptions): () => PluginObj;
32
32
  //#endregion
33
33
  //#region src/index.d.ts
34
- declare function ciaoToolsBabelPlugin(): PluginObj;
34
+ interface BabelPluginState extends PluginPass {
35
+ collectedStrings: TranslatableString[];
36
+ collectedContextBlocks: ContextBlock[];
37
+ ctVariableNames: Set<string>;
38
+ processedLocations: Set<string>;
39
+ }
40
+ declare function ciaoToolsBabelPlugin(): PluginObj<BabelPluginState>;
35
41
  declare function buildSchema(result: ExtractionResult): BuildSchema;
36
42
  //#endregion
37
- export { type BuildSchema, type ContextBlock, type ExtractionPluginOptions, type ExtractionResult, type TranslatableString, buildSchema, createExtractionPlugin, ciaoToolsBabelPlugin as default };
43
+ export { BabelPluginState, type BuildSchema, type ContextBlock, type ExtractionPluginOptions, type ExtractionResult, type TranslatableString, buildSchema, createExtractionPlugin, ciaoToolsBabelPlugin as default };
38
44
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/visitor.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;UAAiB,kBAAA;;;EAAA,oBAAA,CAAkB,EAAA,MAAA;AAMnC;AAIiB,UAJA,YAAA,CAIgB;EAKhB,EAAA,EAAA,MAAA;AAWjB;UAhBiB,gBAAA;WACP;iBACM;ACuRhB;UDpRiB,WAAA;;WAEP;EEEc,aAAA,EFDR,YEC4B,EAAA;EAiB5B,QAAA,EAAA;;;;;;UFVC,uBAAA;wBACM;;;;AA3BN,iBCmSD,sBAAA,CDnSmB,OAAA,CAAA,ECoSzB,uBDpSyB,CAAA,EAAA,GAAA,GCqS1B,SDrS0B;;;AAMlB,iBEaO,oBAAA,CAAA,CFbK,EEamB,SFbnB;AAIZ,iBE0BD,WAAA,CFzBN,MAAA,EEyB0B,gBFxBpB,CAAA,EEwBuC,WFxB3B"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/visitor.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;UAAiB,kBAAA;;;EAAA,oBAAA,CAAkB,EAAA,MAAA;AAMnC;AAIiB,UAJA,YAAA,CAIgB;EAKhB,EAAA,EAAA,MAAA;AAWjB;UAhBiB,gBAAA;WACP;iBACM;AC8hBhB;UD3hBiB,WAAA;;WAEP;EEEO,aAAA,EFDD,YECkB,EAAA;EACf,QAAA,EAAA;IACM,WAAA,EAAA,MAAA;IACP,YAAA,EAAA,MAAA;IACG,kBAAA,EAAA,MAAA;EAJqB,CAAA;;AAOlB,UFAP,uBAAA,CEAyC;EAa1C,UAAA,CAAA,EAAA,CAAW,MAAA,EFZJ,gBEYa,EAAA,GAAmB,IAAA;;;;iBDmgBvC,sBAAA,WACN,gCACD;;;ADtiBQ,UEaA,gBAAA,SAAyB,UFbb,CAAA;EAIZ,gBAAA,EEUE,kBFTT,EAAA;EAIO,sBAAW,EEMH,YFJf,EAAA;EASO,eAAA,EEJC,GFID,CAAA,MAAuB,CAAA;sBEHnB;;iBAGG,oBAAA,CAAA,GAAwB,UAAU;ADghB1C,iBCngBA,WAAA,CDmgBsB,MAC5B,ECpgB0B,gBDogB1B,CAAA,ECpgB6C,WDqgB9C"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { PluginObj } from "@babel/core";
1
+ import { PluginObj, PluginPass } from "@babel/core";
2
2
 
3
3
  //#region src/types.d.ts
4
4
  interface TranslatableString {
@@ -31,8 +31,14 @@ interface ExtractionPluginOptions {
31
31
  declare function createExtractionPlugin(options?: ExtractionPluginOptions): () => PluginObj;
32
32
  //#endregion
33
33
  //#region src/index.d.ts
34
- declare function ciaoToolsBabelPlugin(): PluginObj;
34
+ interface BabelPluginState extends PluginPass {
35
+ collectedStrings: TranslatableString[];
36
+ collectedContextBlocks: ContextBlock[];
37
+ ctVariableNames: Set<string>;
38
+ processedLocations: Set<string>;
39
+ }
40
+ declare function ciaoToolsBabelPlugin(): PluginObj<BabelPluginState>;
35
41
  declare function buildSchema(result: ExtractionResult): BuildSchema;
36
42
  //#endregion
37
- export { type BuildSchema, type ContextBlock, type ExtractionPluginOptions, type ExtractionResult, type TranslatableString, buildSchema, createExtractionPlugin, ciaoToolsBabelPlugin as default };
43
+ export { BabelPluginState, type BuildSchema, type ContextBlock, type ExtractionPluginOptions, type ExtractionResult, type TranslatableString, buildSchema, createExtractionPlugin, ciaoToolsBabelPlugin as default };
38
44
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/visitor.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;UAAiB,kBAAA;;;EAAA,oBAAA,CAAkB,EAAA,MAAA;AAMnC;AAIiB,UAJA,YAAA,CAIgB;EAKhB,EAAA,EAAA,MAAA;AAWjB;UAhBiB,gBAAA;WACP;iBACM;ACuRhB;UDpRiB,WAAA;;WAEP;EEEc,aAAA,EFDR,YEC4B,EAAA;EAiB5B,QAAA,EAAA;;;;;;UFVC,uBAAA;wBACM;;;;AA3BN,iBCmSD,sBAAA,CDnSmB,OAAA,CAAA,ECoSzB,uBDpSyB,CAAA,EAAA,GAAA,GCqS1B,SDrS0B;;;AAMlB,iBEaO,oBAAA,CAAA,CFbK,EEamB,SFbnB;AAIZ,iBE0BD,WAAA,CFzBN,MAAA,EEyB0B,gBFxBpB,CAAA,EEwBuC,WFxB3B"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/visitor.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;UAAiB,kBAAA;;;EAAA,oBAAA,CAAkB,EAAA,MAAA;AAMnC;AAIiB,UAJA,YAAA,CAIgB;EAKhB,EAAA,EAAA,MAAA;AAWjB;UAhBiB,gBAAA;WACP;iBACM;AC8hBhB;UD3hBiB,WAAA;;WAEP;EEEO,aAAA,EFDD,YECkB,EAAA;EACf,QAAA,EAAA;IACM,WAAA,EAAA,MAAA;IACP,YAAA,EAAA,MAAA;IACG,kBAAA,EAAA,MAAA;EAJqB,CAAA;;AAOlB,UFAP,uBAAA,CEAyC;EAa1C,UAAA,CAAA,EAAA,CAAW,MAAA,EFZJ,gBEYa,EAAA,GAAmB,IAAA;;;;iBDmgBvC,sBAAA,WACN,gCACD;;;ADtiBQ,UEaA,gBAAA,SAAyB,UFbb,CAAA;EAIZ,gBAAA,EEUE,kBFTT,EAAA;EAIO,sBAAW,EEMH,YFJf,EAAA;EASO,eAAA,EEJC,GFID,CAAA,MAAuB,CAAA;sBEHnB;;iBAGG,oBAAA,CAAA,GAAwB,UAAU;ADghB1C,iBCngBA,WAAA,CDmgBsB,MAC5B,ECpgB0B,gBDogB1B,CAAA,ECpgB6C,WDqgB9C"}
package/dist/index.mjs CHANGED
@@ -4,14 +4,29 @@ function formatLocation(state, loc) {
4
4
  if (loc) return `${filename}:${loc.line}:${loc.column}`;
5
5
  return filename;
6
6
  }
7
- function extractTransTemplate(children) {
7
+ function getFilename(state) {
8
+ return state.filename || state.file?.opts?.filename || "unknown";
9
+ }
10
+ function isCTContextBlock(name) {
11
+ if (name.type === "JSXIdentifier") return name.name === "CTContextBlock";
12
+ if (name.type === "JSXMemberExpression") return name.property.type === "JSXIdentifier" && name.property.name === "CTContextBlock";
13
+ return false;
14
+ }
15
+ function isTrans(name) {
16
+ if (name.type === "JSXIdentifier") return name.name === "Trans";
17
+ if (name.type === "JSXMemberExpression") return name.property.type === "JSXIdentifier" && name.property.name === "Trans";
18
+ return false;
19
+ }
20
+ function extractTransTemplate(children, expressionCounter) {
8
21
  let elementIndex = 0;
22
+ const exprCounter = expressionCounter || { current: 0 };
9
23
  function processNode(node) {
10
24
  if (node.type === "JSXText") return node.value.replace(/\s+/g, " ");
11
25
  if (node.type === "JSXExpressionContainer") {
12
26
  const expr = node.expression;
13
27
  if (expr.type === "StringLiteral") return expr.value;
14
- return "";
28
+ if (expr.type === "JSXEmptyExpression") return "";
29
+ return `{${exprCounter.current++}}`;
15
30
  }
16
31
  if (node.type === "JSXElement") {
17
32
  const elem = node;
@@ -29,7 +44,7 @@ function getContextBlockIdForJSX(path) {
29
44
  if (current.isJSXElement()) {
30
45
  const openingElement = current.node.openingElement;
31
46
  const name = openingElement.name;
32
- if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
47
+ if (isCTContextBlock(name)) {
33
48
  for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id" && attr.value?.type === "StringLiteral") return attr.value.value;
34
49
  }
35
50
  }
@@ -43,7 +58,7 @@ function getContextBlockId(path) {
43
58
  if (current.isJSXElement()) {
44
59
  const openingElement = current.node.openingElement;
45
60
  const name = openingElement.name;
46
- if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
61
+ if (isCTContextBlock(name)) {
47
62
  for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id" && attr.value?.type === "StringLiteral") return attr.value.value;
48
63
  }
49
64
  }
@@ -58,6 +73,11 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
58
73
  const id = path.node.id;
59
74
  if (init && init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "useCt") {
60
75
  if (id.type === "Identifier") ctVariableNames.add(id.name);
76
+ else if (id.type === "ObjectPattern") {
77
+ for (const prop of id.properties) if (prop.type === "ObjectProperty") {
78
+ if (prop.value.type === "Identifier") ctVariableNames.add(prop.value.name);
79
+ } else if (prop.type === "RestElement" && prop.argument.type === "Identifier") ctVariableNames.add(prop.argument.name);
80
+ }
61
81
  }
62
82
  },
63
83
  CallExpression(path, state) {
@@ -65,7 +85,7 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
65
85
  if (callee.type === "Identifier" && ctVariableNames.has(callee.name)) {
66
86
  const loc = path.node.loc;
67
87
  if (loc) {
68
- const locationKey = `${loc.start.line}:${loc.start.column}`;
88
+ const locationKey = `${getFilename(state)}:${loc.start.line}:${loc.start.column}`;
69
89
  if (processedLocations.has(locationKey)) return;
70
90
  processedLocations.add(locationKey);
71
91
  }
@@ -98,13 +118,13 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
98
118
  const openingElement = path.node.openingElement;
99
119
  const name = openingElement.name;
100
120
  const loc = path.node.loc;
101
- if (name.type === "JSXIdentifier" && name.name === "Trans") {
121
+ if (isTrans(name)) {
102
122
  if (loc) {
103
- const locationKey = `jsx:${loc.start.line}:${loc.start.column}`;
123
+ const locationKey = `${getFilename(state)}:jsx:${loc.start.line}:${loc.start.column}`;
104
124
  if (processedLocations.has(locationKey)) return;
105
125
  processedLocations.add(locationKey);
106
126
  }
107
- const template = extractTransTemplate(path.node.children);
127
+ const template = extractTransTemplate(path.node.children, { current: 0 });
108
128
  if (!template) return;
109
129
  let context = null;
110
130
  for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "context") {
@@ -120,7 +140,7 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
120
140
  collectedStrings.push(entry);
121
141
  }
122
142
  }
123
- if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
143
+ if (isCTContextBlock(name)) {
124
144
  for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id") {
125
145
  if (attr.value && attr.value.type === "StringLiteral") {
126
146
  const id = attr.value.value;
@@ -132,6 +152,92 @@ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVar
132
152
  }
133
153
  };
134
154
  }
155
+ function createExtractionVisitorWithState() {
156
+ return {
157
+ VariableDeclarator(path, state) {
158
+ const init = path.node.init;
159
+ const id = path.node.id;
160
+ if (init && init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "useCt") {
161
+ if (id.type === "Identifier") state.ctVariableNames.add(id.name);
162
+ else if (id.type === "ObjectPattern") {
163
+ for (const prop of id.properties) if (prop.type === "ObjectProperty") {
164
+ if (prop.value.type === "Identifier") state.ctVariableNames.add(prop.value.name);
165
+ } else if (prop.type === "RestElement" && prop.argument.type === "Identifier") state.ctVariableNames.add(prop.argument.name);
166
+ }
167
+ }
168
+ },
169
+ CallExpression(path, state) {
170
+ const callee = path.node.callee;
171
+ if (callee.type === "Identifier" && state.ctVariableNames.has(callee.name)) {
172
+ const loc = path.node.loc;
173
+ if (loc) {
174
+ const locationKey = `${getFilename(state)}:${loc.start.line}:${loc.start.column}`;
175
+ if (state.processedLocations.has(locationKey)) return;
176
+ state.processedLocations.add(locationKey);
177
+ }
178
+ const args = path.node.arguments;
179
+ if (args.length === 0) {
180
+ console.warn(`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`);
181
+ return;
182
+ }
183
+ const textArg = args[0];
184
+ if (textArg.type !== "StringLiteral") {
185
+ console.warn(`[ciao-tools] Warning: ${callee.name}() called with non-string literal at ${formatLocation(state, loc?.start)}. Only string literals are supported. Skipping dynamic string.`);
186
+ return;
187
+ }
188
+ const text = textArg.value;
189
+ let context = null;
190
+ if (args.length >= 2) {
191
+ const contextArg = args[1];
192
+ if (contextArg.type === "StringLiteral") context = contextArg.value;
193
+ }
194
+ const parentContextBlockId = getContextBlockId(path);
195
+ if (!state.collectedStrings.some((s) => s.text === text && s.context === (context ?? void 0) && s.parentContextBlockId === (parentContextBlockId ?? void 0))) {
196
+ const entry = { text };
197
+ if (context) entry.context = context;
198
+ if (parentContextBlockId) entry.parentContextBlockId = parentContextBlockId;
199
+ state.collectedStrings.push(entry);
200
+ }
201
+ }
202
+ },
203
+ JSXElement(path, state) {
204
+ const openingElement = path.node.openingElement;
205
+ const name = openingElement.name;
206
+ const loc = path.node.loc;
207
+ if (isTrans(name)) {
208
+ if (loc) {
209
+ const locationKey = `${getFilename(state)}:jsx:${loc.start.line}:${loc.start.column}`;
210
+ if (state.processedLocations.has(locationKey)) return;
211
+ state.processedLocations.add(locationKey);
212
+ }
213
+ const template = extractTransTemplate(path.node.children, { current: 0 });
214
+ if (!template) return;
215
+ let context = null;
216
+ for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "context") {
217
+ if (attr.value?.type === "StringLiteral") context = attr.value.value;
218
+ else if (attr.value?.type === "JSXExpressionContainer" && attr.value.expression.type === "StringLiteral") context = attr.value.expression.value;
219
+ break;
220
+ }
221
+ const parentContextBlockId = getContextBlockIdForJSX(path);
222
+ if (!state.collectedStrings.some((s) => s.text === template && s.context === (context ?? void 0) && s.parentContextBlockId === (parentContextBlockId ?? void 0))) {
223
+ const entry = { text: template };
224
+ if (context) entry.context = context;
225
+ if (parentContextBlockId) entry.parentContextBlockId = parentContextBlockId;
226
+ state.collectedStrings.push(entry);
227
+ }
228
+ }
229
+ if (isCTContextBlock(name)) {
230
+ for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id") {
231
+ if (attr.value && attr.value.type === "StringLiteral") {
232
+ const id = attr.value.value;
233
+ if (!state.collectedContextBlocks.some((b) => b.id === id)) state.collectedContextBlocks.push({ id });
234
+ } else console.warn(`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`);
235
+ break;
236
+ }
237
+ }
238
+ }
239
+ };
240
+ }
135
241
  function createExtractionPlugin(options = {}) {
136
242
  const { onComplete } = options;
137
243
  const collectedStrings = [];
@@ -155,7 +261,13 @@ function createExtractionPlugin(options = {}) {
155
261
  function ciaoToolsBabelPlugin() {
156
262
  return {
157
263
  name: "@ciao-tools/babel",
158
- visitor: createExtractionVisitor([], [], /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set())
264
+ pre() {
265
+ this.collectedStrings = [];
266
+ this.collectedContextBlocks = [];
267
+ this.ctVariableNames = /* @__PURE__ */ new Set();
268
+ this.processedLocations = /* @__PURE__ */ new Set();
269
+ },
270
+ visitor: createExtractionVisitorWithState()
159
271
  };
160
272
  }
161
273
  function buildSchema(result) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["current: NodePath | null","context: string | null","entry: TranslatableString","collectedStrings: TranslatableString[]","collectedContextBlocks: ContextBlock[]"],"sources":["../src/visitor.ts","../src/index.ts"],"sourcesContent":["import type { NodePath, PluginObj, PluginPass } from \"@babel/core\";\nimport type {\n\tCallExpression,\n\tJSXElement,\n\tJSXText,\n\tJSXExpressionContainer,\n\tJSXFragment,\n\tVariableDeclarator,\n\tNode,\n} from \"@babel/types\";\nimport type {\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n} from \"./types\";\n\nfunction formatLocation(\n\tstate: PluginPass,\n\tloc: { line: number; column: number } | null | undefined,\n): string {\n\tconst filename = state.filename || state.file?.opts?.filename || \"unknown\";\n\tif (loc) {\n\t\treturn `${filename}:${loc.line}:${loc.column}`;\n\t}\n\treturn filename;\n}\n\nfunction extractTransTemplate(children: Node[]): string {\n\tlet elementIndex = 0;\n\n\tfunction processNode(node: Node): string {\n\t\tif (node.type === \"JSXText\") {\n\t\t\treturn (node as JSXText).value.replace(/\\s+/g, \" \");\n\t\t}\n\n\t\tif (node.type === \"JSXExpressionContainer\") {\n\t\t\tconst expr = (node as JSXExpressionContainer).expression;\n\t\t\tif (expr.type === \"StringLiteral\") {\n\t\t\t\treturn expr.value;\n\t\t\t}\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (node.type === \"JSXElement\") {\n\t\t\tconst elem = node as JSXElement;\n\t\t\tconst idx = elementIndex++;\n\t\t\tconst innerContent = elem.children.map(processNode).join(\"\");\n\t\t\treturn `<${idx}>${innerContent}</${idx}>`;\n\t\t}\n\n\t\tif (node.type === \"JSXFragment\") {\n\t\t\tconst frag = node as JSXFragment;\n\t\t\treturn frag.children.map(processNode).join(\"\");\n\t\t}\n\n\t\treturn \"\";\n\t}\n\n\treturn children.map(processNode).join(\"\").trim();\n}\n\nfunction getContextBlockIdForJSX(path: NodePath<JSXElement>): string | null {\n\tlet current: NodePath | null = path.parentPath;\n\n\twhile (current) {\n\t\tif (current.isJSXElement()) {\n\t\t\tconst openingElement = current.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\n\t\t\tif (name.type === \"JSXIdentifier\" && name.name === \"CTContextBlock\") {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\" &&\n\t\t\t\t\t\tattr.value?.type === \"StringLiteral\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn attr.value.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentPath;\n\t}\n\n\treturn null;\n}\n\nfunction getContextBlockId(path: NodePath<CallExpression>): string | null {\n\tlet current: NodePath | null = path.parentPath;\n\n\twhile (current) {\n\t\tif (current.isJSXElement()) {\n\t\t\tconst openingElement = current.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\n\t\t\tif (name.type === \"JSXIdentifier\" && name.name === \"CTContextBlock\") {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\" &&\n\t\t\t\t\t\tattr.value?.type === \"StringLiteral\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn attr.value.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentPath;\n\t}\n\n\treturn null;\n}\n\nexport function createExtractionVisitor(\n\tcollectedStrings: TranslatableString[],\n\tcollectedContextBlocks: ContextBlock[],\n\tctVariableNames: Set<string>,\n\tprocessedLocations: Set<string>,\n): PluginObj[\"visitor\"] {\n\treturn {\n\t\tVariableDeclarator(path: NodePath<VariableDeclarator>) {\n\t\t\tconst init = path.node.init;\n\t\t\tconst id = path.node.id;\n\n\t\t\tif (\n\t\t\t\tinit &&\n\t\t\t\tinit.type === \"CallExpression\" &&\n\t\t\t\tinit.callee.type === \"Identifier\" &&\n\t\t\t\tinit.callee.name === \"useCt\"\n\t\t\t) {\n\t\t\t\tif (id.type === \"Identifier\") {\n\t\t\t\t\tctVariableNames.add(id.name);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tCallExpression(path: NodePath<CallExpression>, state: PluginPass) {\n\t\t\tconst callee = path.node.callee;\n\n\t\t\tif (callee.type === \"Identifier\" && ctVariableNames.has(callee.name)) {\n\t\t\t\tconst loc = path.node.loc;\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst locationKey = `${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst args = path.node.arguments;\n\n\t\t\t\tif (args.length === 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst textArg = args[0];\n\n\t\t\t\tif (textArg.type !== \"StringLiteral\") {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with non-string literal at ${formatLocation(state, loc?.start)}. Only string literals are supported. Skipping dynamic string.`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst text = textArg.value;\n\t\t\t\tlet context: string | null = null;\n\n\t\t\t\tif (args.length >= 2) {\n\t\t\t\t\tconst contextArg = args[1];\n\t\t\t\t\tif (contextArg.type === \"StringLiteral\") {\n\t\t\t\t\t\tcontext = contextArg.value;\n\t\t\t\t\t}\n\t\t\t\t\t// Note: ObjectExpression is valid (interpolation values), so we don't warn about it\n\t\t\t\t\t// Only warn for dynamic context strings (identifiers, member expressions, etc.)\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockId(path);\n\n\t\t\t\tconst isDuplicate = collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === text &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tcollectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tJSXElement(path: NodePath<JSXElement>, state: PluginPass) {\n\t\t\tconst openingElement = path.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\t\t\tconst loc = path.node.loc;\n\n\t\t\tif (name.type === \"JSXIdentifier\" && name.name === \"Trans\") {\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst locationKey = `jsx:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst template = extractTransTemplate(path.node.children);\n\t\t\t\tif (!template) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Extract context prop from Trans component\n\t\t\t\tlet context: string | null = null;\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"context\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value?.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tcontext = attr.value.value;\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tattr.value?.type === \"JSXExpressionContainer\" &&\n\t\t\t\t\t\t\tattr.value.expression.type === \"StringLiteral\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcontext = attr.value.expression.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockIdForJSX(path);\n\n\t\t\t\tconst isDuplicate = collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === template &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text: template };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tcollectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (name.type === \"JSXIdentifier\" && name.name === \"CTContextBlock\") {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value && attr.value.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tconst id = attr.value.value;\n\t\t\t\t\t\t\tconst isDuplicate = collectedContextBlocks.some(\n\t\t\t\t\t\t\t\t(b) => b.id === id,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\t\t\t\tcollectedContextBlocks.push({ id });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createExtractionPlugin(\n\toptions: ExtractionPluginOptions = {},\n): () => PluginObj {\n\tconst { onComplete } = options;\n\tconst collectedStrings: TranslatableString[] = [];\n\tconst collectedContextBlocks: ContextBlock[] = [];\n\tconst ctVariableNames = new Set<string>();\n\tconst processedLocations = new Set<string>();\n\n\treturn (): PluginObj => ({\n\t\tname: \"@ciao-tools/babel-extraction\",\n\t\tvisitor: createExtractionVisitor(\n\t\t\tcollectedStrings,\n\t\t\tcollectedContextBlocks,\n\t\t\tctVariableNames,\n\t\t\tprocessedLocations,\n\t\t),\n\t\tpost() {\n\t\t\tif (onComplete) {\n\t\t\t\tconst result: ExtractionResult = {\n\t\t\t\t\tstrings: [...collectedStrings],\n\t\t\t\t\tcontextBlocks: [...collectedContextBlocks],\n\t\t\t\t};\n\t\t\t\tonComplete(result);\n\t\t\t}\n\t\t},\n\t});\n}\n\nexport function getCollectedData(\n\tcollectedStrings: TranslatableString[],\n\tcollectedContextBlocks: ContextBlock[],\n): ExtractionResult {\n\treturn {\n\t\tstrings: [...collectedStrings],\n\t\tcontextBlocks: [...collectedContextBlocks],\n\t};\n}\n","import type { PluginObj } from \"@babel/core\";\nimport type {\n\tBuildSchema,\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n} from \"./types\";\nimport { createExtractionVisitor } from \"./visitor\";\n\nexport type {\n\tBuildSchema,\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n};\nexport { createExtractionPlugin } from \"./visitor\";\n\nexport default function ciaoToolsBabelPlugin(): PluginObj {\n\tconst collectedStrings: TranslatableString[] = [];\n\tconst collectedContextBlocks: ContextBlock[] = [];\n\tconst ctVariableNames = new Set<string>();\n\tconst processedLocations = new Set<string>();\n\n\treturn {\n\t\tname: \"@ciao-tools/babel\",\n\t\tvisitor: createExtractionVisitor(\n\t\t\tcollectedStrings,\n\t\t\tcollectedContextBlocks,\n\t\t\tctVariableNames,\n\t\t\tprocessedLocations,\n\t\t),\n\t};\n}\n\nexport function buildSchema(result: ExtractionResult): BuildSchema {\n\treturn {\n\t\tversion: \"1.0\",\n\t\tstrings: result.strings,\n\t\tcontextBlocks: result.contextBlocks,\n\t\tmetadata: {\n\t\t\tgeneratedAt: new Date().toISOString(),\n\t\t\ttotalStrings: result.strings.length,\n\t\t\ttotalContextBlocks: result.contextBlocks.length,\n\t\t},\n\t};\n}\n"],"mappings":";AAiBA,SAAS,eACR,OACA,KACS;CACT,MAAM,WAAW,MAAM,YAAY,MAAM,MAAM,MAAM,YAAY;AACjE,KAAI,IACH,QAAO,GAAG,SAAS,GAAG,IAAI,KAAK,GAAG,IAAI;AAEvC,QAAO;;AAGR,SAAS,qBAAqB,UAA0B;CACvD,IAAI,eAAe;CAEnB,SAAS,YAAY,MAAoB;AACxC,MAAI,KAAK,SAAS,UACjB,QAAQ,KAAiB,MAAM,QAAQ,QAAQ,IAAI;AAGpD,MAAI,KAAK,SAAS,0BAA0B;GAC3C,MAAM,OAAQ,KAAgC;AAC9C,OAAI,KAAK,SAAS,gBACjB,QAAO,KAAK;AAEb,UAAO;;AAGR,MAAI,KAAK,SAAS,cAAc;GAC/B,MAAM,OAAO;GACb,MAAM,MAAM;AAEZ,UAAO,IAAI,IAAI,GADM,KAAK,SAAS,IAAI,YAAY,CAAC,KAAK,GAAG,CAC7B,IAAI,IAAI;;AAGxC,MAAI,KAAK,SAAS,cAEjB,QADa,KACD,SAAS,IAAI,YAAY,CAAC,KAAK,GAAG;AAG/C,SAAO;;AAGR,QAAO,SAAS,IAAI,YAAY,CAAC,KAAK,GAAG,CAAC,MAAM;;AAGjD,SAAS,wBAAwB,MAA2C;CAC3E,IAAIA,UAA2B,KAAK;AAEpC,QAAO,SAAS;AACf,MAAI,QAAQ,cAAc,EAAE;GAC3B,MAAM,iBAAiB,QAAQ,KAAK;GACpC,MAAM,OAAO,eAAe;AAE5B,OAAI,KAAK,SAAS,mBAAmB,KAAK,SAAS,kBAClD;SAAK,MAAM,QAAQ,eAAe,WACjC,KACC,KAAK,SAAS,kBACd,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,QACnB,KAAK,OAAO,SAAS,gBAErB,QAAO,KAAK,MAAM;;;AAKtB,YAAU,QAAQ;;AAGnB,QAAO;;AAGR,SAAS,kBAAkB,MAA+C;CACzE,IAAIA,UAA2B,KAAK;AAEpC,QAAO,SAAS;AACf,MAAI,QAAQ,cAAc,EAAE;GAC3B,MAAM,iBAAiB,QAAQ,KAAK;GACpC,MAAM,OAAO,eAAe;AAE5B,OAAI,KAAK,SAAS,mBAAmB,KAAK,SAAS,kBAClD;SAAK,MAAM,QAAQ,eAAe,WACjC,KACC,KAAK,SAAS,kBACd,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,QACnB,KAAK,OAAO,SAAS,gBAErB,QAAO,KAAK,MAAM;;;AAKtB,YAAU,QAAQ;;AAGnB,QAAO;;AAGR,SAAgB,wBACf,kBACA,wBACA,iBACA,oBACuB;AACvB,QAAO;EACN,mBAAmB,MAAoC;GACtD,MAAM,OAAO,KAAK,KAAK;GACvB,MAAM,KAAK,KAAK,KAAK;AAErB,OACC,QACA,KAAK,SAAS,oBACd,KAAK,OAAO,SAAS,gBACrB,KAAK,OAAO,SAAS,SAErB;QAAI,GAAG,SAAS,aACf,iBAAgB,IAAI,GAAG,KAAK;;;EAK/B,eAAe,MAAgC,OAAmB;GACjE,MAAM,SAAS,KAAK,KAAK;AAEzB,OAAI,OAAO,SAAS,gBAAgB,gBAAgB,IAAI,OAAO,KAAK,EAAE;IACrE,MAAM,MAAM,KAAK,KAAK;AACtB,QAAI,KAAK;KACR,MAAM,cAAc,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM;AACnD,SAAI,mBAAmB,IAAI,YAAY,CACtC;AAED,wBAAmB,IAAI,YAAY;;IAGpC,MAAM,OAAO,KAAK,KAAK;AAEvB,QAAI,KAAK,WAAW,GAAG;AACtB,aAAQ,KACP,yBAAyB,OAAO,KAAK,iCAAiC,eAAe,OAAO,KAAK,MAAM,GACvG;AACD;;IAGD,MAAM,UAAU,KAAK;AAErB,QAAI,QAAQ,SAAS,iBAAiB;AACrC,aAAQ,KACP,yBAAyB,OAAO,KAAK,uCAAuC,eAAe,OAAO,KAAK,MAAM,CAAC,gEAC9G;AACD;;IAGD,MAAM,OAAO,QAAQ;IACrB,IAAIC,UAAyB;AAE7B,QAAI,KAAK,UAAU,GAAG;KACrB,MAAM,aAAa,KAAK;AACxB,SAAI,WAAW,SAAS,gBACvB,WAAU,WAAW;;IAMvB,MAAM,uBAAuB,kBAAkB,KAAK;AAQpD,QAAI,CANgB,iBAAiB,MACnC,MACA,EAAE,SAAS,QACX,EAAE,aAAa,WAAW,WAC1B,EAAE,0BAA0B,wBAAwB,QACrD,EACiB;KACjB,MAAMC,QAA4B,EAAE,MAAM;AAC1C,SAAI,QACH,OAAM,UAAU;AAEjB,SAAI,qBACH,OAAM,uBAAuB;AAE9B,sBAAiB,KAAK,MAAM;;;;EAK/B,WAAW,MAA4B,OAAmB;GACzD,MAAM,iBAAiB,KAAK,KAAK;GACjC,MAAM,OAAO,eAAe;GAC5B,MAAM,MAAM,KAAK,KAAK;AAEtB,OAAI,KAAK,SAAS,mBAAmB,KAAK,SAAS,SAAS;AAC3D,QAAI,KAAK;KACR,MAAM,cAAc,OAAO,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM;AACvD,SAAI,mBAAmB,IAAI,YAAY,CACtC;AAED,wBAAmB,IAAI,YAAY;;IAGpC,MAAM,WAAW,qBAAqB,KAAK,KAAK,SAAS;AACzD,QAAI,CAAC,SACJ;IAID,IAAID,UAAyB;AAC7B,SAAK,MAAM,QAAQ,eAAe,WACjC,KACC,KAAK,SAAS,kBACd,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,WAClB;AACD,SAAI,KAAK,OAAO,SAAS,gBACxB,WAAU,KAAK,MAAM;cAErB,KAAK,OAAO,SAAS,4BACrB,KAAK,MAAM,WAAW,SAAS,gBAE/B,WAAU,KAAK,MAAM,WAAW;AAEjC;;IAIF,MAAM,uBAAuB,wBAAwB,KAAK;AAS1D,QAAI,CAPgB,iBAAiB,MACnC,MACA,EAAE,SAAS,YACX,EAAE,aAAa,WAAW,WAC1B,EAAE,0BAA0B,wBAAwB,QACrD,EAEiB;KACjB,MAAMC,QAA4B,EAAE,MAAM,UAAU;AACpD,SAAI,QACH,OAAM,UAAU;AAEjB,SAAI,qBACH,OAAM,uBAAuB;AAE9B,sBAAiB,KAAK,MAAM;;;AAI9B,OAAI,KAAK,SAAS,mBAAmB,KAAK,SAAS,kBAClD;SAAK,MAAM,QAAQ,eAAe,WACjC,KACC,KAAK,SAAS,kBACd,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,MAClB;AACD,SAAI,KAAK,SAAS,KAAK,MAAM,SAAS,iBAAiB;MACtD,MAAM,KAAK,KAAK,MAAM;AAItB,UAAI,CAHgB,uBAAuB,MACzC,MAAM,EAAE,OAAO,GAChB,CAEA,wBAAuB,KAAK,EAAE,IAAI,CAAC;WAGpC,SAAQ,KACP,uEAAuE,eAAe,OAAO,KAAK,MAAM,GACxG;AAEF;;;;EAKJ;;AAGF,SAAgB,uBACf,UAAmC,EAAE,EACnB;CAClB,MAAM,EAAE,eAAe;CACvB,MAAMC,mBAAyC,EAAE;CACjD,MAAMC,yBAAyC,EAAE;CACjD,MAAM,kCAAkB,IAAI,KAAa;CACzC,MAAM,qCAAqB,IAAI,KAAa;AAE5C,eAAyB;EACxB,MAAM;EACN,SAAS,wBACR,kBACA,wBACA,iBACA,mBACA;EACD,OAAO;AACN,OAAI,WAKH,YAJiC;IAChC,SAAS,CAAC,GAAG,iBAAiB;IAC9B,eAAe,CAAC,GAAG,uBAAuB;IAC1C,CACiB;;EAGpB;;;;;AC1SF,SAAwB,uBAAkC;AAMzD,QAAO;EACN,MAAM;EACN,SAAS,wBAPqC,EAAE,EACF,EAAE,kBACzB,IAAI,KAAa,kBACd,IAAI,KAAa,CAS1C;EACD;;AAGF,SAAgB,YAAY,QAAuC;AAClE,QAAO;EACN,SAAS;EACT,SAAS,OAAO;EAChB,eAAe,OAAO;EACtB,UAAU;GACT,8BAAa,IAAI,MAAM,EAAC,aAAa;GACrC,cAAc,OAAO,QAAQ;GAC7B,oBAAoB,OAAO,cAAc;GACzC;EACD"}
1
+ {"version":3,"file":"index.mjs","names":["current: NodePath | null","context: string | null","entry: TranslatableString","collectedStrings: TranslatableString[]","collectedContextBlocks: ContextBlock[]"],"sources":["../src/visitor.ts","../src/index.ts"],"sourcesContent":["import type { NodePath, PluginObj, PluginPass } from \"@babel/core\";\nimport type {\n\tCallExpression,\n\tJSXElement,\n\tJSXText,\n\tJSXExpressionContainer,\n\tJSXFragment,\n\tJSXIdentifier,\n\tJSXMemberExpression,\n\tJSXNamespacedName,\n\tVariableDeclarator,\n\tNode,\n} from \"@babel/types\";\nimport type {\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n} from \"./types\";\n\ninterface BabelPluginState extends PluginPass {\n\tcollectedStrings: TranslatableString[];\n\tcollectedContextBlocks: ContextBlock[];\n\tctVariableNames: Set<string>;\n\tprocessedLocations: Set<string>;\n}\n\nfunction formatLocation(\n\tstate: PluginPass,\n\tloc: { line: number; column: number } | null | undefined,\n): string {\n\tconst filename = state.filename || state.file?.opts?.filename || \"unknown\";\n\tif (loc) {\n\t\treturn `${filename}:${loc.line}:${loc.column}`;\n\t}\n\treturn filename;\n}\n\nfunction getFilename(state: PluginPass): string {\n\treturn state.filename || state.file?.opts?.filename || \"unknown\";\n}\n\nfunction isCTContextBlock(\n\tname: JSXIdentifier | JSXMemberExpression | JSXNamespacedName,\n): boolean {\n\tif (name.type === \"JSXIdentifier\") {\n\t\treturn name.name === \"CTContextBlock\";\n\t}\n\tif (name.type === \"JSXMemberExpression\") {\n\t\treturn (\n\t\t\tname.property.type === \"JSXIdentifier\" &&\n\t\t\tname.property.name === \"CTContextBlock\"\n\t\t);\n\t}\n\treturn false;\n}\n\nfunction isTrans(\n\tname: JSXIdentifier | JSXMemberExpression | JSXNamespacedName,\n): boolean {\n\tif (name.type === \"JSXIdentifier\") {\n\t\treturn name.name === \"Trans\";\n\t}\n\tif (name.type === \"JSXMemberExpression\") {\n\t\treturn (\n\t\t\tname.property.type === \"JSXIdentifier\" && name.property.name === \"Trans\"\n\t\t);\n\t}\n\treturn false;\n}\n\ninterface ExpressionCounter {\n\tcurrent: number;\n}\n\nfunction extractTransTemplate(\n\tchildren: Node[],\n\texpressionCounter?: ExpressionCounter,\n): string {\n\tlet elementIndex = 0;\n\tconst exprCounter = expressionCounter || { current: 0 };\n\n\tfunction processNode(node: Node): string {\n\t\tif (node.type === \"JSXText\") {\n\t\t\treturn (node as JSXText).value.replace(/\\s+/g, \" \");\n\t\t}\n\n\t\tif (node.type === \"JSXExpressionContainer\") {\n\t\t\tconst expr = (node as JSXExpressionContainer).expression;\n\t\t\tif (expr.type === \"StringLiteral\") {\n\t\t\t\treturn expr.value;\n\t\t\t}\n\t\t\tif (expr.type === \"JSXEmptyExpression\") {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\tconst idx = exprCounter.current++;\n\t\t\treturn `{${idx}}`;\n\t\t}\n\n\t\tif (node.type === \"JSXElement\") {\n\t\t\tconst elem = node as JSXElement;\n\t\t\tconst idx = elementIndex++;\n\t\t\tconst innerContent = elem.children.map(processNode).join(\"\");\n\t\t\treturn `<${idx}>${innerContent}</${idx}>`;\n\t\t}\n\n\t\tif (node.type === \"JSXFragment\") {\n\t\t\tconst frag = node as JSXFragment;\n\t\t\treturn frag.children.map(processNode).join(\"\");\n\t\t}\n\n\t\treturn \"\";\n\t}\n\n\treturn children.map(processNode).join(\"\").trim();\n}\n\nfunction getContextBlockIdForJSX(path: NodePath<JSXElement>): string | null {\n\tlet current: NodePath | null = path.parentPath;\n\n\twhile (current) {\n\t\tif (current.isJSXElement()) {\n\t\t\tconst openingElement = current.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\n\t\t\tif (isCTContextBlock(name)) {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\" &&\n\t\t\t\t\t\tattr.value?.type === \"StringLiteral\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn attr.value.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentPath;\n\t}\n\n\treturn null;\n}\n\nfunction getContextBlockId(path: NodePath<CallExpression>): string | null {\n\tlet current: NodePath | null = path.parentPath;\n\n\twhile (current) {\n\t\tif (current.isJSXElement()) {\n\t\t\tconst openingElement = current.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\n\t\t\tif (isCTContextBlock(name)) {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\" &&\n\t\t\t\t\t\tattr.value?.type === \"StringLiteral\"\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn attr.value.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentPath;\n\t}\n\n\treturn null;\n}\n\nexport function createExtractionVisitor(\n\tcollectedStrings: TranslatableString[],\n\tcollectedContextBlocks: ContextBlock[],\n\tctVariableNames: Set<string>,\n\tprocessedLocations: Set<string>,\n): PluginObj[\"visitor\"] {\n\treturn {\n\t\tVariableDeclarator(path: NodePath<VariableDeclarator>) {\n\t\t\tconst init = path.node.init;\n\t\t\tconst id = path.node.id;\n\n\t\t\tif (\n\t\t\t\tinit &&\n\t\t\t\tinit.type === \"CallExpression\" &&\n\t\t\t\tinit.callee.type === \"Identifier\" &&\n\t\t\t\tinit.callee.name === \"useCt\"\n\t\t\t) {\n\t\t\t\tif (id.type === \"Identifier\") {\n\t\t\t\t\tctVariableNames.add(id.name);\n\t\t\t\t} else if (id.type === \"ObjectPattern\") {\n\t\t\t\t\tfor (const prop of id.properties) {\n\t\t\t\t\t\tif (prop.type === \"ObjectProperty\") {\n\t\t\t\t\t\t\tif (prop.value.type === \"Identifier\") {\n\t\t\t\t\t\t\t\tctVariableNames.add(prop.value.name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tprop.type === \"RestElement\" &&\n\t\t\t\t\t\t\tprop.argument.type === \"Identifier\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tctVariableNames.add(prop.argument.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tCallExpression(path: NodePath<CallExpression>, state: PluginPass) {\n\t\t\tconst callee = path.node.callee;\n\n\t\t\tif (callee.type === \"Identifier\" && ctVariableNames.has(callee.name)) {\n\t\t\t\tconst loc = path.node.loc;\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst filename = getFilename(state);\n\t\t\t\t\tconst locationKey = `${filename}:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst args = path.node.arguments;\n\n\t\t\t\tif (args.length === 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst textArg = args[0];\n\n\t\t\t\tif (textArg.type !== \"StringLiteral\") {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with non-string literal at ${formatLocation(state, loc?.start)}. Only string literals are supported. Skipping dynamic string.`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst text = textArg.value;\n\t\t\t\tlet context: string | null = null;\n\n\t\t\t\tif (args.length >= 2) {\n\t\t\t\t\tconst contextArg = args[1];\n\t\t\t\t\tif (contextArg.type === \"StringLiteral\") {\n\t\t\t\t\t\tcontext = contextArg.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockId(path);\n\n\t\t\t\tconst isDuplicate = collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === text &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tcollectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tJSXElement(path: NodePath<JSXElement>, state: PluginPass) {\n\t\t\tconst openingElement = path.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\t\t\tconst loc = path.node.loc;\n\n\t\t\tif (isTrans(name)) {\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst filename = getFilename(state);\n\t\t\t\t\tconst locationKey = `${filename}:jsx:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tprocessedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst expressionCounter = { current: 0 };\n\t\t\t\tconst template = extractTransTemplate(\n\t\t\t\t\tpath.node.children,\n\t\t\t\t\texpressionCounter,\n\t\t\t\t);\n\t\t\t\tif (!template) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet context: string | null = null;\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"context\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value?.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tcontext = attr.value.value;\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tattr.value?.type === \"JSXExpressionContainer\" &&\n\t\t\t\t\t\t\tattr.value.expression.type === \"StringLiteral\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcontext = attr.value.expression.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockIdForJSX(path);\n\n\t\t\t\tconst isDuplicate = collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === template &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text: template };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tcollectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isCTContextBlock(name)) {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value && attr.value.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tconst id = attr.value.value;\n\t\t\t\t\t\t\tconst isDuplicate = collectedContextBlocks.some(\n\t\t\t\t\t\t\t\t(b) => b.id === id,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\t\t\t\tcollectedContextBlocks.push({ id });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createExtractionVisitorWithState(): PluginObj<BabelPluginState>[\"visitor\"] {\n\treturn {\n\t\tVariableDeclarator(\n\t\t\tpath: NodePath<VariableDeclarator>,\n\t\t\tstate: BabelPluginState,\n\t\t) {\n\t\t\tconst init = path.node.init;\n\t\t\tconst id = path.node.id;\n\n\t\t\tif (\n\t\t\t\tinit &&\n\t\t\t\tinit.type === \"CallExpression\" &&\n\t\t\t\tinit.callee.type === \"Identifier\" &&\n\t\t\t\tinit.callee.name === \"useCt\"\n\t\t\t) {\n\t\t\t\tif (id.type === \"Identifier\") {\n\t\t\t\t\tstate.ctVariableNames.add(id.name);\n\t\t\t\t} else if (id.type === \"ObjectPattern\") {\n\t\t\t\t\tfor (const prop of id.properties) {\n\t\t\t\t\t\tif (prop.type === \"ObjectProperty\") {\n\t\t\t\t\t\t\tif (prop.value.type === \"Identifier\") {\n\t\t\t\t\t\t\t\tstate.ctVariableNames.add(prop.value.name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tprop.type === \"RestElement\" &&\n\t\t\t\t\t\t\tprop.argument.type === \"Identifier\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tstate.ctVariableNames.add(prop.argument.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tCallExpression(path: NodePath<CallExpression>, state: BabelPluginState) {\n\t\t\tconst callee = path.node.callee;\n\n\t\t\tif (\n\t\t\t\tcallee.type === \"Identifier\" &&\n\t\t\t\tstate.ctVariableNames.has(callee.name)\n\t\t\t) {\n\t\t\t\tconst loc = path.node.loc;\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst filename = getFilename(state);\n\t\t\t\t\tconst locationKey = `${filename}:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (state.processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tstate.processedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst args = path.node.arguments;\n\n\t\t\t\tif (args.length === 0) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst textArg = args[0];\n\n\t\t\t\tif (textArg.type !== \"StringLiteral\") {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ciao-tools] Warning: ${callee.name}() called with non-string literal at ${formatLocation(state, loc?.start)}. Only string literals are supported. Skipping dynamic string.`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst text = textArg.value;\n\t\t\t\tlet context: string | null = null;\n\n\t\t\t\tif (args.length >= 2) {\n\t\t\t\t\tconst contextArg = args[1];\n\t\t\t\t\tif (contextArg.type === \"StringLiteral\") {\n\t\t\t\t\t\tcontext = contextArg.value;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockId(path);\n\n\t\t\t\tconst isDuplicate = state.collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === text &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tstate.collectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tJSXElement(path: NodePath<JSXElement>, state: BabelPluginState) {\n\t\t\tconst openingElement = path.node.openingElement;\n\t\t\tconst name = openingElement.name;\n\t\t\tconst loc = path.node.loc;\n\n\t\t\tif (isTrans(name)) {\n\t\t\t\tif (loc) {\n\t\t\t\t\tconst filename = getFilename(state);\n\t\t\t\t\tconst locationKey = `${filename}:jsx:${loc.start.line}:${loc.start.column}`;\n\t\t\t\t\tif (state.processedLocations.has(locationKey)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tstate.processedLocations.add(locationKey);\n\t\t\t\t}\n\n\t\t\t\tconst expressionCounter = { current: 0 };\n\t\t\t\tconst template = extractTransTemplate(\n\t\t\t\t\tpath.node.children,\n\t\t\t\t\texpressionCounter,\n\t\t\t\t);\n\t\t\t\tif (!template) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet context: string | null = null;\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"context\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value?.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tcontext = attr.value.value;\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tattr.value?.type === \"JSXExpressionContainer\" &&\n\t\t\t\t\t\t\tattr.value.expression.type === \"StringLiteral\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcontext = attr.value.expression.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst parentContextBlockId = getContextBlockIdForJSX(path);\n\n\t\t\t\tconst isDuplicate = state.collectedStrings.some(\n\t\t\t\t\t(s) =>\n\t\t\t\t\t\ts.text === template &&\n\t\t\t\t\t\ts.context === (context ?? undefined) &&\n\t\t\t\t\t\ts.parentContextBlockId === (parentContextBlockId ?? undefined),\n\t\t\t\t);\n\n\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\tconst entry: TranslatableString = { text: template };\n\t\t\t\t\tif (context) {\n\t\t\t\t\t\tentry.context = context;\n\t\t\t\t\t}\n\t\t\t\t\tif (parentContextBlockId) {\n\t\t\t\t\t\tentry.parentContextBlockId = parentContextBlockId;\n\t\t\t\t\t}\n\t\t\t\t\tstate.collectedStrings.push(entry);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isCTContextBlock(name)) {\n\t\t\t\tfor (const attr of openingElement.attributes) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tattr.type === \"JSXAttribute\" &&\n\t\t\t\t\t\tattr.name.type === \"JSXIdentifier\" &&\n\t\t\t\t\t\tattr.name.name === \"id\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (attr.value && attr.value.type === \"StringLiteral\") {\n\t\t\t\t\t\t\tconst id = attr.value.value;\n\t\t\t\t\t\t\tconst isDuplicate = state.collectedContextBlocks.some(\n\t\t\t\t\t\t\t\t(b) => b.id === id,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (!isDuplicate) {\n\t\t\t\t\t\t\t\tstate.collectedContextBlocks.push({ id });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createExtractionPlugin(\n\toptions: ExtractionPluginOptions = {},\n): () => PluginObj {\n\tconst { onComplete } = options;\n\tconst collectedStrings: TranslatableString[] = [];\n\tconst collectedContextBlocks: ContextBlock[] = [];\n\tconst ctVariableNames = new Set<string>();\n\tconst processedLocations = new Set<string>();\n\n\treturn (): PluginObj => ({\n\t\tname: \"@ciao-tools/babel-extraction\",\n\t\tvisitor: createExtractionVisitor(\n\t\t\tcollectedStrings,\n\t\t\tcollectedContextBlocks,\n\t\t\tctVariableNames,\n\t\t\tprocessedLocations,\n\t\t),\n\t\tpost() {\n\t\t\tif (onComplete) {\n\t\t\t\tconst result: ExtractionResult = {\n\t\t\t\t\tstrings: [...collectedStrings],\n\t\t\t\t\tcontextBlocks: [...collectedContextBlocks],\n\t\t\t\t};\n\t\t\t\tonComplete(result);\n\t\t\t}\n\t\t},\n\t});\n}\n\nexport function getCollectedData(\n\tcollectedStrings: TranslatableString[],\n\tcollectedContextBlocks: ContextBlock[],\n): ExtractionResult {\n\treturn {\n\t\tstrings: [...collectedStrings],\n\t\tcontextBlocks: [...collectedContextBlocks],\n\t};\n}\n","import type { PluginObj, PluginPass } from \"@babel/core\";\nimport type {\n\tBuildSchema,\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n} from \"./types\";\nimport { createExtractionVisitorWithState } from \"./visitor\";\n\nexport type {\n\tBuildSchema,\n\tContextBlock,\n\tExtractionPluginOptions,\n\tExtractionResult,\n\tTranslatableString,\n};\nexport { createExtractionPlugin } from \"./visitor\";\n\nexport interface BabelPluginState extends PluginPass {\n\tcollectedStrings: TranslatableString[];\n\tcollectedContextBlocks: ContextBlock[];\n\tctVariableNames: Set<string>;\n\tprocessedLocations: Set<string>;\n}\n\nexport default function ciaoToolsBabelPlugin(): PluginObj<BabelPluginState> {\n\treturn {\n\t\tname: \"@ciao-tools/babel\",\n\t\tpre() {\n\t\t\tthis.collectedStrings = [];\n\t\t\tthis.collectedContextBlocks = [];\n\t\t\tthis.ctVariableNames = new Set<string>();\n\t\t\tthis.processedLocations = new Set<string>();\n\t\t},\n\t\tvisitor: createExtractionVisitorWithState(),\n\t};\n}\n\nexport function buildSchema(result: ExtractionResult): BuildSchema {\n\treturn {\n\t\tversion: \"1.0\",\n\t\tstrings: result.strings,\n\t\tcontextBlocks: result.contextBlocks,\n\t\tmetadata: {\n\t\t\tgeneratedAt: new Date().toISOString(),\n\t\t\ttotalStrings: result.strings.length,\n\t\t\ttotalContextBlocks: result.contextBlocks.length,\n\t\t},\n\t};\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "experimental-ciao-babel",
3
- "version": "1.1.10",
3
+ "version": "1.1.11",
4
4
  "type": "module",
5
5
  "description": "Babel plugin for ciao-tools - extracts translatable strings at build time",
6
6
  "main": "./dist/index.cjs",
@@ -51,6 +51,7 @@
51
51
  },
52
52
  "devDependencies": {
53
53
  "@babel/core": "^7.24.0",
54
- "@types/babel__core": "^7.20.5"
54
+ "@types/babel__core": "^7.20.5",
55
+ "experimental-ciao-oxc": "workspace:*"
55
56
  }
56
57
  }