experimental-ciao-babel 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # @ciao-tools/babel
2
+
3
+ Babel plugin for Ciao Tools - extracts translatable strings at build time.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -D @ciao-tools/babel
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Add to your Babel config:
14
+
15
+ ```js
16
+ // babel.config.js
17
+ module.exports = {
18
+ plugins: ["@ciao-tools/babel"],
19
+ };
20
+ ```
21
+
22
+ Or with Vite:
23
+
24
+ ```ts
25
+ // vite.config.ts
26
+ import { defineConfig } from "vite";
27
+ import react from "@vitejs/plugin-react";
28
+
29
+ export default defineConfig({
30
+ plugins: [
31
+ react({
32
+ babel: {
33
+ plugins: ["@ciao-tools/babel"],
34
+ },
35
+ }),
36
+ ],
37
+ });
38
+ ```
39
+
40
+ ## What it extracts
41
+
42
+ The plugin scans your code for:
43
+
44
+ - `ct()` function calls with string literals
45
+ - `<CTContextBlock id="...">` components for context grouping
46
+
47
+ ```tsx
48
+ // These strings are extracted:
49
+ ct("Hello, world!");
50
+ ct("Welcome back, {name}", { name: userName });
51
+
52
+ <CTContextBlock id="checkout-page">
53
+ <p>{ct("Review your order")}</p>
54
+ <p>{ct("Proceed to payment")}</p>
55
+ </CTContextBlock>
56
+ ```
57
+
58
+ ## Exports
59
+
60
+ - `default` - Babel plugin function
61
+ - `buildSchema()` - Generate schema from extraction result
62
+ - `createExtractionPlugin()` - Create plugin with custom options
63
+
64
+ ## Documentation
65
+
66
+ See [docs.ciao-tools.com/babel](https://docs.ciao-tools.com/api/babel) for full documentation.
67
+
68
+ ## License
69
+
70
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,180 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ //#region src/visitor.ts
4
+ function formatLocation(state, loc) {
5
+ const filename = state.filename || state.file?.opts?.filename || "unknown";
6
+ if (loc) return `${filename}:${loc.line}:${loc.column}`;
7
+ return filename;
8
+ }
9
+ function extractTransTemplate(children) {
10
+ let elementIndex = 0;
11
+ function processNode(node) {
12
+ if (node.type === "JSXText") return node.value.replace(/\s+/g, " ");
13
+ if (node.type === "JSXExpressionContainer") {
14
+ const expr = node.expression;
15
+ if (expr.type === "StringLiteral") return expr.value;
16
+ return "";
17
+ }
18
+ if (node.type === "JSXElement") {
19
+ const elem = node;
20
+ const idx = elementIndex++;
21
+ return `<${idx}>${elem.children.map(processNode).join("")}</${idx}>`;
22
+ }
23
+ if (node.type === "JSXFragment") return node.children.map(processNode).join("");
24
+ return "";
25
+ }
26
+ return children.map(processNode).join("").trim();
27
+ }
28
+ function getContextBlockIdForJSX(path) {
29
+ let current = path.parentPath;
30
+ while (current) {
31
+ if (current.isJSXElement()) {
32
+ const openingElement = current.node.openingElement;
33
+ const name = openingElement.name;
34
+ if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
35
+ 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
+ }
37
+ }
38
+ current = current.parentPath;
39
+ }
40
+ return null;
41
+ }
42
+ function getContextBlockId(path) {
43
+ let current = path.parentPath;
44
+ while (current) {
45
+ if (current.isJSXElement()) {
46
+ const openingElement = current.node.openingElement;
47
+ const name = openingElement.name;
48
+ if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
49
+ 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
+ }
51
+ }
52
+ current = current.parentPath;
53
+ }
54
+ return null;
55
+ }
56
+ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVariableNames, processedLocations) {
57
+ return {
58
+ VariableDeclarator(path) {
59
+ const init = path.node.init;
60
+ const id = path.node.id;
61
+ if (init && init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "useCt") {
62
+ if (id.type === "Identifier") ctVariableNames.add(id.name);
63
+ }
64
+ },
65
+ CallExpression(path, state) {
66
+ const callee = path.node.callee;
67
+ if (callee.type === "Identifier" && ctVariableNames.has(callee.name)) {
68
+ const loc = path.node.loc;
69
+ if (loc) {
70
+ const locationKey = `${loc.start.line}:${loc.start.column}`;
71
+ if (processedLocations.has(locationKey)) return;
72
+ processedLocations.add(locationKey);
73
+ }
74
+ const args = path.node.arguments;
75
+ if (args.length === 0) {
76
+ console.warn(`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`);
77
+ return;
78
+ }
79
+ const textArg = args[0];
80
+ if (textArg.type !== "StringLiteral") {
81
+ 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.`);
82
+ return;
83
+ }
84
+ const text = textArg.value;
85
+ let context = null;
86
+ if (args.length >= 2) {
87
+ const contextArg = args[1];
88
+ if (contextArg.type === "StringLiteral") context = contextArg.value;
89
+ }
90
+ const parentContextBlockId = getContextBlockId(path);
91
+ if (!collectedStrings.some((s) => s.text === text && s.context === (context ?? void 0) && s.parentContextBlockId === (parentContextBlockId ?? void 0))) {
92
+ const entry = { text };
93
+ if (context) entry.context = context;
94
+ if (parentContextBlockId) entry.parentContextBlockId = parentContextBlockId;
95
+ collectedStrings.push(entry);
96
+ }
97
+ }
98
+ },
99
+ JSXElement(path, state) {
100
+ const openingElement = path.node.openingElement;
101
+ const name = openingElement.name;
102
+ const loc = path.node.loc;
103
+ if (name.type === "JSXIdentifier" && name.name === "Trans") {
104
+ if (loc) {
105
+ const locationKey = `jsx:${loc.start.line}:${loc.start.column}`;
106
+ if (processedLocations.has(locationKey)) return;
107
+ processedLocations.add(locationKey);
108
+ }
109
+ const template = extractTransTemplate(path.node.children);
110
+ if (!template) return;
111
+ let context = null;
112
+ for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "context") {
113
+ if (attr.value?.type === "StringLiteral") context = attr.value.value;
114
+ else if (attr.value?.type === "JSXExpressionContainer" && attr.value.expression.type === "StringLiteral") context = attr.value.expression.value;
115
+ break;
116
+ }
117
+ const parentContextBlockId = getContextBlockIdForJSX(path);
118
+ if (!collectedStrings.some((s) => s.text === template && s.context === (context ?? void 0) && s.parentContextBlockId === (parentContextBlockId ?? void 0))) {
119
+ const entry = { text: template };
120
+ if (context) entry.context = context;
121
+ if (parentContextBlockId) entry.parentContextBlockId = parentContextBlockId;
122
+ collectedStrings.push(entry);
123
+ }
124
+ }
125
+ if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
126
+ for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id") {
127
+ if (attr.value && attr.value.type === "StringLiteral") {
128
+ const id = attr.value.value;
129
+ if (!collectedContextBlocks.some((b) => b.id === id)) collectedContextBlocks.push({ id });
130
+ } else console.warn(`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`);
131
+ break;
132
+ }
133
+ }
134
+ }
135
+ };
136
+ }
137
+ function createExtractionPlugin(options = {}) {
138
+ const { onComplete } = options;
139
+ const collectedStrings = [];
140
+ const collectedContextBlocks = [];
141
+ const ctVariableNames = /* @__PURE__ */ new Set();
142
+ const processedLocations = /* @__PURE__ */ new Set();
143
+ return () => ({
144
+ name: "@ciao-tools/babel-extraction",
145
+ visitor: createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVariableNames, processedLocations),
146
+ post() {
147
+ if (onComplete) onComplete({
148
+ strings: [...collectedStrings],
149
+ contextBlocks: [...collectedContextBlocks]
150
+ });
151
+ }
152
+ });
153
+ }
154
+
155
+ //#endregion
156
+ //#region src/index.ts
157
+ function ciaoToolsBabelPlugin() {
158
+ return {
159
+ name: "@ciao-tools/babel",
160
+ visitor: createExtractionVisitor([], [], /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set())
161
+ };
162
+ }
163
+ function buildSchema(result) {
164
+ return {
165
+ version: "1.0",
166
+ strings: result.strings,
167
+ contextBlocks: result.contextBlocks,
168
+ metadata: {
169
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
170
+ totalStrings: result.strings.length,
171
+ totalContextBlocks: result.contextBlocks.length
172
+ }
173
+ };
174
+ }
175
+
176
+ //#endregion
177
+ exports.buildSchema = buildSchema;
178
+ exports.createExtractionPlugin = createExtractionPlugin;
179
+ exports.default = ciaoToolsBabelPlugin;
180
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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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"}
@@ -0,0 +1,38 @@
1
+ import { PluginObj } from "@babel/core";
2
+
3
+ //#region src/types.d.ts
4
+ interface TranslatableString {
5
+ text: string;
6
+ context?: string;
7
+ parentContextBlockId?: string;
8
+ }
9
+ interface ContextBlock {
10
+ id: string;
11
+ }
12
+ interface ExtractionResult {
13
+ strings: TranslatableString[];
14
+ contextBlocks: ContextBlock[];
15
+ }
16
+ interface BuildSchema {
17
+ version: string;
18
+ strings: TranslatableString[];
19
+ contextBlocks: ContextBlock[];
20
+ metadata: {
21
+ generatedAt: string;
22
+ totalStrings: number;
23
+ totalContextBlocks: number;
24
+ };
25
+ }
26
+ interface ExtractionPluginOptions {
27
+ onComplete?: (result: ExtractionResult) => void;
28
+ }
29
+ //#endregion
30
+ //#region src/visitor.d.ts
31
+ declare function createExtractionPlugin(options?: ExtractionPluginOptions): () => PluginObj;
32
+ //#endregion
33
+ //#region src/index.d.ts
34
+ declare function ciaoToolsBabelPlugin(): PluginObj;
35
+ declare function buildSchema(result: ExtractionResult): BuildSchema;
36
+ //#endregion
37
+ export { type BuildSchema, type ContextBlock, type ExtractionPluginOptions, type ExtractionResult, type TranslatableString, buildSchema, createExtractionPlugin, ciaoToolsBabelPlugin as default };
38
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/visitor.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;UAAiB,kBAAA;;;EAAA,oBAAA,CAAkB,EAAA,MAAA;AAMnC;AAIiB,UAJA,YAAA,CAIgB;EAKhB,EAAA,EAAA,MAAA;AAWjB;UAhBiB,gBAAA;WACP;iBACM;ACuRhB;UDpRiB,WAAA;;WAEP;EEEc,aAAA,EFDR,YEC4B,EAAA;EAiB5B,QAAA,EAAA;;;;;;UFVC,uBAAA;wBACM;;;;AA3BN,iBCmSD,sBAAA,CDnSmB,OAAA,CAAA,ECoSzB,uBDpSyB,CAAA,EAAA,GAAA,GCqS1B,SDrS0B;;;AAMlB,iBEaO,oBAAA,CAAA,CFbK,EEamB,SFbnB;AAIZ,iBE0BD,WAAA,CFzBN,MAAA,EEyB0B,gBFxBpB,CAAA,EEwBuC,WFxB3B"}
@@ -0,0 +1,38 @@
1
+ import { PluginObj } from "@babel/core";
2
+
3
+ //#region src/types.d.ts
4
+ interface TranslatableString {
5
+ text: string;
6
+ context?: string;
7
+ parentContextBlockId?: string;
8
+ }
9
+ interface ContextBlock {
10
+ id: string;
11
+ }
12
+ interface ExtractionResult {
13
+ strings: TranslatableString[];
14
+ contextBlocks: ContextBlock[];
15
+ }
16
+ interface BuildSchema {
17
+ version: string;
18
+ strings: TranslatableString[];
19
+ contextBlocks: ContextBlock[];
20
+ metadata: {
21
+ generatedAt: string;
22
+ totalStrings: number;
23
+ totalContextBlocks: number;
24
+ };
25
+ }
26
+ interface ExtractionPluginOptions {
27
+ onComplete?: (result: ExtractionResult) => void;
28
+ }
29
+ //#endregion
30
+ //#region src/visitor.d.ts
31
+ declare function createExtractionPlugin(options?: ExtractionPluginOptions): () => PluginObj;
32
+ //#endregion
33
+ //#region src/index.d.ts
34
+ declare function ciaoToolsBabelPlugin(): PluginObj;
35
+ declare function buildSchema(result: ExtractionResult): BuildSchema;
36
+ //#endregion
37
+ export { type BuildSchema, type ContextBlock, type ExtractionPluginOptions, type ExtractionResult, type TranslatableString, buildSchema, createExtractionPlugin, ciaoToolsBabelPlugin as default };
38
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/visitor.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;UAAiB,kBAAA;;;EAAA,oBAAA,CAAkB,EAAA,MAAA;AAMnC;AAIiB,UAJA,YAAA,CAIgB;EAKhB,EAAA,EAAA,MAAA;AAWjB;UAhBiB,gBAAA;WACP;iBACM;ACuRhB;UDpRiB,WAAA;;WAEP;EEEc,aAAA,EFDR,YEC4B,EAAA;EAiB5B,QAAA,EAAA;;;;;;UFVC,uBAAA;wBACM;;;;AA3BN,iBCmSD,sBAAA,CDnSmB,OAAA,CAAA,ECoSzB,uBDpSyB,CAAA,EAAA,GAAA,GCqS1B,SDrS0B;;;AAMlB,iBEaO,oBAAA,CAAA,CFbK,EEamB,SFbnB;AAIZ,iBE0BD,WAAA,CFzBN,MAAA,EEyB0B,gBFxBpB,CAAA,EEwBuC,WFxB3B"}
package/dist/index.mjs ADDED
@@ -0,0 +1,176 @@
1
+ //#region src/visitor.ts
2
+ function formatLocation(state, loc) {
3
+ const filename = state.filename || state.file?.opts?.filename || "unknown";
4
+ if (loc) return `${filename}:${loc.line}:${loc.column}`;
5
+ return filename;
6
+ }
7
+ function extractTransTemplate(children) {
8
+ let elementIndex = 0;
9
+ function processNode(node) {
10
+ if (node.type === "JSXText") return node.value.replace(/\s+/g, " ");
11
+ if (node.type === "JSXExpressionContainer") {
12
+ const expr = node.expression;
13
+ if (expr.type === "StringLiteral") return expr.value;
14
+ return "";
15
+ }
16
+ if (node.type === "JSXElement") {
17
+ const elem = node;
18
+ const idx = elementIndex++;
19
+ return `<${idx}>${elem.children.map(processNode).join("")}</${idx}>`;
20
+ }
21
+ if (node.type === "JSXFragment") return node.children.map(processNode).join("");
22
+ return "";
23
+ }
24
+ return children.map(processNode).join("").trim();
25
+ }
26
+ function getContextBlockIdForJSX(path) {
27
+ let current = path.parentPath;
28
+ while (current) {
29
+ if (current.isJSXElement()) {
30
+ const openingElement = current.node.openingElement;
31
+ const name = openingElement.name;
32
+ if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
33
+ 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
+ }
35
+ }
36
+ current = current.parentPath;
37
+ }
38
+ return null;
39
+ }
40
+ function getContextBlockId(path) {
41
+ let current = path.parentPath;
42
+ while (current) {
43
+ if (current.isJSXElement()) {
44
+ const openingElement = current.node.openingElement;
45
+ const name = openingElement.name;
46
+ if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
47
+ 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
+ }
49
+ }
50
+ current = current.parentPath;
51
+ }
52
+ return null;
53
+ }
54
+ function createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVariableNames, processedLocations) {
55
+ return {
56
+ VariableDeclarator(path) {
57
+ const init = path.node.init;
58
+ const id = path.node.id;
59
+ if (init && init.type === "CallExpression" && init.callee.type === "Identifier" && init.callee.name === "useCt") {
60
+ if (id.type === "Identifier") ctVariableNames.add(id.name);
61
+ }
62
+ },
63
+ CallExpression(path, state) {
64
+ const callee = path.node.callee;
65
+ if (callee.type === "Identifier" && ctVariableNames.has(callee.name)) {
66
+ const loc = path.node.loc;
67
+ if (loc) {
68
+ const locationKey = `${loc.start.line}:${loc.start.column}`;
69
+ if (processedLocations.has(locationKey)) return;
70
+ processedLocations.add(locationKey);
71
+ }
72
+ const args = path.node.arguments;
73
+ if (args.length === 0) {
74
+ console.warn(`[ciao-tools] Warning: ${callee.name}() called with no arguments at ${formatLocation(state, loc?.start)}`);
75
+ return;
76
+ }
77
+ const textArg = args[0];
78
+ if (textArg.type !== "StringLiteral") {
79
+ 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.`);
80
+ return;
81
+ }
82
+ const text = textArg.value;
83
+ let context = null;
84
+ if (args.length >= 2) {
85
+ const contextArg = args[1];
86
+ if (contextArg.type === "StringLiteral") context = contextArg.value;
87
+ }
88
+ const parentContextBlockId = getContextBlockId(path);
89
+ if (!collectedStrings.some((s) => s.text === text && s.context === (context ?? void 0) && s.parentContextBlockId === (parentContextBlockId ?? void 0))) {
90
+ const entry = { text };
91
+ if (context) entry.context = context;
92
+ if (parentContextBlockId) entry.parentContextBlockId = parentContextBlockId;
93
+ collectedStrings.push(entry);
94
+ }
95
+ }
96
+ },
97
+ JSXElement(path, state) {
98
+ const openingElement = path.node.openingElement;
99
+ const name = openingElement.name;
100
+ const loc = path.node.loc;
101
+ if (name.type === "JSXIdentifier" && name.name === "Trans") {
102
+ if (loc) {
103
+ const locationKey = `jsx:${loc.start.line}:${loc.start.column}`;
104
+ if (processedLocations.has(locationKey)) return;
105
+ processedLocations.add(locationKey);
106
+ }
107
+ const template = extractTransTemplate(path.node.children);
108
+ if (!template) return;
109
+ let context = null;
110
+ for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "context") {
111
+ if (attr.value?.type === "StringLiteral") context = attr.value.value;
112
+ else if (attr.value?.type === "JSXExpressionContainer" && attr.value.expression.type === "StringLiteral") context = attr.value.expression.value;
113
+ break;
114
+ }
115
+ const parentContextBlockId = getContextBlockIdForJSX(path);
116
+ if (!collectedStrings.some((s) => s.text === template && s.context === (context ?? void 0) && s.parentContextBlockId === (parentContextBlockId ?? void 0))) {
117
+ const entry = { text: template };
118
+ if (context) entry.context = context;
119
+ if (parentContextBlockId) entry.parentContextBlockId = parentContextBlockId;
120
+ collectedStrings.push(entry);
121
+ }
122
+ }
123
+ if (name.type === "JSXIdentifier" && name.name === "CTContextBlock") {
124
+ for (const attr of openingElement.attributes) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "id") {
125
+ if (attr.value && attr.value.type === "StringLiteral") {
126
+ const id = attr.value.value;
127
+ if (!collectedContextBlocks.some((b) => b.id === id)) collectedContextBlocks.push({ id });
128
+ } else console.warn(`[ciao-tools] Warning: CTContextBlock id must be a string literal at ${formatLocation(state, loc?.start)}`);
129
+ break;
130
+ }
131
+ }
132
+ }
133
+ };
134
+ }
135
+ function createExtractionPlugin(options = {}) {
136
+ const { onComplete } = options;
137
+ const collectedStrings = [];
138
+ const collectedContextBlocks = [];
139
+ const ctVariableNames = /* @__PURE__ */ new Set();
140
+ const processedLocations = /* @__PURE__ */ new Set();
141
+ return () => ({
142
+ name: "@ciao-tools/babel-extraction",
143
+ visitor: createExtractionVisitor(collectedStrings, collectedContextBlocks, ctVariableNames, processedLocations),
144
+ post() {
145
+ if (onComplete) onComplete({
146
+ strings: [...collectedStrings],
147
+ contextBlocks: [...collectedContextBlocks]
148
+ });
149
+ }
150
+ });
151
+ }
152
+
153
+ //#endregion
154
+ //#region src/index.ts
155
+ function ciaoToolsBabelPlugin() {
156
+ return {
157
+ name: "@ciao-tools/babel",
158
+ visitor: createExtractionVisitor([], [], /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set())
159
+ };
160
+ }
161
+ function buildSchema(result) {
162
+ return {
163
+ version: "1.0",
164
+ strings: result.strings,
165
+ contextBlocks: result.contextBlocks,
166
+ metadata: {
167
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
168
+ totalStrings: result.strings.length,
169
+ totalContextBlocks: result.contextBlocks.length
170
+ }
171
+ };
172
+ }
173
+
174
+ //#endregion
175
+ export { buildSchema, createExtractionPlugin, ciaoToolsBabelPlugin as default };
176
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "experimental-ciao-babel",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Babel plugin for ciao-tools - extracts translatable strings at build time",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.mts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.mts",
12
+ "import": "./dist/index.mjs",
13
+ "require": {
14
+ "types": "./dist/index.d.cts",
15
+ "default": "./dist/index.cjs"
16
+ }
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsdown",
24
+ "dev": "tsdown --watch",
25
+ "clean": "rm -rf dist",
26
+ "test": "bun test"
27
+ },
28
+ "keywords": [
29
+ "ciao-tools",
30
+ "babel",
31
+ "i18n",
32
+ "translation",
33
+ "extraction"
34
+ ],
35
+ "license": "MIT",
36
+ "author": "Ciao Tools",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/ciao-tools/core.git",
40
+ "directory": "packages/babel"
41
+ },
42
+ "homepage": "https://docs.ciao-tools.com",
43
+ "bugs": {
44
+ "url": "https://github.com/ciao-tools/core/issues"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "peerDependencies": {
50
+ "@babel/core": "^7.0.0"
51
+ },
52
+ "devDependencies": {
53
+ "@babel/core": "^7.24.0",
54
+ "@types/babel__core": "^7.20.5"
55
+ }
56
+ }