@intlayer/babel 8.10.0 → 8.10.1
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/cjs/extractContent/babelProcessor.cjs +48 -1
- package/dist/cjs/extractContent/babelProcessor.cjs.map +1 -1
- package/dist/cjs/extractContent/utils/shouldExtract.cjs +1 -1
- package/dist/cjs/extractContent/utils/shouldExtract.cjs.map +1 -1
- package/dist/esm/extractContent/babelProcessor.mjs +48 -1
- package/dist/esm/extractContent/babelProcessor.mjs.map +1 -1
- package/dist/esm/extractContent/utils/shouldExtract.mjs +1 -1
- package/dist/esm/extractContent/utils/shouldExtract.mjs.map +1 -1
- package/dist/types/extractContent/babelProcessor.d.ts.map +1 -1
- package/dist/types/extractContent/utils/extractDictionaryKey.d.ts +2 -2
- package/package.json +10 -10
|
@@ -244,7 +244,54 @@ const extractBabelContentForComponents = (ast, fileCode, existingKeys, defaultKe
|
|
|
244
244
|
if (_babel_types.isIdentifier(parent.node.callee.object) && parent.node.callee.object.name === "console" && _babel_types.isIdentifier(parent.node.callee.property) && parent.node.callee.property.name === "log") return;
|
|
245
245
|
}
|
|
246
246
|
if (parent.isObjectProperty() && parent.node.key === path.node) return;
|
|
247
|
-
|
|
247
|
+
const TECHNICAL_KEYS = new Set([
|
|
248
|
+
"icon",
|
|
249
|
+
"className",
|
|
250
|
+
"class",
|
|
251
|
+
"id",
|
|
252
|
+
"type",
|
|
253
|
+
"variant",
|
|
254
|
+
"color",
|
|
255
|
+
"theme",
|
|
256
|
+
"size",
|
|
257
|
+
"align",
|
|
258
|
+
"placement",
|
|
259
|
+
"target",
|
|
260
|
+
"rel",
|
|
261
|
+
"method",
|
|
262
|
+
"mode",
|
|
263
|
+
"direction",
|
|
264
|
+
"orientation",
|
|
265
|
+
"scope",
|
|
266
|
+
"role",
|
|
267
|
+
"lang",
|
|
268
|
+
"locale",
|
|
269
|
+
"href",
|
|
270
|
+
"src",
|
|
271
|
+
"width",
|
|
272
|
+
"height",
|
|
273
|
+
"as",
|
|
274
|
+
"to",
|
|
275
|
+
"key",
|
|
276
|
+
"value",
|
|
277
|
+
"defaultValue",
|
|
278
|
+
"prop",
|
|
279
|
+
"property",
|
|
280
|
+
"state",
|
|
281
|
+
"action",
|
|
282
|
+
"event",
|
|
283
|
+
"handler",
|
|
284
|
+
"callback",
|
|
285
|
+
"url",
|
|
286
|
+
"uri",
|
|
287
|
+
"path",
|
|
288
|
+
"route",
|
|
289
|
+
"slug",
|
|
290
|
+
"endpoint",
|
|
291
|
+
"headers",
|
|
292
|
+
"contentType"
|
|
293
|
+
]);
|
|
294
|
+
if (parent.isObjectProperty() && _babel_types.isIdentifier(parent.node.key) && TECHNICAL_KEYS.has(parent.node.key.name)) return;
|
|
248
295
|
if (parent.isMemberExpression() && parent.node.property === path.node) return;
|
|
249
296
|
const componentKey = getComponentKeyForPath(path);
|
|
250
297
|
const key = require_extractContent_utils_getOrGenerateKey.getOrGenerateKey(text.trim(), componentKey, existingKeys, extractedContent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"babelProcessor.cjs","names":["_traverse","t","shouldExtract","getOrGenerateKey","getExistingIntlayerInfo","resolveDictionaryKey","getComponentName","ATTRIBUTES_TO_EXTRACT"],"sources":["../../../src/extractContent/babelProcessor.ts"],"sourcesContent":["import _traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { resolveDictionaryKey } from '../extractContent/utils';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n getComponentName,\n getExistingIntlayerInfo,\n getOrGenerateKey,\n shouldExtract,\n} from './utils';\n\nexport type BabelReplacement = {\n path: NodePath;\n key: string;\n type:\n | 'jsx-text'\n | 'jsx-attribute'\n | 'string-literal'\n | 'jsx-insertion'\n | 'jsx-text-combined'\n | 'template-literal';\n componentKey: string;\n childrenToReplace?: t.Node[];\n variables?: string[];\n};\n\n// CJS/ESM interop: @babel/traverse exports its function as `.default` in CJS bundles\nconst traverse = (\n typeof _traverse === 'function' ? _traverse : (_traverse as any).default\n) as typeof _traverse;\n\n/**\n * Handles JSX insertions (elements with multiple children, including expressions).\n * Replaces complex JSX structures with variable-based translations.\n */\nexport const handleJsxInsertionBabel = (\n path: NodePath<t.JSXElement | t.JSXFragment>,\n fileCode: string,\n existingKeys: Set<string>,\n getComponentKeyForPath: (path: NodePath) => string,\n extractedContent: Record<string, Record<string, string>>,\n replacements: BabelReplacement[],\n handledNodes: Set<t.Node>\n): boolean => {\n const children = path.node.children;\n\n if (children.length <= 1) return false;\n\n const parts: {\n type: 'text' | 'var';\n value: string;\n originalExpr?: string;\n }[] = [];\n let hasSignificantText = false;\n let hasVariables = false;\n\n for (const child of children) {\n if (t.isJSXText(child)) {\n const text = child.value;\n\n if (text.trim().length > 0) hasSignificantText = true;\n\n parts.push({ type: 'text', value: text });\n } else if (t.isJSXExpressionContainer(child)) {\n if (t.isJSXEmptyExpression(child.expression)) {\n parts.push({ type: 'text', value: '' });\n } else {\n const expr = child.expression;\n\n if (t.isIdentifier(expr)) {\n parts.push({\n type: 'var',\n value: expr.name,\n originalExpr: expr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n\n parts.push({ type: 'var', value: varName, originalExpr: code });\n\n hasVariables = true;\n } else if (t.isTemplateLiteral(expr)) {\n for (let i = 0; i < expr.quasis.length; i++) {\n parts.push({ type: 'text', value: expr.quasis[i].value.raw });\n if (i < expr.expressions.length) {\n const subExpr = expr.expressions[i];\n if (t.isIdentifier(subExpr)) {\n parts.push({\n type: 'var',\n value: subExpr.name,\n originalExpr: subExpr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(subExpr)) {\n const code = fileCode.substring(subExpr.start!, subExpr.end!);\n const varName = t.isIdentifier(subExpr.property)\n ? subExpr.property.name\n : 'var';\n parts.push({ type: 'var', value: varName, originalExpr: code });\n hasVariables = true;\n } else {\n return false;\n }\n }\n }\n } else {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n\n if (!hasSignificantText) return false;\n\n let combinedString = '';\n for (const part of parts) {\n if (part.type === 'var') combinedString += `{{${part.value}}}`;\n else combinedString += part.value;\n }\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (shouldExtract(cleanString)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const varMap = parts\n .filter((part) => part.type === 'var')\n .map((part) => `${part.value}: ${part.originalExpr}`);\n const uniqueVars = Array.from(new Set(varMap));\n\n if (hasVariables) {\n replacements.push({\n path,\n key,\n type: 'jsx-insertion',\n componentKey,\n childrenToReplace: children,\n variables: uniqueVars,\n });\n } else {\n replacements.push({\n path,\n key,\n type: 'jsx-text-combined',\n componentKey,\n childrenToReplace: children,\n });\n }\n\n children.forEach((child) => {\n handledNodes.add(child);\n });\n return true;\n }\n\n return false;\n};\n\n/**\n * Traverses the AST to identify components and extract content.\n * Returns extraction results and metadata about which components need Intlayer hooks.\n */\nexport const extractBabelContentForComponents = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n defaultKey: string = 'default',\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, Record<string, string>>;\n replacements: BabelReplacement[];\n componentsNeedingHooks: Set<NodePath>;\n componentKeyMap: Map<t.Node, string>;\n componentPaths: NodePath[];\n hookMap: Map<t.Node, 'useIntlayer' | 'getIntlayer'>;\n isSolid: boolean;\n} => {\n const extractedContent: Record<string, Record<string, string>> = {};\n const replacements: BabelReplacement[] = [];\n const handledNodes = new Set<t.Node>();\n const componentKeyMap = new Map<t.Node, string>();\n const hookMap = new Map<t.Node, 'useIntlayer' | 'getIntlayer'>();\n const usedKeysInFile = new Set<string>();\n let globalFileKey: string | undefined;\n\n const componentPaths: NodePath[] = [];\n\n traverse(ast, {\n Program(path) {\n componentPaths.push(path);\n },\n FunctionDeclaration(path) {\n componentPaths.push(path);\n },\n ArrowFunctionExpression(path) {\n componentPaths.push(path);\n },\n FunctionExpression(path) {\n componentPaths.push(path);\n },\n });\n\n // Pre-scan non-Program paths to collect their existing dictionary keys before the\n // Program scope is assigned. Without this, Program is processed first (depth-first\n // traversal) and creates a new file-path-derived key even when a child component\n // already declares a specific dictionary (e.g. useIntlayer('dashboard-sidebar')).\n for (const path of componentPaths) {\n if (path.isProgram()) continue;\n const existingInfo = getExistingIntlayerInfo(path);\n if (existingInfo) {\n usedKeysInFile.add(existingInfo.key);\n }\n }\n\n for (const path of componentPaths) {\n const existingInfo = getExistingIntlayerInfo(path);\n\n if (existingInfo) {\n componentKeyMap.set(path.node, existingInfo.key);\n usedKeysInFile.add(existingInfo.key);\n hookMap.set(path.node, existingInfo.hook);\n } else {\n if (path.isProgram()) {\n if (!globalFileKey) {\n // Reuse the dominant existing key from child components so that\n // module-level strings join the same dictionary rather than\n // creating a new file-path-derived one (e.g. 'route').\n const dominantKey =\n usedKeysInFile.size > 0 ? [...usedKeysInFile][0] : undefined;\n if (dominantKey) {\n globalFileKey = dominantKey;\n } else {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n }\n componentKeyMap.set(path.node, globalFileKey);\n hookMap.set(path.node, 'getIntlayer');\n } else {\n let inheritedKey: string | undefined;\n let parent: NodePath | null = path.parentPath;\n while (parent) {\n if (componentKeyMap.has(parent.node)) {\n inheritedKey = componentKeyMap.get(parent.node);\n break;\n }\n parent = parent.parentPath;\n }\n\n if (!inheritedKey) {\n if (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n inheritedKey = globalFileKey;\n }\n\n componentKeyMap.set(path.node, inheritedKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n const isHook = compName ? /^use[A-Z]/.test(compName) : false;\n hookMap.set(\n path.node,\n isComponent || isHook ? 'useIntlayer' : 'getIntlayer'\n );\n }\n }\n }\n\n const getComponentKeyForPath = (path: NodePath): string => {\n let current: NodePath | null = path;\n while (current) {\n if (componentKeyMap.has(current.node)) {\n return componentKeyMap.get(current.node)!;\n }\n current = current.parentPath;\n }\n return globalFileKey || defaultKey;\n };\n\n traverse(ast, {\n JSXElement(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXFragment(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXText(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (shouldExtract(text)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.replace(/\\s+/g, ' ').trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-text', componentKey });\n }\n },\n JSXAttribute(path) {\n if (handledNodes.has(path.node)) return;\n\n const name = path.node.name.name;\n\n if (\n typeof name !== 'string' ||\n !ATTRIBUTES_TO_EXTRACT.includes(name as any)\n )\n return;\n const value = path.node.value;\n\n if (t.isStringLiteral(value) && shouldExtract(value.value)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n value.value.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-attribute', componentKey });\n }\n },\n StringLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (!shouldExtract(text)) return;\n\n const parent = path.parentPath;\n\n if (\n parent.isImportDeclaration() ||\n parent.isImportSpecifier() ||\n parent.isExportDeclaration()\n )\n return;\n\n if (parent.isJSXAttribute()) return;\n\n if (\n parent.isCallExpression() &&\n t.isMemberExpression(parent.node.callee)\n ) {\n if (\n t.isIdentifier(parent.node.callee.object) &&\n parent.node.callee.object.name === 'console' &&\n t.isIdentifier(parent.node.callee.property) &&\n parent.node.callee.property.name === 'log'\n ) {\n return;\n }\n }\n\n if (parent.isObjectProperty() && parent.node.key === path.node) return;\n\n // Skip string values in named object properties (identifier key, e.g. `icon: 'Globe'`).\n // These are technical mappings, not translatable text. String-keyed properties\n // (e.g. `'translation-status': 'Translation Status'`) are still extracted.\n if (parent.isObjectProperty() && t.isIdentifier(parent.node.key)) return;\n\n if (parent.isMemberExpression() && parent.node.property === path.node)\n return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'string-literal', componentKey });\n },\n TemplateLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const { quasis, expressions } = path.node;\n\n // Build the combined string with placeholders\n let combinedString = '';\n const variables: string[] = [];\n let hasSignificantText = false;\n\n for (let i = 0; i < quasis.length; i++) {\n const text = quasis[i].value.raw;\n combinedString += text;\n if (text.trim().length > 0) hasSignificantText = true;\n\n if (i < expressions.length) {\n const expr = expressions[i];\n if (t.isIdentifier(expr)) {\n combinedString += `{{${expr.name}}}`;\n variables.push(`${expr.name}: ${expr.name}`);\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n combinedString += `{{${varName}}}`;\n variables.push(`${varName}: ${code}`);\n } else {\n // Complex expression in template literal, skip\n return;\n }\n }\n }\n\n if (!hasSignificantText) return;\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (!shouldExtract(cleanString)) return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const uniqueVars = Array.from(new Set(variables));\n\n replacements.push({\n path,\n key,\n type: 'template-literal',\n componentKey,\n variables: uniqueVars,\n });\n },\n });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\n if (componentPath.isProgram()) {\n const hasDirectReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) {\n return true;\n }\n const isOtherComponent = componentPaths.some(\n (p) => p !== componentPath && p.node === current?.node\n );\n if (isOtherComponent) {\n return false;\n }\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasDirectReplacements) {\n componentsNeedingHooks.add(componentPath);\n }\n continue;\n }\n\n const hasReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) return true;\n\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasReplacements) {\n const key = componentKeyMap.get(componentPath.node)!;\n let ancestorProvidesKey = false;\n let currentPath: NodePath | null = componentPath.parentPath;\n while (currentPath) {\n const ancestorPath = componentPaths.find(\n (path) => path.node === currentPath?.node\n );\n\n if (ancestorPath && !ancestorPath.isProgram()) {\n const ancestorKey = componentKeyMap.get(ancestorPath.node);\n\n if (ancestorKey === key) {\n const ancestorHasReplacements = replacements.some((replacement) => {\n let rPath: NodePath | null = replacement.path;\n while (rPath) {\n if (rPath.node === ancestorPath.node) return true;\n\n rPath = rPath.parentPath;\n }\n return false;\n });\n const existingInfo = getExistingIntlayerInfo(ancestorPath);\n\n if (ancestorHasReplacements || existingInfo) {\n ancestorProvidesKey = true;\n break;\n }\n }\n }\n currentPath = currentPath.parentPath;\n }\n\n if (!ancestorProvidesKey) {\n componentsNeedingHooks.add(componentPath);\n }\n }\n }\n\n return {\n extractedContent,\n replacements,\n componentsNeedingHooks,\n componentKeyMap,\n componentPaths,\n hookMap,\n isSolid: false,\n };\n};\n\n/**\n * High-level function to extract content from TS/JS/JSX/TSX AST.\n */\nexport const extractTsContent = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, string>;\n replacements: BabelReplacement[];\n} => {\n const { extractedContent, replacements } = extractBabelContentForComponents(\n ast,\n fileCode,\n existingKeys,\n 'default',\n configuration,\n filePath,\n unmergedDictionaries\n );\n\n const flatContent: Record<string, string> = {};\n for (const group of Object.values(extractedContent)) {\n Object.assign(flatContent, group);\n }\n\n return { extractedContent: flatContent, replacements };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"babelProcessor.cjs","names":["_traverse","t","shouldExtract","getOrGenerateKey","getExistingIntlayerInfo","resolveDictionaryKey","getComponentName","ATTRIBUTES_TO_EXTRACT"],"sources":["../../../src/extractContent/babelProcessor.ts"],"sourcesContent":["import _traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { resolveDictionaryKey } from '../extractContent/utils';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n getComponentName,\n getExistingIntlayerInfo,\n getOrGenerateKey,\n shouldExtract,\n} from './utils';\n\nexport type BabelReplacement = {\n path: NodePath;\n key: string;\n type:\n | 'jsx-text'\n | 'jsx-attribute'\n | 'string-literal'\n | 'jsx-insertion'\n | 'jsx-text-combined'\n | 'template-literal';\n componentKey: string;\n childrenToReplace?: t.Node[];\n variables?: string[];\n};\n\n// CJS/ESM interop: @babel/traverse exports its function as `.default` in CJS bundles\nconst traverse = (\n typeof _traverse === 'function' ? _traverse : (_traverse as any).default\n) as typeof _traverse;\n\n/**\n * Handles JSX insertions (elements with multiple children, including expressions).\n * Replaces complex JSX structures with variable-based translations.\n */\nexport const handleJsxInsertionBabel = (\n path: NodePath<t.JSXElement | t.JSXFragment>,\n fileCode: string,\n existingKeys: Set<string>,\n getComponentKeyForPath: (path: NodePath) => string,\n extractedContent: Record<string, Record<string, string>>,\n replacements: BabelReplacement[],\n handledNodes: Set<t.Node>\n): boolean => {\n const children = path.node.children;\n\n if (children.length <= 1) return false;\n\n const parts: {\n type: 'text' | 'var';\n value: string;\n originalExpr?: string;\n }[] = [];\n let hasSignificantText = false;\n let hasVariables = false;\n\n for (const child of children) {\n if (t.isJSXText(child)) {\n const text = child.value;\n\n if (text.trim().length > 0) hasSignificantText = true;\n\n parts.push({ type: 'text', value: text });\n } else if (t.isJSXExpressionContainer(child)) {\n if (t.isJSXEmptyExpression(child.expression)) {\n parts.push({ type: 'text', value: '' });\n } else {\n const expr = child.expression;\n\n if (t.isIdentifier(expr)) {\n parts.push({\n type: 'var',\n value: expr.name,\n originalExpr: expr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n\n parts.push({ type: 'var', value: varName, originalExpr: code });\n\n hasVariables = true;\n } else if (t.isTemplateLiteral(expr)) {\n for (let i = 0; i < expr.quasis.length; i++) {\n parts.push({ type: 'text', value: expr.quasis[i].value.raw });\n if (i < expr.expressions.length) {\n const subExpr = expr.expressions[i];\n if (t.isIdentifier(subExpr)) {\n parts.push({\n type: 'var',\n value: subExpr.name,\n originalExpr: subExpr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(subExpr)) {\n const code = fileCode.substring(subExpr.start!, subExpr.end!);\n const varName = t.isIdentifier(subExpr.property)\n ? subExpr.property.name\n : 'var';\n parts.push({ type: 'var', value: varName, originalExpr: code });\n hasVariables = true;\n } else {\n return false;\n }\n }\n }\n } else {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n\n if (!hasSignificantText) return false;\n\n let combinedString = '';\n for (const part of parts) {\n if (part.type === 'var') combinedString += `{{${part.value}}}`;\n else combinedString += part.value;\n }\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (shouldExtract(cleanString)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const varMap = parts\n .filter((part) => part.type === 'var')\n .map((part) => `${part.value}: ${part.originalExpr}`);\n const uniqueVars = Array.from(new Set(varMap));\n\n if (hasVariables) {\n replacements.push({\n path,\n key,\n type: 'jsx-insertion',\n componentKey,\n childrenToReplace: children,\n variables: uniqueVars,\n });\n } else {\n replacements.push({\n path,\n key,\n type: 'jsx-text-combined',\n componentKey,\n childrenToReplace: children,\n });\n }\n\n children.forEach((child) => {\n handledNodes.add(child);\n });\n return true;\n }\n\n return false;\n};\n\n/**\n * Traverses the AST to identify components and extract content.\n * Returns extraction results and metadata about which components need Intlayer hooks.\n */\nexport const extractBabelContentForComponents = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n defaultKey: string = 'default',\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, Record<string, string>>;\n replacements: BabelReplacement[];\n componentsNeedingHooks: Set<NodePath>;\n componentKeyMap: Map<t.Node, string>;\n componentPaths: NodePath[];\n hookMap: Map<t.Node, 'useIntlayer' | 'getIntlayer'>;\n isSolid: boolean;\n} => {\n const extractedContent: Record<string, Record<string, string>> = {};\n const replacements: BabelReplacement[] = [];\n const handledNodes = new Set<t.Node>();\n const componentKeyMap = new Map<t.Node, string>();\n const hookMap = new Map<t.Node, 'useIntlayer' | 'getIntlayer'>();\n const usedKeysInFile = new Set<string>();\n let globalFileKey: string | undefined;\n\n const componentPaths: NodePath[] = [];\n\n traverse(ast, {\n Program(path) {\n componentPaths.push(path);\n },\n FunctionDeclaration(path) {\n componentPaths.push(path);\n },\n ArrowFunctionExpression(path) {\n componentPaths.push(path);\n },\n FunctionExpression(path) {\n componentPaths.push(path);\n },\n });\n\n // Pre-scan non-Program paths to collect their existing dictionary keys before the\n // Program scope is assigned. Without this, Program is processed first (depth-first\n // traversal) and creates a new file-path-derived key even when a child component\n // already declares a specific dictionary (e.g. useIntlayer('dashboard-sidebar')).\n for (const path of componentPaths) {\n if (path.isProgram()) continue;\n const existingInfo = getExistingIntlayerInfo(path);\n if (existingInfo) {\n usedKeysInFile.add(existingInfo.key);\n }\n }\n\n for (const path of componentPaths) {\n const existingInfo = getExistingIntlayerInfo(path);\n\n if (existingInfo) {\n componentKeyMap.set(path.node, existingInfo.key);\n usedKeysInFile.add(existingInfo.key);\n hookMap.set(path.node, existingInfo.hook);\n } else {\n if (path.isProgram()) {\n if (!globalFileKey) {\n // Reuse the dominant existing key from child components so that\n // module-level strings join the same dictionary rather than\n // creating a new file-path-derived one (e.g. 'route').\n const dominantKey =\n usedKeysInFile.size > 0 ? [...usedKeysInFile][0] : undefined;\n if (dominantKey) {\n globalFileKey = dominantKey;\n } else {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n }\n componentKeyMap.set(path.node, globalFileKey);\n hookMap.set(path.node, 'getIntlayer');\n } else {\n let inheritedKey: string | undefined;\n let parent: NodePath | null = path.parentPath;\n while (parent) {\n if (componentKeyMap.has(parent.node)) {\n inheritedKey = componentKeyMap.get(parent.node);\n break;\n }\n parent = parent.parentPath;\n }\n\n if (!inheritedKey) {\n if (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n inheritedKey = globalFileKey;\n }\n\n componentKeyMap.set(path.node, inheritedKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n const isHook = compName ? /^use[A-Z]/.test(compName) : false;\n hookMap.set(\n path.node,\n isComponent || isHook ? 'useIntlayer' : 'getIntlayer'\n );\n }\n }\n }\n\n const getComponentKeyForPath = (path: NodePath): string => {\n let current: NodePath | null = path;\n while (current) {\n if (componentKeyMap.has(current.node)) {\n return componentKeyMap.get(current.node)!;\n }\n current = current.parentPath;\n }\n return globalFileKey || defaultKey;\n };\n\n traverse(ast, {\n JSXElement(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXFragment(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXText(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (shouldExtract(text)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.replace(/\\s+/g, ' ').trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-text', componentKey });\n }\n },\n JSXAttribute(path) {\n if (handledNodes.has(path.node)) return;\n\n const name = path.node.name.name;\n\n if (\n typeof name !== 'string' ||\n !ATTRIBUTES_TO_EXTRACT.includes(name as any)\n )\n return;\n const value = path.node.value;\n\n if (t.isStringLiteral(value) && shouldExtract(value.value)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n value.value.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-attribute', componentKey });\n }\n },\n StringLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (!shouldExtract(text)) return;\n\n const parent = path.parentPath;\n\n if (\n parent.isImportDeclaration() ||\n parent.isImportSpecifier() ||\n parent.isExportDeclaration()\n )\n return;\n\n if (parent.isJSXAttribute()) return;\n\n if (\n parent.isCallExpression() &&\n t.isMemberExpression(parent.node.callee)\n ) {\n if (\n t.isIdentifier(parent.node.callee.object) &&\n parent.node.callee.object.name === 'console' &&\n t.isIdentifier(parent.node.callee.property) &&\n parent.node.callee.property.name === 'log'\n ) {\n return;\n }\n }\n\n if (parent.isObjectProperty() && parent.node.key === path.node) return;\n\n // Skip string values in known technical/non-translatable object properties (e.g. `icon: 'Globe'`).\n // String values in translatable object properties (e.g. `label: 'Language'`) are still extracted.\n const TECHNICAL_KEYS = new Set([\n 'icon',\n 'className',\n 'class',\n 'id',\n 'type',\n 'variant',\n 'color',\n 'theme',\n 'size',\n 'align',\n 'placement',\n 'target',\n 'rel',\n 'method',\n 'mode',\n 'direction',\n 'orientation',\n 'scope',\n 'role',\n 'lang',\n 'locale',\n 'href',\n 'src',\n 'width',\n 'height',\n 'as',\n 'to',\n 'key',\n 'value',\n 'defaultValue',\n 'prop',\n 'property',\n 'state',\n 'action',\n 'event',\n 'handler',\n 'callback',\n 'url',\n 'uri',\n 'path',\n 'route',\n 'slug',\n 'endpoint',\n 'headers',\n 'contentType',\n ]);\n if (\n parent.isObjectProperty() &&\n t.isIdentifier(parent.node.key) &&\n TECHNICAL_KEYS.has(parent.node.key.name)\n ) {\n return;\n }\n\n if (parent.isMemberExpression() && parent.node.property === path.node)\n return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'string-literal', componentKey });\n },\n TemplateLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const { quasis, expressions } = path.node;\n\n // Build the combined string with placeholders\n let combinedString = '';\n const variables: string[] = [];\n let hasSignificantText = false;\n\n for (let i = 0; i < quasis.length; i++) {\n const text = quasis[i].value.raw;\n combinedString += text;\n if (text.trim().length > 0) hasSignificantText = true;\n\n if (i < expressions.length) {\n const expr = expressions[i];\n if (t.isIdentifier(expr)) {\n combinedString += `{{${expr.name}}}`;\n variables.push(`${expr.name}: ${expr.name}`);\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n combinedString += `{{${varName}}}`;\n variables.push(`${varName}: ${code}`);\n } else {\n // Complex expression in template literal, skip\n return;\n }\n }\n }\n\n if (!hasSignificantText) return;\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (!shouldExtract(cleanString)) return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const uniqueVars = Array.from(new Set(variables));\n\n replacements.push({\n path,\n key,\n type: 'template-literal',\n componentKey,\n variables: uniqueVars,\n });\n },\n });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\n if (componentPath.isProgram()) {\n const hasDirectReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) {\n return true;\n }\n const isOtherComponent = componentPaths.some(\n (p) => p !== componentPath && p.node === current?.node\n );\n if (isOtherComponent) {\n return false;\n }\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasDirectReplacements) {\n componentsNeedingHooks.add(componentPath);\n }\n continue;\n }\n\n const hasReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) return true;\n\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasReplacements) {\n const key = componentKeyMap.get(componentPath.node)!;\n let ancestorProvidesKey = false;\n let currentPath: NodePath | null = componentPath.parentPath;\n while (currentPath) {\n const ancestorPath = componentPaths.find(\n (path) => path.node === currentPath?.node\n );\n\n if (ancestorPath && !ancestorPath.isProgram()) {\n const ancestorKey = componentKeyMap.get(ancestorPath.node);\n\n if (ancestorKey === key) {\n const ancestorHasReplacements = replacements.some((replacement) => {\n let rPath: NodePath | null = replacement.path;\n while (rPath) {\n if (rPath.node === ancestorPath.node) return true;\n\n rPath = rPath.parentPath;\n }\n return false;\n });\n const existingInfo = getExistingIntlayerInfo(ancestorPath);\n\n if (ancestorHasReplacements || existingInfo) {\n ancestorProvidesKey = true;\n break;\n }\n }\n }\n currentPath = currentPath.parentPath;\n }\n\n if (!ancestorProvidesKey) {\n componentsNeedingHooks.add(componentPath);\n }\n }\n }\n\n return {\n extractedContent,\n replacements,\n componentsNeedingHooks,\n componentKeyMap,\n componentPaths,\n hookMap,\n isSolid: false,\n };\n};\n\n/**\n * High-level function to extract content from TS/JS/JSX/TSX AST.\n */\nexport const extractTsContent = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, string>;\n replacements: BabelReplacement[];\n} => {\n const { extractedContent, replacements } = extractBabelContentForComponents(\n ast,\n fileCode,\n existingKeys,\n 'default',\n configuration,\n filePath,\n unmergedDictionaries\n );\n\n const flatContent: Record<string, string> = {};\n for (const group of Object.values(extractedContent)) {\n Object.assign(flatContent, group);\n }\n\n return { extractedContent: flatContent, replacements };\n};\n"],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ const shouldExtract = (text) => {
|
|
|
18
18
|
if (trimmed.includes("=>") || trimmed.includes(");") || trimmed.includes("(){") || trimmed.includes("==") || trimmed.includes("window.") || trimmed.startsWith("(function") || trimmed.startsWith("function(")) return false;
|
|
19
19
|
if ((trimmed.match(/[^\p{L}\p{N}\s.,!?;:'"()[\]{}–—/«»„“\p{Sc}%&*+#@^_+=<>/~]/gu) || []).length > 5) return false;
|
|
20
20
|
const wordCount = trimmed.split(/\s+/).length;
|
|
21
|
-
const cssClassTokenRegex = /^!?([a-z][a-z0-9]*:)*[a-z][a-z0-9]*(-[a-z0-9[\].,%#/]+)*(\/[a-z0-9]+)?$/;
|
|
21
|
+
const cssClassTokenRegex = /^!?([a-z][a-z0-9-]*:)*[a-z][a-z0-9]*(-[a-z0-9[\].,%#/]+)*(\/[a-z0-9]+)?$/;
|
|
22
22
|
if (wordCount > 1) {
|
|
23
23
|
const tokens = trimmed.split(/\s+/);
|
|
24
24
|
if (tokens.every((token) => cssClassTokenRegex.test(token)) && tokens.some((token) => token.includes("-"))) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shouldExtract.cjs","names":[],"sources":["../../../../src/extractContent/utils/shouldExtract.ts"],"sourcesContent":["/**\n * Checks whether the given text should be extracted as a translatable string.\n *\n * Filters out:\n * - Empty strings\n * - Emails\n * - Uncapitalized strings of 2 words or fewer (likely technical terms)\n * - Dynamic content patterns like Vue bindings (`v-`) or object patterns (`{`)\n */\nexport const shouldExtract = (text: string): boolean => {\n const trimmed = text.trim();\n\n if (!trimmed) return false;\n\n // Ignore emails\n if (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) return false;\n\n // Ignore dynamic content patterns\n if (trimmed.startsWith('{') || trimmed.startsWith('v-')) return false;\n\n // Ignore explicit code patterns (markers)\n if (\n trimmed.includes('=>') ||\n trimmed.includes(');') ||\n trimmed.includes('(){') ||\n trimmed.includes('==') ||\n trimmed.includes('window.') ||\n trimmed.startsWith('(function') ||\n trimmed.startsWith('function(')\n ) {\n return false;\n }\n\n // Heuristic: check for characters that are common in code but rare in natural text.\n // Whitelist: letters, numbers, spaces, and frequent text symbols (including punctuation, braces, and technical symbols)\n const nonTextualRegex =\n /[^\\p{L}\\p{N}\\s.,!?;:'\"()[\\]{}–—/«»„“\\p{Sc}%&*+#@^_+=<>/~]/gu;\n const nonTextualMatches = trimmed.match(nonTextualRegex) || [];\n\n // If a string contains a high density of truly exceptional symbols (like |, \\, etc.),\n // it is highly likely to be code or complex technical data.\n if (nonTextualMatches.length > 5) return false;\n\n const wordCount = trimmed.split(/\\s+/).length;\n\n // Ignore CSS/Tailwind utility class strings. A string whose tokens all look\n // like CSS utility classes (lowercase, optional responsive/state prefix like\n // \"sm:\" or \"hover:\", optional hyphenated suffix like \"-4\" or \"-full\") and\n // where at least one token contains a hyphen is almost certainly a className\n // value, not translatable text.\n const cssClassTokenRegex =\n /^!?([a-z][a-z0-9]*:)*[a-z][a-z0-9]*(-[a-z0-9[\\].,%#/]+)*(\\/[a-z0-9]+)?$/;\n if (wordCount > 1) {\n const tokens = trimmed.split(/\\s+/);\n if (\n tokens.every((token) => cssClassTokenRegex.test(token)) &&\n tokens.some((token) => token.includes('-'))\n ) {\n return false;\n }\n }\n\n // Check if starts with a capital letter (including after an opening parenthesis/quote)\n const isCapitalized = /^['\"([]*\\p{Lu}/u.test(trimmed);\n\n // Ignore technical identifiers (one word strings with camelCase, kebab-case, snake_case etc.)\n if (wordCount === 1) {\n // CamelCase or internal capitals (like camelCaseProperty or CamelCaseProperty)\n if (/[a-z]\\p{Lu}/u.test(trimmed)) return false;\n // kebab-case or snake_case\n if (trimmed.includes('-') || trimmed.includes('_')) return false;\n }\n\n // We usually want to extract full sentences or labels, not single/short technical words.\n // Extract if capitalized, or if it contains more than 2 words.\n if (!isCapitalized && wordCount <= 2) return false;\n\n return true;\n};\n"],"mappings":";;;;;;;;;;;;AASA,MAAa,iBAAiB,SAA0B;CACtD,MAAM,UAAU,KAAK,KAAK;CAE1B,IAAI,CAAC,SAAS,OAAO;CAGrB,IAAI,6BAA6B,KAAK,OAAO,GAAG,OAAO;CAGvD,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,IAAI,GAAG,OAAO;CAGhE,IACE,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,SAAS,KAC1B,QAAQ,WAAW,WAAW,KAC9B,QAAQ,WAAW,WAAW,GAE9B,OAAO;CAWT,KAJ0B,QAAQ,MAAM,6DAAe,KAAK,CAAC,GAIvC,SAAS,GAAG,OAAO;CAEzC,MAAM,YAAY,QAAQ,MAAM,KAAK,EAAE;CAOvC,MAAM,qBACJ;CACF,IAAI,YAAY,GAAG;EACjB,MAAM,SAAS,QAAQ,MAAM,KAAK;EAClC,IACE,OAAO,OAAO,UAAU,mBAAmB,KAAK,KAAK,CAAC,KACtD,OAAO,MAAM,UAAU,MAAM,SAAS,GAAG,CAAC,GAE1C,OAAO;CAEX;CAGA,MAAM,gBAAgB,kBAAkB,KAAK,OAAO;CAGpD,IAAI,cAAc,GAAG;EAEnB,IAAI,eAAe,KAAK,OAAO,GAAG,OAAO;EAEzC,IAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG,OAAO;CAC7D;CAIA,IAAI,CAAC,iBAAiB,aAAa,GAAG,OAAO;CAE7C,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"shouldExtract.cjs","names":[],"sources":["../../../../src/extractContent/utils/shouldExtract.ts"],"sourcesContent":["/**\n * Checks whether the given text should be extracted as a translatable string.\n *\n * Filters out:\n * - Empty strings\n * - Emails\n * - Uncapitalized strings of 2 words or fewer (likely technical terms)\n * - Dynamic content patterns like Vue bindings (`v-`) or object patterns (`{`)\n */\nexport const shouldExtract = (text: string): boolean => {\n const trimmed = text.trim();\n\n if (!trimmed) return false;\n\n // Ignore emails\n if (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) return false;\n\n // Ignore dynamic content patterns\n if (trimmed.startsWith('{') || trimmed.startsWith('v-')) return false;\n\n // Ignore explicit code patterns (markers)\n if (\n trimmed.includes('=>') ||\n trimmed.includes(');') ||\n trimmed.includes('(){') ||\n trimmed.includes('==') ||\n trimmed.includes('window.') ||\n trimmed.startsWith('(function') ||\n trimmed.startsWith('function(')\n ) {\n return false;\n }\n\n // Heuristic: check for characters that are common in code but rare in natural text.\n // Whitelist: letters, numbers, spaces, and frequent text symbols (including punctuation, braces, and technical symbols)\n const nonTextualRegex =\n /[^\\p{L}\\p{N}\\s.,!?;:'\"()[\\]{}–—/«»„“\\p{Sc}%&*+#@^_+=<>/~]/gu;\n const nonTextualMatches = trimmed.match(nonTextualRegex) || [];\n\n // If a string contains a high density of truly exceptional symbols (like |, \\, etc.),\n // it is highly likely to be code or complex technical data.\n if (nonTextualMatches.length > 5) return false;\n\n const wordCount = trimmed.split(/\\s+/).length;\n\n // Ignore CSS/Tailwind utility class strings. A string whose tokens all look\n // like CSS utility classes (lowercase, optional responsive/state prefix like\n // \"sm:\" or \"hover:\", optional hyphenated suffix like \"-4\" or \"-full\") and\n // where at least one token contains a hyphen is almost certainly a className\n // value, not translatable text.\n const cssClassTokenRegex =\n /^!?([a-z][a-z0-9-]*:)*[a-z][a-z0-9]*(-[a-z0-9[\\].,%#/]+)*(\\/[a-z0-9]+)?$/;\n if (wordCount > 1) {\n const tokens = trimmed.split(/\\s+/);\n if (\n tokens.every((token) => cssClassTokenRegex.test(token)) &&\n tokens.some((token) => token.includes('-'))\n ) {\n return false;\n }\n }\n\n // Check if starts with a capital letter (including after an opening parenthesis/quote)\n const isCapitalized = /^['\"([]*\\p{Lu}/u.test(trimmed);\n\n // Ignore technical identifiers (one word strings with camelCase, kebab-case, snake_case etc.)\n if (wordCount === 1) {\n // CamelCase or internal capitals (like camelCaseProperty or CamelCaseProperty)\n if (/[a-z]\\p{Lu}/u.test(trimmed)) return false;\n // kebab-case or snake_case\n if (trimmed.includes('-') || trimmed.includes('_')) return false;\n }\n\n // We usually want to extract full sentences or labels, not single/short technical words.\n // Extract if capitalized, or if it contains more than 2 words.\n if (!isCapitalized && wordCount <= 2) return false;\n\n return true;\n};\n"],"mappings":";;;;;;;;;;;;AASA,MAAa,iBAAiB,SAA0B;CACtD,MAAM,UAAU,KAAK,KAAK;CAE1B,IAAI,CAAC,SAAS,OAAO;CAGrB,IAAI,6BAA6B,KAAK,OAAO,GAAG,OAAO;CAGvD,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,IAAI,GAAG,OAAO;CAGhE,IACE,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,SAAS,KAC1B,QAAQ,WAAW,WAAW,KAC9B,QAAQ,WAAW,WAAW,GAE9B,OAAO;CAWT,KAJ0B,QAAQ,MAAM,6DAAe,KAAK,CAAC,GAIvC,SAAS,GAAG,OAAO;CAEzC,MAAM,YAAY,QAAQ,MAAM,KAAK,EAAE;CAOvC,MAAM,qBACJ;CACF,IAAI,YAAY,GAAG;EACjB,MAAM,SAAS,QAAQ,MAAM,KAAK;EAClC,IACE,OAAO,OAAO,UAAU,mBAAmB,KAAK,KAAK,CAAC,KACtD,OAAO,MAAM,UAAU,MAAM,SAAS,GAAG,CAAC,GAE1C,OAAO;CAEX;CAGA,MAAM,gBAAgB,kBAAkB,KAAK,OAAO;CAGpD,IAAI,cAAc,GAAG;EAEnB,IAAI,eAAe,KAAK,OAAO,GAAG,OAAO;EAEzC,IAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG,OAAO;CAC7D;CAIA,IAAI,CAAC,iBAAiB,aAAa,GAAG,OAAO;CAE7C,OAAO;AACT"}
|
|
@@ -240,7 +240,54 @@ const extractBabelContentForComponents = (ast, fileCode, existingKeys, defaultKe
|
|
|
240
240
|
if (t.isIdentifier(parent.node.callee.object) && parent.node.callee.object.name === "console" && t.isIdentifier(parent.node.callee.property) && parent.node.callee.property.name === "log") return;
|
|
241
241
|
}
|
|
242
242
|
if (parent.isObjectProperty() && parent.node.key === path.node) return;
|
|
243
|
-
|
|
243
|
+
const TECHNICAL_KEYS = new Set([
|
|
244
|
+
"icon",
|
|
245
|
+
"className",
|
|
246
|
+
"class",
|
|
247
|
+
"id",
|
|
248
|
+
"type",
|
|
249
|
+
"variant",
|
|
250
|
+
"color",
|
|
251
|
+
"theme",
|
|
252
|
+
"size",
|
|
253
|
+
"align",
|
|
254
|
+
"placement",
|
|
255
|
+
"target",
|
|
256
|
+
"rel",
|
|
257
|
+
"method",
|
|
258
|
+
"mode",
|
|
259
|
+
"direction",
|
|
260
|
+
"orientation",
|
|
261
|
+
"scope",
|
|
262
|
+
"role",
|
|
263
|
+
"lang",
|
|
264
|
+
"locale",
|
|
265
|
+
"href",
|
|
266
|
+
"src",
|
|
267
|
+
"width",
|
|
268
|
+
"height",
|
|
269
|
+
"as",
|
|
270
|
+
"to",
|
|
271
|
+
"key",
|
|
272
|
+
"value",
|
|
273
|
+
"defaultValue",
|
|
274
|
+
"prop",
|
|
275
|
+
"property",
|
|
276
|
+
"state",
|
|
277
|
+
"action",
|
|
278
|
+
"event",
|
|
279
|
+
"handler",
|
|
280
|
+
"callback",
|
|
281
|
+
"url",
|
|
282
|
+
"uri",
|
|
283
|
+
"path",
|
|
284
|
+
"route",
|
|
285
|
+
"slug",
|
|
286
|
+
"endpoint",
|
|
287
|
+
"headers",
|
|
288
|
+
"contentType"
|
|
289
|
+
]);
|
|
290
|
+
if (parent.isObjectProperty() && t.isIdentifier(parent.node.key) && TECHNICAL_KEYS.has(parent.node.key.name)) return;
|
|
244
291
|
if (parent.isMemberExpression() && parent.node.property === path.node) return;
|
|
245
292
|
const componentKey = getComponentKeyForPath(path);
|
|
246
293
|
const key = getOrGenerateKey(text.trim(), componentKey, existingKeys, extractedContent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"babelProcessor.mjs","names":[],"sources":["../../../src/extractContent/babelProcessor.ts"],"sourcesContent":["import _traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { resolveDictionaryKey } from '../extractContent/utils';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n getComponentName,\n getExistingIntlayerInfo,\n getOrGenerateKey,\n shouldExtract,\n} from './utils';\n\nexport type BabelReplacement = {\n path: NodePath;\n key: string;\n type:\n | 'jsx-text'\n | 'jsx-attribute'\n | 'string-literal'\n | 'jsx-insertion'\n | 'jsx-text-combined'\n | 'template-literal';\n componentKey: string;\n childrenToReplace?: t.Node[];\n variables?: string[];\n};\n\n// CJS/ESM interop: @babel/traverse exports its function as `.default` in CJS bundles\nconst traverse = (\n typeof _traverse === 'function' ? _traverse : (_traverse as any).default\n) as typeof _traverse;\n\n/**\n * Handles JSX insertions (elements with multiple children, including expressions).\n * Replaces complex JSX structures with variable-based translations.\n */\nexport const handleJsxInsertionBabel = (\n path: NodePath<t.JSXElement | t.JSXFragment>,\n fileCode: string,\n existingKeys: Set<string>,\n getComponentKeyForPath: (path: NodePath) => string,\n extractedContent: Record<string, Record<string, string>>,\n replacements: BabelReplacement[],\n handledNodes: Set<t.Node>\n): boolean => {\n const children = path.node.children;\n\n if (children.length <= 1) return false;\n\n const parts: {\n type: 'text' | 'var';\n value: string;\n originalExpr?: string;\n }[] = [];\n let hasSignificantText = false;\n let hasVariables = false;\n\n for (const child of children) {\n if (t.isJSXText(child)) {\n const text = child.value;\n\n if (text.trim().length > 0) hasSignificantText = true;\n\n parts.push({ type: 'text', value: text });\n } else if (t.isJSXExpressionContainer(child)) {\n if (t.isJSXEmptyExpression(child.expression)) {\n parts.push({ type: 'text', value: '' });\n } else {\n const expr = child.expression;\n\n if (t.isIdentifier(expr)) {\n parts.push({\n type: 'var',\n value: expr.name,\n originalExpr: expr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n\n parts.push({ type: 'var', value: varName, originalExpr: code });\n\n hasVariables = true;\n } else if (t.isTemplateLiteral(expr)) {\n for (let i = 0; i < expr.quasis.length; i++) {\n parts.push({ type: 'text', value: expr.quasis[i].value.raw });\n if (i < expr.expressions.length) {\n const subExpr = expr.expressions[i];\n if (t.isIdentifier(subExpr)) {\n parts.push({\n type: 'var',\n value: subExpr.name,\n originalExpr: subExpr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(subExpr)) {\n const code = fileCode.substring(subExpr.start!, subExpr.end!);\n const varName = t.isIdentifier(subExpr.property)\n ? subExpr.property.name\n : 'var';\n parts.push({ type: 'var', value: varName, originalExpr: code });\n hasVariables = true;\n } else {\n return false;\n }\n }\n }\n } else {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n\n if (!hasSignificantText) return false;\n\n let combinedString = '';\n for (const part of parts) {\n if (part.type === 'var') combinedString += `{{${part.value}}}`;\n else combinedString += part.value;\n }\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (shouldExtract(cleanString)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const varMap = parts\n .filter((part) => part.type === 'var')\n .map((part) => `${part.value}: ${part.originalExpr}`);\n const uniqueVars = Array.from(new Set(varMap));\n\n if (hasVariables) {\n replacements.push({\n path,\n key,\n type: 'jsx-insertion',\n componentKey,\n childrenToReplace: children,\n variables: uniqueVars,\n });\n } else {\n replacements.push({\n path,\n key,\n type: 'jsx-text-combined',\n componentKey,\n childrenToReplace: children,\n });\n }\n\n children.forEach((child) => {\n handledNodes.add(child);\n });\n return true;\n }\n\n return false;\n};\n\n/**\n * Traverses the AST to identify components and extract content.\n * Returns extraction results and metadata about which components need Intlayer hooks.\n */\nexport const extractBabelContentForComponents = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n defaultKey: string = 'default',\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, Record<string, string>>;\n replacements: BabelReplacement[];\n componentsNeedingHooks: Set<NodePath>;\n componentKeyMap: Map<t.Node, string>;\n componentPaths: NodePath[];\n hookMap: Map<t.Node, 'useIntlayer' | 'getIntlayer'>;\n isSolid: boolean;\n} => {\n const extractedContent: Record<string, Record<string, string>> = {};\n const replacements: BabelReplacement[] = [];\n const handledNodes = new Set<t.Node>();\n const componentKeyMap = new Map<t.Node, string>();\n const hookMap = new Map<t.Node, 'useIntlayer' | 'getIntlayer'>();\n const usedKeysInFile = new Set<string>();\n let globalFileKey: string | undefined;\n\n const componentPaths: NodePath[] = [];\n\n traverse(ast, {\n Program(path) {\n componentPaths.push(path);\n },\n FunctionDeclaration(path) {\n componentPaths.push(path);\n },\n ArrowFunctionExpression(path) {\n componentPaths.push(path);\n },\n FunctionExpression(path) {\n componentPaths.push(path);\n },\n });\n\n // Pre-scan non-Program paths to collect their existing dictionary keys before the\n // Program scope is assigned. Without this, Program is processed first (depth-first\n // traversal) and creates a new file-path-derived key even when a child component\n // already declares a specific dictionary (e.g. useIntlayer('dashboard-sidebar')).\n for (const path of componentPaths) {\n if (path.isProgram()) continue;\n const existingInfo = getExistingIntlayerInfo(path);\n if (existingInfo) {\n usedKeysInFile.add(existingInfo.key);\n }\n }\n\n for (const path of componentPaths) {\n const existingInfo = getExistingIntlayerInfo(path);\n\n if (existingInfo) {\n componentKeyMap.set(path.node, existingInfo.key);\n usedKeysInFile.add(existingInfo.key);\n hookMap.set(path.node, existingInfo.hook);\n } else {\n if (path.isProgram()) {\n if (!globalFileKey) {\n // Reuse the dominant existing key from child components so that\n // module-level strings join the same dictionary rather than\n // creating a new file-path-derived one (e.g. 'route').\n const dominantKey =\n usedKeysInFile.size > 0 ? [...usedKeysInFile][0] : undefined;\n if (dominantKey) {\n globalFileKey = dominantKey;\n } else {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n }\n componentKeyMap.set(path.node, globalFileKey);\n hookMap.set(path.node, 'getIntlayer');\n } else {\n let inheritedKey: string | undefined;\n let parent: NodePath | null = path.parentPath;\n while (parent) {\n if (componentKeyMap.has(parent.node)) {\n inheritedKey = componentKeyMap.get(parent.node);\n break;\n }\n parent = parent.parentPath;\n }\n\n if (!inheritedKey) {\n if (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n inheritedKey = globalFileKey;\n }\n\n componentKeyMap.set(path.node, inheritedKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n const isHook = compName ? /^use[A-Z]/.test(compName) : false;\n hookMap.set(\n path.node,\n isComponent || isHook ? 'useIntlayer' : 'getIntlayer'\n );\n }\n }\n }\n\n const getComponentKeyForPath = (path: NodePath): string => {\n let current: NodePath | null = path;\n while (current) {\n if (componentKeyMap.has(current.node)) {\n return componentKeyMap.get(current.node)!;\n }\n current = current.parentPath;\n }\n return globalFileKey || defaultKey;\n };\n\n traverse(ast, {\n JSXElement(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXFragment(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXText(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (shouldExtract(text)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.replace(/\\s+/g, ' ').trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-text', componentKey });\n }\n },\n JSXAttribute(path) {\n if (handledNodes.has(path.node)) return;\n\n const name = path.node.name.name;\n\n if (\n typeof name !== 'string' ||\n !ATTRIBUTES_TO_EXTRACT.includes(name as any)\n )\n return;\n const value = path.node.value;\n\n if (t.isStringLiteral(value) && shouldExtract(value.value)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n value.value.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-attribute', componentKey });\n }\n },\n StringLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (!shouldExtract(text)) return;\n\n const parent = path.parentPath;\n\n if (\n parent.isImportDeclaration() ||\n parent.isImportSpecifier() ||\n parent.isExportDeclaration()\n )\n return;\n\n if (parent.isJSXAttribute()) return;\n\n if (\n parent.isCallExpression() &&\n t.isMemberExpression(parent.node.callee)\n ) {\n if (\n t.isIdentifier(parent.node.callee.object) &&\n parent.node.callee.object.name === 'console' &&\n t.isIdentifier(parent.node.callee.property) &&\n parent.node.callee.property.name === 'log'\n ) {\n return;\n }\n }\n\n if (parent.isObjectProperty() && parent.node.key === path.node) return;\n\n // Skip string values in named object properties (identifier key, e.g. `icon: 'Globe'`).\n // These are technical mappings, not translatable text. String-keyed properties\n // (e.g. `'translation-status': 'Translation Status'`) are still extracted.\n if (parent.isObjectProperty() && t.isIdentifier(parent.node.key)) return;\n\n if (parent.isMemberExpression() && parent.node.property === path.node)\n return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'string-literal', componentKey });\n },\n TemplateLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const { quasis, expressions } = path.node;\n\n // Build the combined string with placeholders\n let combinedString = '';\n const variables: string[] = [];\n let hasSignificantText = false;\n\n for (let i = 0; i < quasis.length; i++) {\n const text = quasis[i].value.raw;\n combinedString += text;\n if (text.trim().length > 0) hasSignificantText = true;\n\n if (i < expressions.length) {\n const expr = expressions[i];\n if (t.isIdentifier(expr)) {\n combinedString += `{{${expr.name}}}`;\n variables.push(`${expr.name}: ${expr.name}`);\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n combinedString += `{{${varName}}}`;\n variables.push(`${varName}: ${code}`);\n } else {\n // Complex expression in template literal, skip\n return;\n }\n }\n }\n\n if (!hasSignificantText) return;\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (!shouldExtract(cleanString)) return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const uniqueVars = Array.from(new Set(variables));\n\n replacements.push({\n path,\n key,\n type: 'template-literal',\n componentKey,\n variables: uniqueVars,\n });\n },\n });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\n if (componentPath.isProgram()) {\n const hasDirectReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) {\n return true;\n }\n const isOtherComponent = componentPaths.some(\n (p) => p !== componentPath && p.node === current?.node\n );\n if (isOtherComponent) {\n return false;\n }\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasDirectReplacements) {\n componentsNeedingHooks.add(componentPath);\n }\n continue;\n }\n\n const hasReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) return true;\n\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasReplacements) {\n const key = componentKeyMap.get(componentPath.node)!;\n let ancestorProvidesKey = false;\n let currentPath: NodePath | null = componentPath.parentPath;\n while (currentPath) {\n const ancestorPath = componentPaths.find(\n (path) => path.node === currentPath?.node\n );\n\n if (ancestorPath && !ancestorPath.isProgram()) {\n const ancestorKey = componentKeyMap.get(ancestorPath.node);\n\n if (ancestorKey === key) {\n const ancestorHasReplacements = replacements.some((replacement) => {\n let rPath: NodePath | null = replacement.path;\n while (rPath) {\n if (rPath.node === ancestorPath.node) return true;\n\n rPath = rPath.parentPath;\n }\n return false;\n });\n const existingInfo = getExistingIntlayerInfo(ancestorPath);\n\n if (ancestorHasReplacements || existingInfo) {\n ancestorProvidesKey = true;\n break;\n }\n }\n }\n currentPath = currentPath.parentPath;\n }\n\n if (!ancestorProvidesKey) {\n componentsNeedingHooks.add(componentPath);\n }\n }\n }\n\n return {\n extractedContent,\n replacements,\n componentsNeedingHooks,\n componentKeyMap,\n componentPaths,\n hookMap,\n isSolid: false,\n };\n};\n\n/**\n * High-level function to extract content from TS/JS/JSX/TSX AST.\n */\nexport const extractTsContent = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, string>;\n replacements: BabelReplacement[];\n} => {\n const { extractedContent, replacements } = extractBabelContentForComponents(\n ast,\n fileCode,\n existingKeys,\n 'default',\n configuration,\n filePath,\n unmergedDictionaries\n );\n\n const flatContent: Record<string, string> = {};\n for (const group of Object.values(extractedContent)) {\n Object.assign(flatContent, group);\n }\n\n return { extractedContent: flatContent, replacements };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"babelProcessor.mjs","names":[],"sources":["../../../src/extractContent/babelProcessor.ts"],"sourcesContent":["import _traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { resolveDictionaryKey } from '../extractContent/utils';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n getComponentName,\n getExistingIntlayerInfo,\n getOrGenerateKey,\n shouldExtract,\n} from './utils';\n\nexport type BabelReplacement = {\n path: NodePath;\n key: string;\n type:\n | 'jsx-text'\n | 'jsx-attribute'\n | 'string-literal'\n | 'jsx-insertion'\n | 'jsx-text-combined'\n | 'template-literal';\n componentKey: string;\n childrenToReplace?: t.Node[];\n variables?: string[];\n};\n\n// CJS/ESM interop: @babel/traverse exports its function as `.default` in CJS bundles\nconst traverse = (\n typeof _traverse === 'function' ? _traverse : (_traverse as any).default\n) as typeof _traverse;\n\n/**\n * Handles JSX insertions (elements with multiple children, including expressions).\n * Replaces complex JSX structures with variable-based translations.\n */\nexport const handleJsxInsertionBabel = (\n path: NodePath<t.JSXElement | t.JSXFragment>,\n fileCode: string,\n existingKeys: Set<string>,\n getComponentKeyForPath: (path: NodePath) => string,\n extractedContent: Record<string, Record<string, string>>,\n replacements: BabelReplacement[],\n handledNodes: Set<t.Node>\n): boolean => {\n const children = path.node.children;\n\n if (children.length <= 1) return false;\n\n const parts: {\n type: 'text' | 'var';\n value: string;\n originalExpr?: string;\n }[] = [];\n let hasSignificantText = false;\n let hasVariables = false;\n\n for (const child of children) {\n if (t.isJSXText(child)) {\n const text = child.value;\n\n if (text.trim().length > 0) hasSignificantText = true;\n\n parts.push({ type: 'text', value: text });\n } else if (t.isJSXExpressionContainer(child)) {\n if (t.isJSXEmptyExpression(child.expression)) {\n parts.push({ type: 'text', value: '' });\n } else {\n const expr = child.expression;\n\n if (t.isIdentifier(expr)) {\n parts.push({\n type: 'var',\n value: expr.name,\n originalExpr: expr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n\n parts.push({ type: 'var', value: varName, originalExpr: code });\n\n hasVariables = true;\n } else if (t.isTemplateLiteral(expr)) {\n for (let i = 0; i < expr.quasis.length; i++) {\n parts.push({ type: 'text', value: expr.quasis[i].value.raw });\n if (i < expr.expressions.length) {\n const subExpr = expr.expressions[i];\n if (t.isIdentifier(subExpr)) {\n parts.push({\n type: 'var',\n value: subExpr.name,\n originalExpr: subExpr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(subExpr)) {\n const code = fileCode.substring(subExpr.start!, subExpr.end!);\n const varName = t.isIdentifier(subExpr.property)\n ? subExpr.property.name\n : 'var';\n parts.push({ type: 'var', value: varName, originalExpr: code });\n hasVariables = true;\n } else {\n return false;\n }\n }\n }\n } else {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n\n if (!hasSignificantText) return false;\n\n let combinedString = '';\n for (const part of parts) {\n if (part.type === 'var') combinedString += `{{${part.value}}}`;\n else combinedString += part.value;\n }\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (shouldExtract(cleanString)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const varMap = parts\n .filter((part) => part.type === 'var')\n .map((part) => `${part.value}: ${part.originalExpr}`);\n const uniqueVars = Array.from(new Set(varMap));\n\n if (hasVariables) {\n replacements.push({\n path,\n key,\n type: 'jsx-insertion',\n componentKey,\n childrenToReplace: children,\n variables: uniqueVars,\n });\n } else {\n replacements.push({\n path,\n key,\n type: 'jsx-text-combined',\n componentKey,\n childrenToReplace: children,\n });\n }\n\n children.forEach((child) => {\n handledNodes.add(child);\n });\n return true;\n }\n\n return false;\n};\n\n/**\n * Traverses the AST to identify components and extract content.\n * Returns extraction results and metadata about which components need Intlayer hooks.\n */\nexport const extractBabelContentForComponents = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n defaultKey: string = 'default',\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, Record<string, string>>;\n replacements: BabelReplacement[];\n componentsNeedingHooks: Set<NodePath>;\n componentKeyMap: Map<t.Node, string>;\n componentPaths: NodePath[];\n hookMap: Map<t.Node, 'useIntlayer' | 'getIntlayer'>;\n isSolid: boolean;\n} => {\n const extractedContent: Record<string, Record<string, string>> = {};\n const replacements: BabelReplacement[] = [];\n const handledNodes = new Set<t.Node>();\n const componentKeyMap = new Map<t.Node, string>();\n const hookMap = new Map<t.Node, 'useIntlayer' | 'getIntlayer'>();\n const usedKeysInFile = new Set<string>();\n let globalFileKey: string | undefined;\n\n const componentPaths: NodePath[] = [];\n\n traverse(ast, {\n Program(path) {\n componentPaths.push(path);\n },\n FunctionDeclaration(path) {\n componentPaths.push(path);\n },\n ArrowFunctionExpression(path) {\n componentPaths.push(path);\n },\n FunctionExpression(path) {\n componentPaths.push(path);\n },\n });\n\n // Pre-scan non-Program paths to collect their existing dictionary keys before the\n // Program scope is assigned. Without this, Program is processed first (depth-first\n // traversal) and creates a new file-path-derived key even when a child component\n // already declares a specific dictionary (e.g. useIntlayer('dashboard-sidebar')).\n for (const path of componentPaths) {\n if (path.isProgram()) continue;\n const existingInfo = getExistingIntlayerInfo(path);\n if (existingInfo) {\n usedKeysInFile.add(existingInfo.key);\n }\n }\n\n for (const path of componentPaths) {\n const existingInfo = getExistingIntlayerInfo(path);\n\n if (existingInfo) {\n componentKeyMap.set(path.node, existingInfo.key);\n usedKeysInFile.add(existingInfo.key);\n hookMap.set(path.node, existingInfo.hook);\n } else {\n if (path.isProgram()) {\n if (!globalFileKey) {\n // Reuse the dominant existing key from child components so that\n // module-level strings join the same dictionary rather than\n // creating a new file-path-derived one (e.g. 'route').\n const dominantKey =\n usedKeysInFile.size > 0 ? [...usedKeysInFile][0] : undefined;\n if (dominantKey) {\n globalFileKey = dominantKey;\n } else {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n }\n componentKeyMap.set(path.node, globalFileKey);\n hookMap.set(path.node, 'getIntlayer');\n } else {\n let inheritedKey: string | undefined;\n let parent: NodePath | null = path.parentPath;\n while (parent) {\n if (componentKeyMap.has(parent.node)) {\n inheritedKey = componentKeyMap.get(parent.node);\n break;\n }\n parent = parent.parentPath;\n }\n\n if (!inheritedKey) {\n if (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n inheritedKey = globalFileKey;\n }\n\n componentKeyMap.set(path.node, inheritedKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n const isHook = compName ? /^use[A-Z]/.test(compName) : false;\n hookMap.set(\n path.node,\n isComponent || isHook ? 'useIntlayer' : 'getIntlayer'\n );\n }\n }\n }\n\n const getComponentKeyForPath = (path: NodePath): string => {\n let current: NodePath | null = path;\n while (current) {\n if (componentKeyMap.has(current.node)) {\n return componentKeyMap.get(current.node)!;\n }\n current = current.parentPath;\n }\n return globalFileKey || defaultKey;\n };\n\n traverse(ast, {\n JSXElement(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXFragment(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXText(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (shouldExtract(text)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.replace(/\\s+/g, ' ').trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-text', componentKey });\n }\n },\n JSXAttribute(path) {\n if (handledNodes.has(path.node)) return;\n\n const name = path.node.name.name;\n\n if (\n typeof name !== 'string' ||\n !ATTRIBUTES_TO_EXTRACT.includes(name as any)\n )\n return;\n const value = path.node.value;\n\n if (t.isStringLiteral(value) && shouldExtract(value.value)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n value.value.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-attribute', componentKey });\n }\n },\n StringLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (!shouldExtract(text)) return;\n\n const parent = path.parentPath;\n\n if (\n parent.isImportDeclaration() ||\n parent.isImportSpecifier() ||\n parent.isExportDeclaration()\n )\n return;\n\n if (parent.isJSXAttribute()) return;\n\n if (\n parent.isCallExpression() &&\n t.isMemberExpression(parent.node.callee)\n ) {\n if (\n t.isIdentifier(parent.node.callee.object) &&\n parent.node.callee.object.name === 'console' &&\n t.isIdentifier(parent.node.callee.property) &&\n parent.node.callee.property.name === 'log'\n ) {\n return;\n }\n }\n\n if (parent.isObjectProperty() && parent.node.key === path.node) return;\n\n // Skip string values in known technical/non-translatable object properties (e.g. `icon: 'Globe'`).\n // String values in translatable object properties (e.g. `label: 'Language'`) are still extracted.\n const TECHNICAL_KEYS = new Set([\n 'icon',\n 'className',\n 'class',\n 'id',\n 'type',\n 'variant',\n 'color',\n 'theme',\n 'size',\n 'align',\n 'placement',\n 'target',\n 'rel',\n 'method',\n 'mode',\n 'direction',\n 'orientation',\n 'scope',\n 'role',\n 'lang',\n 'locale',\n 'href',\n 'src',\n 'width',\n 'height',\n 'as',\n 'to',\n 'key',\n 'value',\n 'defaultValue',\n 'prop',\n 'property',\n 'state',\n 'action',\n 'event',\n 'handler',\n 'callback',\n 'url',\n 'uri',\n 'path',\n 'route',\n 'slug',\n 'endpoint',\n 'headers',\n 'contentType',\n ]);\n if (\n parent.isObjectProperty() &&\n t.isIdentifier(parent.node.key) &&\n TECHNICAL_KEYS.has(parent.node.key.name)\n ) {\n return;\n }\n\n if (parent.isMemberExpression() && parent.node.property === path.node)\n return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'string-literal', componentKey });\n },\n TemplateLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const { quasis, expressions } = path.node;\n\n // Build the combined string with placeholders\n let combinedString = '';\n const variables: string[] = [];\n let hasSignificantText = false;\n\n for (let i = 0; i < quasis.length; i++) {\n const text = quasis[i].value.raw;\n combinedString += text;\n if (text.trim().length > 0) hasSignificantText = true;\n\n if (i < expressions.length) {\n const expr = expressions[i];\n if (t.isIdentifier(expr)) {\n combinedString += `{{${expr.name}}}`;\n variables.push(`${expr.name}: ${expr.name}`);\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n combinedString += `{{${varName}}}`;\n variables.push(`${varName}: ${code}`);\n } else {\n // Complex expression in template literal, skip\n return;\n }\n }\n }\n\n if (!hasSignificantText) return;\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (!shouldExtract(cleanString)) return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const uniqueVars = Array.from(new Set(variables));\n\n replacements.push({\n path,\n key,\n type: 'template-literal',\n componentKey,\n variables: uniqueVars,\n });\n },\n });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\n if (componentPath.isProgram()) {\n const hasDirectReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) {\n return true;\n }\n const isOtherComponent = componentPaths.some(\n (p) => p !== componentPath && p.node === current?.node\n );\n if (isOtherComponent) {\n return false;\n }\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasDirectReplacements) {\n componentsNeedingHooks.add(componentPath);\n }\n continue;\n }\n\n const hasReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) return true;\n\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasReplacements) {\n const key = componentKeyMap.get(componentPath.node)!;\n let ancestorProvidesKey = false;\n let currentPath: NodePath | null = componentPath.parentPath;\n while (currentPath) {\n const ancestorPath = componentPaths.find(\n (path) => path.node === currentPath?.node\n );\n\n if (ancestorPath && !ancestorPath.isProgram()) {\n const ancestorKey = componentKeyMap.get(ancestorPath.node);\n\n if (ancestorKey === key) {\n const ancestorHasReplacements = replacements.some((replacement) => {\n let rPath: NodePath | null = replacement.path;\n while (rPath) {\n if (rPath.node === ancestorPath.node) return true;\n\n rPath = rPath.parentPath;\n }\n return false;\n });\n const existingInfo = getExistingIntlayerInfo(ancestorPath);\n\n if (ancestorHasReplacements || existingInfo) {\n ancestorProvidesKey = true;\n break;\n }\n }\n }\n currentPath = currentPath.parentPath;\n }\n\n if (!ancestorProvidesKey) {\n componentsNeedingHooks.add(componentPath);\n }\n }\n }\n\n return {\n extractedContent,\n replacements,\n componentsNeedingHooks,\n componentKeyMap,\n componentPaths,\n hookMap,\n isSolid: false,\n };\n};\n\n/**\n * High-level function to extract content from TS/JS/JSX/TSX AST.\n */\nexport const extractTsContent = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, string>;\n replacements: BabelReplacement[];\n} => {\n const { extractedContent, replacements } = extractBabelContentForComponents(\n ast,\n fileCode,\n existingKeys,\n 'default',\n configuration,\n filePath,\n unmergedDictionaries\n );\n\n const flatContent: Record<string, string> = {};\n for (const group of Object.values(extractedContent)) {\n Object.assign(flatContent, group);\n }\n\n return { extractedContent: flatContent, replacements };\n};\n"],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ const shouldExtract = (text) => {
|
|
|
16
16
|
if (trimmed.includes("=>") || trimmed.includes(");") || trimmed.includes("(){") || trimmed.includes("==") || trimmed.includes("window.") || trimmed.startsWith("(function") || trimmed.startsWith("function(")) return false;
|
|
17
17
|
if ((trimmed.match(/[^\p{L}\p{N}\s.,!?;:'"()[\]{}–—/«»„“\p{Sc}%&*+#@^_+=<>/~]/gu) || []).length > 5) return false;
|
|
18
18
|
const wordCount = trimmed.split(/\s+/).length;
|
|
19
|
-
const cssClassTokenRegex = /^!?([a-z][a-z0-9]*:)*[a-z][a-z0-9]*(-[a-z0-9[\].,%#/]+)*(\/[a-z0-9]+)?$/;
|
|
19
|
+
const cssClassTokenRegex = /^!?([a-z][a-z0-9-]*:)*[a-z][a-z0-9]*(-[a-z0-9[\].,%#/]+)*(\/[a-z0-9]+)?$/;
|
|
20
20
|
if (wordCount > 1) {
|
|
21
21
|
const tokens = trimmed.split(/\s+/);
|
|
22
22
|
if (tokens.every((token) => cssClassTokenRegex.test(token)) && tokens.some((token) => token.includes("-"))) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shouldExtract.mjs","names":[],"sources":["../../../../src/extractContent/utils/shouldExtract.ts"],"sourcesContent":["/**\n * Checks whether the given text should be extracted as a translatable string.\n *\n * Filters out:\n * - Empty strings\n * - Emails\n * - Uncapitalized strings of 2 words or fewer (likely technical terms)\n * - Dynamic content patterns like Vue bindings (`v-`) or object patterns (`{`)\n */\nexport const shouldExtract = (text: string): boolean => {\n const trimmed = text.trim();\n\n if (!trimmed) return false;\n\n // Ignore emails\n if (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) return false;\n\n // Ignore dynamic content patterns\n if (trimmed.startsWith('{') || trimmed.startsWith('v-')) return false;\n\n // Ignore explicit code patterns (markers)\n if (\n trimmed.includes('=>') ||\n trimmed.includes(');') ||\n trimmed.includes('(){') ||\n trimmed.includes('==') ||\n trimmed.includes('window.') ||\n trimmed.startsWith('(function') ||\n trimmed.startsWith('function(')\n ) {\n return false;\n }\n\n // Heuristic: check for characters that are common in code but rare in natural text.\n // Whitelist: letters, numbers, spaces, and frequent text symbols (including punctuation, braces, and technical symbols)\n const nonTextualRegex =\n /[^\\p{L}\\p{N}\\s.,!?;:'\"()[\\]{}–—/«»„“\\p{Sc}%&*+#@^_+=<>/~]/gu;\n const nonTextualMatches = trimmed.match(nonTextualRegex) || [];\n\n // If a string contains a high density of truly exceptional symbols (like |, \\, etc.),\n // it is highly likely to be code or complex technical data.\n if (nonTextualMatches.length > 5) return false;\n\n const wordCount = trimmed.split(/\\s+/).length;\n\n // Ignore CSS/Tailwind utility class strings. A string whose tokens all look\n // like CSS utility classes (lowercase, optional responsive/state prefix like\n // \"sm:\" or \"hover:\", optional hyphenated suffix like \"-4\" or \"-full\") and\n // where at least one token contains a hyphen is almost certainly a className\n // value, not translatable text.\n const cssClassTokenRegex =\n /^!?([a-z][a-z0-9]*:)*[a-z][a-z0-9]*(-[a-z0-9[\\].,%#/]+)*(\\/[a-z0-9]+)?$/;\n if (wordCount > 1) {\n const tokens = trimmed.split(/\\s+/);\n if (\n tokens.every((token) => cssClassTokenRegex.test(token)) &&\n tokens.some((token) => token.includes('-'))\n ) {\n return false;\n }\n }\n\n // Check if starts with a capital letter (including after an opening parenthesis/quote)\n const isCapitalized = /^['\"([]*\\p{Lu}/u.test(trimmed);\n\n // Ignore technical identifiers (one word strings with camelCase, kebab-case, snake_case etc.)\n if (wordCount === 1) {\n // CamelCase or internal capitals (like camelCaseProperty or CamelCaseProperty)\n if (/[a-z]\\p{Lu}/u.test(trimmed)) return false;\n // kebab-case or snake_case\n if (trimmed.includes('-') || trimmed.includes('_')) return false;\n }\n\n // We usually want to extract full sentences or labels, not single/short technical words.\n // Extract if capitalized, or if it contains more than 2 words.\n if (!isCapitalized && wordCount <= 2) return false;\n\n return true;\n};\n"],"mappings":";;;;;;;;;;AASA,MAAa,iBAAiB,SAA0B;CACtD,MAAM,UAAU,KAAK,KAAK;CAE1B,IAAI,CAAC,SAAS,OAAO;CAGrB,IAAI,6BAA6B,KAAK,OAAO,GAAG,OAAO;CAGvD,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,IAAI,GAAG,OAAO;CAGhE,IACE,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,SAAS,KAC1B,QAAQ,WAAW,WAAW,KAC9B,QAAQ,WAAW,WAAW,GAE9B,OAAO;CAWT,KAJ0B,QAAQ,MAAM,6DAAe,KAAK,CAAC,GAIvC,SAAS,GAAG,OAAO;CAEzC,MAAM,YAAY,QAAQ,MAAM,KAAK,EAAE;CAOvC,MAAM,qBACJ;CACF,IAAI,YAAY,GAAG;EACjB,MAAM,SAAS,QAAQ,MAAM,KAAK;EAClC,IACE,OAAO,OAAO,UAAU,mBAAmB,KAAK,KAAK,CAAC,KACtD,OAAO,MAAM,UAAU,MAAM,SAAS,GAAG,CAAC,GAE1C,OAAO;CAEX;CAGA,MAAM,gBAAgB,kBAAkB,KAAK,OAAO;CAGpD,IAAI,cAAc,GAAG;EAEnB,IAAI,eAAe,KAAK,OAAO,GAAG,OAAO;EAEzC,IAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG,OAAO;CAC7D;CAIA,IAAI,CAAC,iBAAiB,aAAa,GAAG,OAAO;CAE7C,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"shouldExtract.mjs","names":[],"sources":["../../../../src/extractContent/utils/shouldExtract.ts"],"sourcesContent":["/**\n * Checks whether the given text should be extracted as a translatable string.\n *\n * Filters out:\n * - Empty strings\n * - Emails\n * - Uncapitalized strings of 2 words or fewer (likely technical terms)\n * - Dynamic content patterns like Vue bindings (`v-`) or object patterns (`{`)\n */\nexport const shouldExtract = (text: string): boolean => {\n const trimmed = text.trim();\n\n if (!trimmed) return false;\n\n // Ignore emails\n if (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(trimmed)) return false;\n\n // Ignore dynamic content patterns\n if (trimmed.startsWith('{') || trimmed.startsWith('v-')) return false;\n\n // Ignore explicit code patterns (markers)\n if (\n trimmed.includes('=>') ||\n trimmed.includes(');') ||\n trimmed.includes('(){') ||\n trimmed.includes('==') ||\n trimmed.includes('window.') ||\n trimmed.startsWith('(function') ||\n trimmed.startsWith('function(')\n ) {\n return false;\n }\n\n // Heuristic: check for characters that are common in code but rare in natural text.\n // Whitelist: letters, numbers, spaces, and frequent text symbols (including punctuation, braces, and technical symbols)\n const nonTextualRegex =\n /[^\\p{L}\\p{N}\\s.,!?;:'\"()[\\]{}–—/«»„“\\p{Sc}%&*+#@^_+=<>/~]/gu;\n const nonTextualMatches = trimmed.match(nonTextualRegex) || [];\n\n // If a string contains a high density of truly exceptional symbols (like |, \\, etc.),\n // it is highly likely to be code or complex technical data.\n if (nonTextualMatches.length > 5) return false;\n\n const wordCount = trimmed.split(/\\s+/).length;\n\n // Ignore CSS/Tailwind utility class strings. A string whose tokens all look\n // like CSS utility classes (lowercase, optional responsive/state prefix like\n // \"sm:\" or \"hover:\", optional hyphenated suffix like \"-4\" or \"-full\") and\n // where at least one token contains a hyphen is almost certainly a className\n // value, not translatable text.\n const cssClassTokenRegex =\n /^!?([a-z][a-z0-9-]*:)*[a-z][a-z0-9]*(-[a-z0-9[\\].,%#/]+)*(\\/[a-z0-9]+)?$/;\n if (wordCount > 1) {\n const tokens = trimmed.split(/\\s+/);\n if (\n tokens.every((token) => cssClassTokenRegex.test(token)) &&\n tokens.some((token) => token.includes('-'))\n ) {\n return false;\n }\n }\n\n // Check if starts with a capital letter (including after an opening parenthesis/quote)\n const isCapitalized = /^['\"([]*\\p{Lu}/u.test(trimmed);\n\n // Ignore technical identifiers (one word strings with camelCase, kebab-case, snake_case etc.)\n if (wordCount === 1) {\n // CamelCase or internal capitals (like camelCaseProperty or CamelCaseProperty)\n if (/[a-z]\\p{Lu}/u.test(trimmed)) return false;\n // kebab-case or snake_case\n if (trimmed.includes('-') || trimmed.includes('_')) return false;\n }\n\n // We usually want to extract full sentences or labels, not single/short technical words.\n // Extract if capitalized, or if it contains more than 2 words.\n if (!isCapitalized && wordCount <= 2) return false;\n\n return true;\n};\n"],"mappings":";;;;;;;;;;AASA,MAAa,iBAAiB,SAA0B;CACtD,MAAM,UAAU,KAAK,KAAK;CAE1B,IAAI,CAAC,SAAS,OAAO;CAGrB,IAAI,6BAA6B,KAAK,OAAO,GAAG,OAAO;CAGvD,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,IAAI,GAAG,OAAO;CAGhE,IACE,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,IAAI,KACrB,QAAQ,SAAS,SAAS,KAC1B,QAAQ,WAAW,WAAW,KAC9B,QAAQ,WAAW,WAAW,GAE9B,OAAO;CAWT,KAJ0B,QAAQ,MAAM,6DAAe,KAAK,CAAC,GAIvC,SAAS,GAAG,OAAO;CAEzC,MAAM,YAAY,QAAQ,MAAM,KAAK,EAAE;CAOvC,MAAM,qBACJ;CACF,IAAI,YAAY,GAAG;EACjB,MAAM,SAAS,QAAQ,MAAM,KAAK;EAClC,IACE,OAAO,OAAO,UAAU,mBAAmB,KAAK,KAAK,CAAC,KACtD,OAAO,MAAM,UAAU,MAAM,SAAS,GAAG,CAAC,GAE1C,OAAO;CAEX;CAGA,MAAM,gBAAgB,kBAAkB,KAAK,OAAO;CAGpD,IAAI,cAAc,GAAG;EAEnB,IAAI,eAAe,KAAK,OAAO,GAAG,OAAO;EAEzC,IAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG,OAAO;CAC7D;CAIA,IAAI,CAAC,iBAAiB,aAAa,GAAG,OAAO;CAE7C,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"babelProcessor.d.ts","names":[],"sources":["../../../src/extractContent/babelProcessor.ts"],"mappings":";;;;;KAYY,gBAAA;EACV,IAAA,EAAM,QAAA;EACN,GAAA;EACA,IAAA;EAOA,YAAA;EACA,iBAAA,GAAoB,CAAA,CAAE,IAAI;EAC1B,SAAA;AAAA;;;;;cAYW,uBAAA,GACX,IAAA,EAAM,QAAA,CAAS,CAAA,CAAE,UAAA,GAAa,CAAA,CAAE,WAAA,GAChC,QAAA,UACA,YAAA,EAAc,GAAA,UACd,sBAAA,GAAyB,IAAA,EAAM,QAAA,aAC/B,gBAAA,EAAkB,MAAA,SAAe,MAAA,mBACjC,YAAA,EAAc,gBAAA,IACd,YAAA,EAAc,GAAA,CAAI,CAAA,CAAE,IAAA;;;;AAnBX;cAwJE,gCAAA,GACX,GAAA,EAAK,CAAA,CAAE,IAAA,EACP,QAAA,UACA,YAAA,EAAc,GAAA,UACd,UAAA,UACA,aAAA,EAAe,cAAA,EACf,QAAA,UACA,oBAAA,GAAsB,MAAA;EAEtB,gBAAA,EAAkB,MAAA,SAAe,MAAA;EACjC,YAAA,EAAc,gBAAA;EACd,sBAAA,EAAwB,GAAA,CAAI,QAAA;EAC5B,eAAA,EAAiB,GAAA,CAAI,CAAA,CAAE,IAAA;EACvB,cAAA,EAAgB,QAAA;EAChB,OAAA,EAAS,GAAA,CAAI,CAAA,CAAE,IAAA;EACf,OAAA;AAAA;;;;
|
|
1
|
+
{"version":3,"file":"babelProcessor.d.ts","names":[],"sources":["../../../src/extractContent/babelProcessor.ts"],"mappings":";;;;;KAYY,gBAAA;EACV,IAAA,EAAM,QAAA;EACN,GAAA;EACA,IAAA;EAOA,YAAA;EACA,iBAAA,GAAoB,CAAA,CAAE,IAAI;EAC1B,SAAA;AAAA;;;;;cAYW,uBAAA,GACX,IAAA,EAAM,QAAA,CAAS,CAAA,CAAE,UAAA,GAAa,CAAA,CAAE,WAAA,GAChC,QAAA,UACA,YAAA,EAAc,GAAA,UACd,sBAAA,GAAyB,IAAA,EAAM,QAAA,aAC/B,gBAAA,EAAkB,MAAA,SAAe,MAAA,mBACjC,YAAA,EAAc,gBAAA,IACd,YAAA,EAAc,GAAA,CAAI,CAAA,CAAE,IAAA;;;;AAnBX;cAwJE,gCAAA,GACX,GAAA,EAAK,CAAA,CAAE,IAAA,EACP,QAAA,UACA,YAAA,EAAc,GAAA,UACd,UAAA,UACA,aAAA,EAAe,cAAA,EACf,QAAA,UACA,oBAAA,GAAsB,MAAA;EAEtB,gBAAA,EAAkB,MAAA,SAAe,MAAA;EACjC,YAAA,EAAc,gBAAA;EACd,sBAAA,EAAwB,GAAA,CAAI,QAAA;EAC5B,eAAA,EAAiB,GAAA,CAAI,CAAA,CAAE,IAAA;EACvB,cAAA,EAAgB,QAAA;EAChB,OAAA,EAAS,GAAA,CAAI,CAAA,CAAE,IAAA;EACf,OAAA;AAAA;;;;cAobW,gBAAA,GACX,GAAA,EAAK,CAAA,CAAE,IAAA,EACP,QAAA,UACA,YAAA,EAAc,GAAA,UACd,aAAA,EAAe,cAAA,EACf,QAAA,UACA,oBAAA,GAAsB,MAAA;EAEtB,gBAAA,EAAkB,MAAA;EAClB,YAAA,EAAc,gBAAA;AAAA"}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Example: "src/components/MyComponent/index.tsx" -> "comp-my-component"
|
|
6
6
|
*/
|
|
7
|
-
declare const extractDictionaryKeyFromPath: (filePath: string, prefix?:
|
|
8
|
-
declare const extractDictionaryKey: (filePath: string, fileText: string, prefix?:
|
|
7
|
+
declare const extractDictionaryKeyFromPath: (filePath: string, prefix?: any) => string;
|
|
8
|
+
declare const extractDictionaryKey: (filePath: string, fileText: string, prefix?: any) => string;
|
|
9
9
|
//#endregion
|
|
10
10
|
export { extractDictionaryKey, extractDictionaryKeyFromPath };
|
|
11
11
|
//# sourceMappingURL=extractDictionaryKey.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/babel",
|
|
3
|
-
"version": "8.10.
|
|
3
|
+
"version": "8.10.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A Babel plugin for Intlayer that transforms declaration files and provides internationalization features during the build process according to the Intlayer configuration.",
|
|
6
6
|
"keywords": [
|
|
@@ -81,12 +81,12 @@
|
|
|
81
81
|
"@babel/plugin-syntax-jsx": "7.28.6",
|
|
82
82
|
"@babel/traverse": "7.29.0",
|
|
83
83
|
"@babel/types": "7.29.0",
|
|
84
|
-
"@intlayer/chokidar": "8.10.
|
|
85
|
-
"@intlayer/config": "8.10.
|
|
86
|
-
"@intlayer/core": "8.10.
|
|
87
|
-
"@intlayer/dictionaries-entry": "8.10.
|
|
88
|
-
"@intlayer/types": "8.10.
|
|
89
|
-
"@intlayer/unmerged-dictionaries-entry": "8.10.
|
|
84
|
+
"@intlayer/chokidar": "8.10.1",
|
|
85
|
+
"@intlayer/config": "8.10.1",
|
|
86
|
+
"@intlayer/core": "8.10.1",
|
|
87
|
+
"@intlayer/dictionaries-entry": "8.10.1",
|
|
88
|
+
"@intlayer/types": "8.10.1",
|
|
89
|
+
"@intlayer/unmerged-dictionaries-entry": "8.10.1",
|
|
90
90
|
"@types/babel__core": "7.20.5",
|
|
91
91
|
"@types/babel__generator": "7.27.0",
|
|
92
92
|
"@types/babel__traverse": "7.28.0"
|
|
@@ -101,11 +101,11 @@
|
|
|
101
101
|
"rimraf": "6.1.3",
|
|
102
102
|
"tsdown": "0.22.00",
|
|
103
103
|
"typescript": "6.0.3",
|
|
104
|
-
"vitest": "4.1.
|
|
104
|
+
"vitest": "4.1.7"
|
|
105
105
|
},
|
|
106
106
|
"peerDependencies": {
|
|
107
|
-
"@intlayer/svelte-compiler": "8.10.
|
|
108
|
-
"@intlayer/vue-compiler": "8.10.
|
|
107
|
+
"@intlayer/svelte-compiler": "8.10.1",
|
|
108
|
+
"@intlayer/vue-compiler": "8.10.1"
|
|
109
109
|
},
|
|
110
110
|
"peerDependenciesMeta": {
|
|
111
111
|
"@intlayer/svelte-compiler": {
|