experimental-ciao-babel 1.1.9 → 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 +122 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +9 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +122 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
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
|
|
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
|
|
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
|
|
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
|
|
123
|
+
if (isTrans(name)) {
|
|
104
124
|
if (loc) {
|
|
105
|
-
const locationKey =
|
|
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
|
|
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
|
-
|
|
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) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -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":"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"}
|
|
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
|
-
|
|
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
|
package/dist/index.d.cts.map
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
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
|
package/dist/index.d.mts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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
|
|
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
|
|
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
|
|
121
|
+
if (isTrans(name)) {
|
|
102
122
|
if (loc) {
|
|
103
|
-
const locationKey =
|
|
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
|
|
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
|
-
|
|
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) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -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":"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"}
|
|
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.
|
|
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
|
}
|