UNPKG

@jsverse/transloco-keys-manager

Version:

Extract translatable keys from projects that uses Transloco

70 lines 3.25 kB
import { ScriptKind, tsquery } from '@phenomnomnominal/tsquery'; import ts from 'typescript'; import { addScope, hasScope } from '../keys-builder/utils/scope.utils.js'; import { readFile } from './file.utils.js'; import { toCamelCase } from './string.utils.js'; import { normalizedGlob } from './normalize-glob-path.js'; const tokenProviderQuery = `ObjectLiteralExpression:has(PropertyAssignment > Identifier[name=TRANSLOCO_SCOPE]) > PropertyAssignment > Identifier[name=/useValue|useFactory/]`; const functionProviderQuery = `CallExpression > Identifier[name=provideTranslocoScope]`; function stringQueryDef(rootNode) { return (tsquery(rootNode, `StringLiteral`) // Since we are querying for StringLiteral we might pickup nested nodes from // the scope def and cause duplications, we only want direct children from the root node .filter((node) => node.parent === rootNode) .map((node) => ({ scope: node.text }))); } function objectQueryDef(rootNode) { return tsquery(rootNode, 'ObjectLiteralExpression:has(Identifier[name=scope])').map((node) => { const result = {}; for (const prop of node .properties) { if (prop.initializer) { const key = prop.name.getText(); if (key === 'scope' || key === 'alias') { result[key] = prop.initializer.getText().replace(/['"]/g, ''); } } } return result; }); } // Order is important, we check if it's an object first, then string const scopeValueQueries = [objectQueryDef, stringQueryDef]; const translocoProvider = /(TRANSLOCO_SCOPE|provideTranslocoScope)/; export function updateScopesMap({ input, files, }) { const tsFiles = files || input.map((path) => normalizedGlob(`${path}/**/*.ts`)).flat(); // Return only the new scopes (for the plugin) const aliasToScope = {}; for (const file of tsFiles) { const content = readFile(file); if (!translocoProvider.test(content)) continue; let result = []; const ast = tsquery.ast(content, undefined, ScriptKind.TS); const tokenAndProviderNodes = tsquery(ast, `${tokenProviderQuery}, ${functionProviderQuery}`); for (let node of tokenAndProviderNodes) { // :has(> child) is not supported ... So we need to use a workaround, select child and make second query for parent node = node.parent; if (ts.isCallExpression(node)) { const [providersArray] = tsquery(node, 'ArrayLiteralExpression'); if (providersArray) { result.push(...resolveScopeProvider(providersArray)); continue; } } result.push(...resolveScopeProvider(node)); } for (let { scope, alias } of result) { if (scope && !hasScope(scope)) { alias ??= toCamelCase(scope); addScope(scope, alias); aliasToScope[alias] = scope; } } } return aliasToScope; } function resolveScopeProvider(node) { return scopeValueQueries.map((resolver) => resolver(node)).flat(); } //# sourceMappingURL=update-scopes-map.js.map